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:51 SCOTT@ prod>select * from dept1; DEPTNO DNAME LOC---------- -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTONElapsed: 00:00:00.0616:54:03 SYS@ prod> select NAMESPACE,GETS,PINS,RELOADS,INVALIDATIONS from v$librarycacheNAMESPACE GETS PINS RELOADS INVALIDATIONS------------------------------ ---------- ---------- ---------- -------------SQL AREA 7722 30134 30 97TABLE/PROCEDURE 10906 8328 88 0BODY 608 801 0 0TRIGGER 24 41 0 0INDEX 96 62 0 0CLUSTER 485 300 0 0QUEUE 36 168 0 0APP CONTEXT 14 14 0 0RULESET 3 3 0 0SUBSCRIPTION 5 5 0 0EDITION 58 99 0 0DBLINK 5 0 0 0OBJECT ID 59 0 0 0SCHEMA 3584 0 0 0DBINSTANCE 1 0 0 015 rows selected.Elapsed: 00:00:00.01在访问对象dept1上,做DDL操作,导致原来的执行计划变得无效16:55:01 SCOTT@ prod>grant all on dept1 to hr;Grant succeeded.Elapsed: 00:00:00.2616:55:24 SCOTT@ prod>select * from dept1; DEPTNO DNAME LOC---------- -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTONElapsed: 00:00:00.0416:55:29 SCOTT@ prod>16:55:08 SYS@ prod>r 1* select NAMESPACE,GETS,PINS,RELOADS,INVALIDATIONS from v$librarycacheNAMESPACE GETS PINS RELOADS INVALIDATIONS------------------------------ ---------- ---------- ---------- -------------SQL AREA 7781 30422 32 100TABLE/PROCEDURE 10980 8420 88 0BODY 623 817 0 0TRIGGER 26 43 0 0INDEX 96 62 0 0CLUSTER 488 302 0 0QUEUE 36 168 0 0APP CONTEXT 14 14 0 0RULESET 3 3 0 0SUBSCRIPTION 5 5 0 0EDITION 59 101 0 0DBLINK 5 0 0 0OBJECT ID 59 0 0 0SCHEMA 3595 0 0 0DBINSTANCE 1 0 0 015 rows selected.Elapsed: 00:00:00.0316:55:34 SYS@ 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 * from v$librarycache;NAMESPACE GETS GETHITS GETHITRATIO PINS PINHITS--------------- ---------- --------------------- ---------- ----------SQL AREA 21811 4149 .190225116 120258 105272TABLE/PROCEDURE 25152 16372 .650922392 60649 46008BODY 4360 4098 .939908257 5931 5537TRIGGER 320 251 .784375 1655 1576INDEX 453 128 .282560706 2065 1531CLUSTER 755 728 .964238411 2339 2296OBJECT 0 0 1 0 0PIPE 0 0 1 0 0JAVA SOURCE 0 0 1 0 0JAVA RESOURCE 0 0 1 0 0JAVA DATA 0 0 1 0 0
可以看在库缓存中共有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:30 SYS@ prod>select name,GETS,MISSES from v$latch where upper(name) like '%LIBRARY%' OR upper(name) like '%SHARE%';NAME GETS MISSES---------------------------------------------------------------- ---------- ----------test shared non-parent l0 0 0ksxp shared latch 0 0kcfis stats shared latch 0 0shared pool 126676 61library cache load lock 0 0shared pool simulator 6576 0shared pool sim alloc 45 0Shared B-Tree 302 0shared server configuration 6 0shared server info 1 0运行业务:17:08:34 SCOTT@ prod>begin17:08:38 2 for i in 1..100000 loop17:08:52 3 execute immediate 'insert into t1 values ('||i||')';17:09:18 4 end loop;17:09:26 5 end;17:09:27 6 /PL/SQL procedure successfully completed.业务运行后:17:11:05 SYS@ prod>select name,GETS,MISSES from v$latch where upper(name) like '%LIBRARY%' OR upper(name) like '%SHARE%'NAME GETS MISSES---------------------------------------------------------------- ---------- ----------test shared non-parent l0 0 0ksxp shared latch 0 0kcfis stats shared latch 0 0shared pool 4526672 214library cache load lock 0 0shared pool simulator 1086437 0shared pool sim alloc 2048 0Shared B-Tree 316 0shared server configuration 6 0shared server info 1 010 rows selected.17:15:42 SYS@ prod>select sid,event,WAIT_TIME,state from v$session_wait where sid=42 SID EVENT WAIT_TIME STATE---------- ---------------------------------------------------------------- ---------- ------------------- 42 latch: shared pool -1 WAITED SHORT TIMEElapsed: 00:00:00.08案例2:业务运行前:17:18:35 SYS@ prod>select sid,EVENT,TOTAL_WAITS,AVERAGE_WAIT from v$session_event where sid in (42,46); SID EVENT TOTAL_WAITS AVERAGE_WAIT---------- ---------------------------------------------------------------- ----------- ------------ 42 Disk file operations I/O 4 .03 42 log file switch (private strand flush incomplete) 1 10.03 42 log file sync 4 1.76 42 db file sequential read 385 .23 42 latch: row cache objects 5 .44 42 latch: shared pool 194 .25 42 SQL*Net message to client 24 0 42 SQL*Net message from client 23 5318.9 42 SQL*Net break/reset to client 2 .08 42 events in waitclass Other 1 0 46 Disk file operations I/O 1 .03 46 db file sequential read 33 .02 46 SQL*Net message to client 13 0 46 SQL*Net message from client 12 79.914 rows selected.运行业务:17:16:39 SYS@ prod>select sid ,username from v$session where username is not null; SID USERNAME---------- ------------------------------ 1 SYS 42 SCOTT 46 HR 17:17:22 SCOTT@ prod>begin17:20:46 2 for i in 1..100000 loop17:20:52 3 execute immediate 'insert into t1 values ('||i||')';17:20:58 4 end loop;17:21:02 5 end;17:21:05 6 /PL/SQL procedure successfully completed.17:17:42 HR@ prod>begin17:21:16 2 for i in 1..100000 loop17:21:24 3 execute immediate 'insert into scott.t1 values ('||i||')';17:21:49 4 end loop;17:21:51 5 end;17:21:52 6 /PL/SQL procedure successfully completed.业务运行后:17:22:32 SYS@ prod>select sid,EVENT,TOTAL_WAITS,AVERAGE_WAIT from v$session_event where sid in (42,46); SID EVENT TOTAL_WAITS AVERAGE_WAIT---------- ---------------------------------------------------------------- ----------- ------------ 42 Disk file operations I/O 4 .03 42 latch: cache buffers chains 16 .18 42 buffer busy waits 2 .15 42 log file switch (private strand flush incomplete) 1 10.03 42 log file sync 4 1.76 42 db file sequential read 413 .21 42 latch: row cache objects 58 .13 42 latch: shared pool 1008 .19 42 library cache: mutex X 123 .33 42 SQL*Net message to client 24 0 42 SQL*Net message from client 24 6044.43 42 SQL*Net break/reset to client 2 .08 42 events in waitclass Other 87 .09 46 Disk file operations I/O 3 .03 46 latch: cache buffers chains 13 .21 46 buffer busy waits 1 .35 46 latch: redo copy 1 1.26 SID EVENT TOTAL_WAITS AVERAGE_WAIT---------- ---------------------------------------------------------------- ----------- ------------ 46 db file sequential read 38 .02 46 enq: HW - contention 1 .01 46 latch: row cache objects 58 .14 46 row cache lock 1 .08 46 latch: shared pool 666 .17 46 library cache: mutex X 99 .29 46 SQL*Net message to client 13 0 46 SQL*Net message from client 13 2010.63 46 events in waitclass Other 68 .1426 rows selected.Elapsed: 00:00:00.3717:22:42 SYS@ prod>17:22:02 SYS@ prod>select sid,event,WAIT_TIME,state from v$session_wait where sid=4217:22:25 2 or sid=46; SID EVENT WAIT_TIME STATE---------- ---------------------------------------------------------------- ---------- ------------------- 42 latch: shared pool -1 WAITED SHORT TIME 46 latch: shared pool -1 WAITED SHORT TIME
以上是"Oracle Library Cache的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!