3、library cache lock 和 library cache pin
library cache lock 的定义:访问或修改库高速缓冲区的对象时,对库高速缓冲区句柄(handle)获得的锁,在获得library cache lock 的过程中,如果发生争用,则等待library cache lock事件。
通过library cache lock 事件的P1=handle address P2=lock address P3=mode*100+namespace,可以掌握对哪个对象以哪种模式获得锁的过程中发生争用的。对sql 语句所对应库高速缓冲区对象执行parsing期间,以shared 模设获得library cache lock。parsing 结束后,library cache lock 变为null 模式,library cahce lock对sql所引用的所有对象(表,视图,同义词等)以相同的模式获取。
可以这么想,当执行parsing时,以shared 模式获取的锁,这样多个进程可以同时执行sql语句。因此,对库高速缓冲区对象(sql cursor 、procedure 、package等)的parsing和执行阶段,不发生library cache lock或library cache pin 争用。
然而,利用create or replace procedure 。命令,创建或修改该procedure的进程,对procedure相应的库高速缓冲区对象,应该以exclusive 获得library cache lock。修改表(alter)时,也应该对表相应的库高速缓冲区对象(库高速缓冲区内sql语句对表的引用),以exclusive模式获得library cache lock。因此,如果有许多会话对某个表执行select 操作,而这时对相应的表执行长时间的修改,按照以前的想法,构造CR块,不会引起争用,但是现在看来,修改进程如果以exclusive模式持有了库高速缓冲区内sql对象的libray cache lock ,那么查询操作时不能获得shared 模式的library cache lock 也就不能执行sql语句。。
执行sql语句或procedure时,对库高速缓冲区对象,以shared模式获得library cache lock 后,没有完全释放,而是变换为null 模式继续持有该锁的理由是什么呢??其实,这是为了自动执行库高速缓冲区对象的无效化(invalidation),sql cursor之列的对象,只要自身参考的对象被修改,则这些对象就要被自动无效化,缓存与PGA区域的sql cursor也应该被自动无效化,为此,sql cursor对自身参照的所有对象,以null模式请求library cache lock。因此,若对相应对象执行DDL(alter drop等)操作,参考一null 模式获得library cache lock信息后,对相关的库高速缓冲区对象进行无效化。
library cache pin的定义:对库高速缓冲区对象访问或修改时,对library cache object(LCO)获得的锁。若library cache lock 保护的是LCO的详述(specification),则library cache pin 则保护的是LCO的内容(执行信息),在获取library cache pin过程中,若发生争用,则等待library cache pin事件。通过library cache pin 时间的P1=handle address P2=lock address P3=mode*100+namespace,可掌握那个对象以哪种模式获得锁的过程中发生争用。
library cache pin是在获得library cache lock后,需要对库高速缓冲区对象进行追加工作时获取。例如,想要执行天特定procedure 或sql语句的进程,以shared模式获得library cache lock后,应该以shared 模式获得ibrary cahce pin,对procedure执行编译(alter procedure 。。compile。。)时,应该以exclusive模式获取。在hard parsing期间,对于相应的sql cursor ,需要以exclusive 模式获取library cache pin。
好了,现在我们大概了解了library cache lock 和 library cache pin的区别,可能会禁不住想一个问题,为啥oracle对一个库高速缓冲区不用一个锁,而是使用这两个锁呢??这就要从库高速缓冲区的管理机制说起了。。。。library cahce lock 是对句柄获得的。而library cache pin 是对lco获得的。因此两个进程对父句柄各自以shared 模式获得library cache lock的状态下,两个进程可以各自对LCO,以exclusivce模式获得library cache pin,所以与sql cursor相同,对于一个逻辑对象创建多个LCO时,可以最大限度提高对高速缓冲区的访问量。
对于库高速缓冲区对象获得library cache lock 过程属于soft parsing 阶段,发生hard parsing并执行5-6(生成解析树和和执行计划)期间,将library cache lock变换为null模式,然后以exclusive模式获得library cache pin。这是为了防止建立执行计划期间对LCO发生修改。hard parsing结束后将 library cache pin变换为shared 模式,然后进入执行阶段。
还有一点需要说明,这两个锁不被归为enqueue锁,但是内部使用与enqueue锁类似的机制,对于enqueue锁来讲,在位于SGA共享池内管理排队资源和enqueue锁的Array区域上,管理所有相关信息。。但是,没有被归为enqueue锁的library cache lock/pin、row cache lock 、buffer lock等,是各自在其内存区域上管理的。
4、关于上面两个锁的具体实例分析
下面,我们通过7个问题逐个分析,来理解library cache lock 和 library cache pin的运行机制:
1、若两个会话持续调用相同的create or replace procedure xxx,则等待何种时间呢?
通过执行测试环境,执行查询当前会话的等待事件语句(下面是我行电脑上自己查的,没有构造环境,所以没有library cache lock等待),可以学习这个查询等待事件的sql:
SQL> select event,total_waits ,time_waited from v$session_event
2 where sid=(select sid from v$mystat where rownum=1)
3 order by 3 desc;
EVENT TOTAL_WAITS TIME_WAITED
------------------------------ ----------- -----------
SQL*Net message from client 570 1019057
db file sequential read 1129 635
db file scattered read 172 83
control file sequential read 104 43
latch: library cache 52 34
log file switch completion 2 27
latch: cache buffers chains 6 26
rdbms ipc reply 8 21
log file sync 12 17
latch: In memory undo latch 1 14
direct path read 5 11
EVENT TOTAL_WAITS TIME_WAITED
------------------------------ ----------- -----------
buffer busy waits 6 6
control file parallel write 8 1
ksfd: async disk IO 5 0
db file single write 1 0
instance state change 2 0
SQL*Net more data to client 1 0
SQL*Net break/reset to client 2 0
SQL*Net message to client 571 0
direct path read temp 1 0
control file single write 3 0
buffer deadlock 2 0
已选择22行。
当我们同时修改相同的procedure时,可以确认各会话等待library cache lock时事件,通过v$session_wait视图,查得此libarary cache lock P3=30。。可以知道P3=3*100+1( 锁的mode是3,namespace是1)然后根据下图判断:
新创建procedure等对象时,对于该库高速缓冲区对象,应该以exclusive模式获得library cache lock。
2、若两个会话上持续编译相同的procedure,则等待何种事件呢?
与第一种情况一样,编译和创建procedure对象也发生应解析,就会发生exclusive模式的library cache lock争用。
3、一个会话上执行procedure期间,另外会话如果编译此peocedure,则等待何种事件呢?
会话a为了执行procedure,在以shared 模式获得library cache lock后变换为null模式,以shared 模式获得library cache pin。然而,会话b为执行编译,以exclusive模式获得library cache lock 和 library cache pin,在此过程中会发生争用。
会话b执行编译时,基本上不出现library cache lock等待,而只出现较多的library cache pin 等待的理由是什么?
第一,执行procedure的会话a在parsing sql语句的短暂时间内,对于library cache lock以shared 模式维持,parsing 结束后,将library cache lock修改为null模式。因此,编译procedure的会话b,轻松的以exclusive莫侯斯获得library cache lock。
第二,library cache pin在执行procedure期间,继续维持shared 模式,因此会话a在执行procedure期间,会话b为了执行编译,很难以exclusive模式获得library cache pin。相应的会话b的library cache lock等待时间表现的非常短,而library cache pin等待时间表现的非常长。
4、对执行hard parsing 时需要很长时间的sql 语句,若在两个会话上同时执行,则等待何种事件呢?
先执行会话a(a的hard parsing 需要花费很长时间),在会话a执行hard parsing过程中,会话b执行相同的sql语句。这时,会话a几乎不发生等待,会话b等待library cache pin事件,等待时间与会话a的hard parsing 时间几乎相同。
sql cursor上,以LCO名称使用sql文本,即,会话b为了对该sql cursor以shared 模式获得library cache pin(执行与a相同的sql)而等待。这说明正在执行的会话a对sql cursor正以exclusive模式获得,library cache pin。
在过多发生hard parsing 的系统上,大部分是因为library cache 锁存器或shared pool锁存器争用引发性能下降现象的。这时,对于library cache pin的等待偶尔也会一起发生。其理由是因为当发生hard parsing时,对于该sql cursor以及相关对象以exclusive 模式获得library cache pin ,这些可以通过上述的测试进行确认。
虽然执行hard parsing,但是父对象的lock=N,pin=0,并且正在以null模式获得library cache lock,而并没有获得library cache pin。因为在sql cursor上,符对象只管理文本信息。实际的cursor对象是由子对象管理的。因此,对于子对象,以null模式获得library cache lock以exclusive 模式获得library cache pin。
5、若两个会话上持续改变相同表的定义,则等待何种事件呢?
若想修改表的属性,对于表相应的库高速缓冲区对象,应该以exclusive模式获得library cache lock。
6、一个会话上利用alter table 。。修改表定义期间,若另外的会话对相同的表执行select,则等待何种事件呢?
修改表的会话a,为了以exclusive模式获得library cache lick而等待。相反,执行select 的会话b,为了一shared模式获得library cache lock而等待。因为shared 模式和exclusive模式之间没有共享性。因此在此过程中发生争用。
7、一个会话执行select。。from 。。。期间,若另外会话上执行alter system flush shard pool,则等待何种事件呢?
执行flush后,位于共享池上的数据字典信息都会消失,因此,想要引用该信息的话,需要一直等待library cache pin事件,直到数据字典信息相应的库高速缓冲区对象呗重新载入到内存上为止。