Oracle Library Cache的示例分析
这篇文章主要为大家展示了“Oracle Library Cache的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Oracle Library Cache的示例分析”这篇文章吧。
Oracle Library Cache深入解析
每一个进入库缓存的对象,在库缓存中都被按照本身内容分割成多块进行存贮。Oracle这样做的目的是为了更灵活的内存管理,因为在内存寻找大块连续的内存,总比寻找小块连续内存更慢一些.如果一个库缓存对象(如一条SQL语句的执行计划),它所占的内存被切割成4个小块,它们分别被存放在库缓存的各处,并且互不相连。为了将这4个小块组合起来,Oracle另外这个库缓存对象分配一小块内存,这块内存中存有其他4个小块内存的地址,并且,还有一些有关此库缓存对象的基本信息,如名字、类型等等,这块内存就叫库缓存对象句柄(handles)。
Library Cache结构示意图如下:
在访问库缓存对象时,比如软解析时,要从库缓存中读取执行计划。Oracle首先找到句柄,读取句柄中的信息,这就叫做一次库缓存Get。如果库缓存中不包括对象的句柄信息,Oracle就要重新在库缓存中分配内存、构造句柄,这就是库缓存句柄未命中(Get Miss)。相反,如果在库缓存中找到了对象句柄,就是库缓存句柄命中(Get Hit)。硬解析时,就会发生Get Miss。而软解析则是Get Hit。
在取出句柄中的其他内存块地址后,每访问一个内存块,都叫做一次库缓存Pin。如果相应的内存块已经不在内存中了,这就是Pin Miss,Pin的未命中。相反就是Pin Hit。
当库缓存中对象发生改变后,会引起其他一些对象的无效(Invalidation)。比如,你修改了一个表的结构,那么,选择了这个表的SQL语句的执行计划就会变的无效。其实大部分对表的DDL操作,都会造成相关SQL语句执行计划的无效。就连Grant(授权)、Revoke(撤消权限)这样看来跟执行计划耗无关系的操作,都会引起无效。如果有一个表TAB1,你发布了“Grant 某权限 on tab1 to 某用户”,或“revoke 某权限 on tabl from 某用户”这样的操作,那么,所有和TAB1表有关的执行计划都将无效。无效之后,库缓存对象除句柄外的所有内存块,都将被清除。再使用到对象后,必须重新加载对象。如上例,如果你对TAB1使用了DDL语句,那么所有使用了TAB1表语句的执行计划都将无效,你再使用这些语句时,就必须重新硬解析语句。
案例:
16:54:51SCOTT@prod>select*fromdept1;DEPTNODNAMELOC-------------------------------------10ACCOUNTINGNEWYORK20RESEARCHDALLAS30SALESCHICAGO40OPERATIONSBOSTONElapsed:00:00:00.0616:54:03SYS@prod>selectNAMESPACE,GETS,PINS,RELOADS,INVALIDATIONSfromv$librarycacheNAMESPACEGETSPINSRELOADSINVALIDATIONS-------------------------------------------------------------------------SQLAREA7722301343097TABLE/PROCEDURE109068328880BODY60880100TRIGGER244100INDEX966200CLUSTER48530000QUEUE3616800APPCONTEXT141400RULESET3300SUBSCRIPTION5500EDITION589900DBLINK5000OBJECTID59000SCHEMA3584000DBINSTANCE100015rowsselected.Elapsed:00:00:00.01在访问对象dept1上,做DDL操作,导致原来的执行计划变得无效16:55:01SCOTT@prod>grantallondept1tohr;Grantsucceeded.Elapsed:00:00:00.2616:55:24SCOTT@prod>select*fromdept1;DEPTNODNAMELOC-------------------------------------10ACCOUNTINGNEWYORK20RESEARCHDALLAS30SALESCHICAGO40OPERATIONSBOSTONElapsed:00:00:00.0416:55:29SCOTT@prod>16:55:08SYS@prod>r1*selectNAMESPACE,GETS,PINS,RELOADS,INVALIDATIONSfromv$librarycacheNAMESPACEGETSPINSRELOADSINVALIDATIONS-------------------------------------------------------------------------SQLAREA77813042232100TABLE/PROCEDURE109808420880BODY62381700TRIGGER264300INDEX966200CLUSTER48830200QUEUE3616800APPCONTEXT141400RULESET3300SUBSCRIPTION5500EDITION5910100DBLINK5000OBJECTID59000SCHEMA3595000DBINSTANCE100015rowsselected.Elapsed:00:00:00.0316:55:34SYS@prod>
因此,使用DDL语句是需要注意的,如果没有要求立即使用DDL,我们最好等到数据库并不繁忙的时刻,再执行DDL。作为DBA,这一点一定要牢记,除非要求立即执行,否则等到数据库并不繁忙时再执行任何DDL。
再补充一点,无效和库缓存对象的老化并不一样。老化是连句柄带对象的所有内存块都被清除出去了。而无效是只在库缓存中保留对象句柄,但所有其他内存块都被清除出去。对于无效的对象,当再次重新调用到它时,Oracle会再次将它调入到库缓存中,这个操作被称为Reload。一般说来,Reload与Get是无关的,因为Reload是在对象无效后才发生的,而对象的无效并不影响对象句柄。好,说了这么多,下面我们来看这些值的意义。
我们已经讲述了Get、Pin与它们的命中、未命中,还有什么是Invalidation和Reload。在OLTP系统中,Get的命中率应该在90%之上。而Reload和Pin的次数的比值,应该小于1%。如果超出了这些数值范围,就说明库缓存的使用有问题。问题的原因主要有两个,没有使用绑定变量或是库缓存太小。不过Reload和Pin的比例过高,也可能是在繁忙时执行了DDL所导致的。
另外,V$librarycache的第一列是NAMESPACE,也就是名称空间。它相当于存储在库缓存中对象的类型。具体的名称空间是什么意思呢?就是对象的名字所在的范围,比如表和列的名字就不在一个范围内。也就是说表名和列名可以重复,还有用户名和表、列也不在同一范围内,用户名也可以和表、列名相同。我可以有个叫做AA的表,也可以有叫做AA的用户。这两个AA处在不同的范围内,也就明它们的名称空间不同。这就好像在北京有个电话号码是12345678,在上海也有个12345678,这两个电话号码虽然相同,但不会引起问题,因为它们在不同的范围内。这个范围,也可以说是类型。
我显示一下V$librarycache的所有行(列只有一部分):
SQL>select*fromv$librarycache;NAMESPACEGETSGETHITSGETHITRATIOPINSPINHITS------------------------------------------------------------------SQLAREA218114149.190225116120258105272TABLE/PROCEDURE2515216372.6509223926064946008BODY43604098.93990825759315537TRIGGER320251.78437516551576INDEX453128.28256070620651531CLUSTER755728.96423841123392296OBJECT00100PIPE00100JAVASOURCE00100JAVARESOURCE00100JAVADATA00100
可以看在库缓存中共有11个名称空间,我们基本上可以说库缓存中有11种类型的信息。有一个非常重要的指标,就是库缓存命中率,这个命中率就是库缓存中所有对象的GETHITRAIO,它的计算方法如下:
select 1-sum(gethits)/sum(gets) fromv$librarycache;
这个比率应该在90%以上。
还有一个比率也很重要,就是Reload和Pin的比值,这个比值应该小于1%。
如果没有达到这些比例,解决方法很简单,问题或者是SQL语句没有共享,或者是共享池太小。
有关库缓存命中率,也可以查看STATSPACK报告中的Library Hit %项。这个我们上面已经说过了。
Library cache lock、Library cache pin等待事件
等待事件在Oracle中无处不在,为了记录这些数据,是损失了一些性能。但是你是想出了问题一筹莫展好,还是可以利用等待事件或各种资料轻松的查找出问题在哪好呢?而且,这些等待事件和资源你即使不去用它,Oracle一样会消耗CPU去记载它们。因此,一个好的DBA一定要对各种等待事件、资料了如指掌。下面,我们介绍两个和库缓存相关的等待事件,如题,就是Library cache lock和Library cache pin。
我们上面说到库缓存中的对象在库缓存中被切割成多个内存块,另有一个对象句柄记录了各个内存块的地址和其他的一些信息。当你要修改句柄中的信息时,需要在句柄上加独占锁,而如果另一个进程恰好在这时要求读、写句柄中的信息,它就必须等待。此时的等待就被Oracle记入Library cache lock事件。而读、写对象内存块也是无法同时进行的,有人如果正在写,你的读操作就必须等待,读写内存块的等待事件就是Library cache pin。如果这两个等待事件过多,同样说明了库缓存过小或没有共享执行计划。或者,当你在数据库繁忙时使用DDL时,也会有这两个等待事件。
案例1:业务运行前:17:07:30SYS@prod>selectname,GETS,MISSESfromv$latchwhereupper(name)like'%LIBRARY%'ORupper(name)like'%SHARE%';NAMEGETSMISSES------------------------------------------------------------------------------------testsharednon-parentl000ksxpsharedlatch00kcfisstatssharedlatch00sharedpool12667661librarycacheloadlock00sharedpoolsimulator65760sharedpoolsimalloc450SharedB-Tree3020sharedserverconfiguration60sharedserverinfo10运行业务:17:08:34SCOTT@prod>begin17:08:382foriin1..100000loop17:08:523executeimmediate'insertintot1values('||i||')';17:09:184endloop;17:09:265end;17:09:276/PL/SQLproceduresuccessfullycompleted.业务运行后:17:11:05SYS@prod>selectname,GETS,MISSESfromv$latchwhereupper(name)like'%LIBRARY%'ORupper(name)like'%SHARE%'NAMEGETSMISSES------------------------------------------------------------------------------------testsharednon-parentl000ksxpsharedlatch00kcfisstatssharedlatch00sharedpool4526672214librarycacheloadlock00sharedpoolsimulator10864370sharedpoolsimalloc20480SharedB-Tree3160sharedserverconfiguration60sharedserverinfo1010rowsselected.17:15:42SYS@prod>selectsid,event,WAIT_TIME,statefromv$session_waitwheresid=42SIDEVENTWAIT_TIMESTATE-------------------------------------------------------------------------------------------------------42latch:sharedpool-1WAITEDSHORTTIMEElapsed:00:00:00.08案例2:业务运行前:17:18:35SYS@prod>selectsid,EVENT,TOTAL_WAITS,AVERAGE_WAITfromv$session_eventwheresidin(42,46);SIDEVENTTOTAL_WAITSAVERAGE_WAIT-------------------------------------------------------------------------------------------------42DiskfileoperationsI/O4.0342logfileswitch(privatestrandflushincomplete)110.0342logfilesync41.7642dbfilesequentialread385.2342latch:rowcacheobjects5.4442latch:sharedpool194.2542SQL*Netmessagetoclient24042SQL*Netmessagefromclient235318.942SQL*Netbreak/resettoclient2.0842eventsinwaitclassOther1046DiskfileoperationsI/O1.0346dbfilesequentialread33.0246SQL*Netmessagetoclient13046SQL*Netmessagefromclient1279.914rowsselected.运行业务:17:16:39SYS@prod>selectsid,usernamefromv$sessionwhereusernameisnotnull;SIDUSERNAME----------------------------------------1SYS42SCOTT46HR17:17:22SCOTT@prod>begin17:20:462foriin1..100000loop17:20:523executeimmediate'insertintot1values('||i||')';17:20:584endloop;17:21:025end;17:21:056/PL/SQLproceduresuccessfullycompleted.17:17:42HR@prod>begin17:21:162foriin1..100000loop17:21:243executeimmediate'insertintoscott.t1values('||i||')';17:21:494endloop;17:21:515end;17:21:526/PL/SQLproceduresuccessfullycompleted.业务运行后:17:22:32SYS@prod>selectsid,EVENT,TOTAL_WAITS,AVERAGE_WAITfromv$session_eventwheresidin(42,46);SIDEVENTTOTAL_WAITSAVERAGE_WAIT-------------------------------------------------------------------------------------------------42DiskfileoperationsI/O4.0342latch:cachebufferschains16.1842bufferbusywaits2.1542logfileswitch(privatestrandflushincomplete)110.0342logfilesync41.7642dbfilesequentialread413.2142latch:rowcacheobjects58.1342latch:sharedpool1008.1942librarycache:mutexX123.3342SQL*Netmessagetoclient24042SQL*Netmessagefromclient246044.4342SQL*Netbreak/resettoclient2.0842eventsinwaitclassOther87.0946DiskfileoperationsI/O3.0346latch:cachebufferschains13.2146bufferbusywaits1.3546latch:redocopy11.26SIDEVENTTOTAL_WAITSAVERAGE_WAIT-------------------------------------------------------------------------------------------------46dbfilesequentialread38.0246enq:HW-contention1.0146latch:rowcacheobjects58.1446rowcachelock1.0846latch:sharedpool666.1746librarycache:mutexX99.2946SQL*Netmessagetoclient13046SQL*Netmessagefromclient132010.6346eventsinwaitclassOther68.1426rowsselected.Elapsed:00:00:00.3717:22:42SYS@prod>17:22:02SYS@prod>selectsid,event,WAIT_TIME,statefromv$session_waitwheresid=4217:22:252orsid=46;SIDEVENTWAIT_TIMESTATE-------------------------------------------------------------------------------------------------------42latch:sharedpool-1WAITEDSHORTTIME46latch:sharedpool-1WAITEDSHORTTIME
以上是“Oracle Library Cache的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。