一.背景
继上一篇写TX锁的处理,发现《DBA攻坚指南》这本书讲的内容特别实用,这么棒的内容应该广为推广,所以把library cache lock的处理继续分享一下。
二.理论知识
高峰期谨慎编译业务对象
在业务高峰期如果编译存储过程、函数或者视图,就会导致大量使用该对象的会话堵塞,自身也将处于挂起状态,后台等待事件主要为“library cache pin”。在日常运维中,“library cache”相关等待事件较为常见,主要分为“library cache lock”和“library cache pin”,
前者维护“library object handle”上的并发访问,后者维护“library object handle”下对应heap的并发访问,lock管理并发,pin管理一致性。
详细了解关于这里介绍的概念可以去读读《基于Oracle的SQL优化》这本书。或者看看熊老师的博客。
当我们编译存储过程、函数或者视图的时候,oracle就会在这些对象的handle上获得一个“library cache lock”,然后在这些对象的heap上获得pin,这样就能保证在编译的时候其他进程不会来更改这些对象。
三.处理过程
当业务高峰期编译对象出现会话堵塞的问题时,我们需要用到基表DBA_KGLLOCK,其包含如下两个字段:
- kgllkuse字段:“Address of user session that holds the lock or pin”,主要用于记录持有lock或pin的用户地址。
- kgllkhdl字段:“Address of the handle for the KGL object”,主要用于记录handle的对象地址。
3.1.首先查看等待事件
故障发生时,首先查看后台等待事件
SQL> select inst_id,sid,event,p1,p1text,p1raw,p2,p2text,p2raw from gv$session where wait_class <> 'Idle';
INST_ID SID EVENT P1 P1TEXT P1RAW P2 P2TEXT P2RAW
1 33 library cache pin 2081944584 handle address 000000007C17F408
SQL>
复制
3.2.获取锁信息
根据等待事件“library cache pin”获取“p1 handle address 000000007C17F408”。
关联视图“dba_kgllock dk,v$session”获取锁信息。
SQL> select s.sid,s.sql_id,s.event,dk.* from dba_kgllock dk,v$session s where s.saddr = dk.kgllkuse and kgllkhdl='000000007C17F408';
SID SQL_ID EVENT KGLLKUSE KGLLKHDL KGLLKMOD KGLLKREQ KGLLKTYPE
---------- ------------- ---------------------------------------------------------------- ----------------
33 087rrdjwc2act library cache pin 0000000A92FC040 0000000007C17F408 3 0 Lock
33 087rrdjwc2act library cache pin 0000000A92FC040 0000000007C17F408 0 3 Pin
SQL>
复制
从以上返回结果中可以看出,我们并没有找到pin的持有者,KGLLKRED表示当前会话需要申请的锁模式,KGLLKMOD表示当前系统中持有的锁模式,由于该系统为RAC,各节点之间的内存结构不同,handle地址不能公用,因此我们需要定位出owner和object_name在其他节点持有pin的会话。
3.3.定位出其他节点的信息
SQL>
SQL> select ADDR,INDX,INST_ID,KGLHDADR,KGLNAOWN,KGLNAOBJ FROM X$KGLOB WHERE KGLHDADR='000000007C17F408';
ADDR INDX INST_ID KGLHDADR KGLNAOWN KGLNAOBJ
---------------- ---------- ---------- ---------------- -------------------
00007FE9B0B45850 4979 1 000000007C17F408 SYS DUMMY
SQL>
复制
其中,x$kglob为“library cache object”对象的视图。
RAC2节点2根据object_name查找对应的handle的地址信息。
SQL> select ADDR,INDX,INST_ID,KGLHDADR,KGLNAOWN,KGLNAOBJ from x$kglob where KGLNAOBJ='DUMMY';
ADDR INDX INST_ID KGLHDADR KGLNAOWN KGLNAOBJ
---------------- ---------- ---------- ---------------- -------------------
00007F987B1D8ED0 4150 2 00000000AA193870 SYS DUMMY
复制
3.4.其他节点查看锁的信息
SQL> select s.sid,s.sql_id,s.event,dk.* from dba_kgllock dk,v$session s where s.saddr = dk.kgllkuse and kgllkhdl='0000000AA193870';
SID SQL_ID EVENT KGLLKUSE KGLLKHDL KGLLKMOD KGLLKREQ KGLLKTYPE
---------- ------------- --------------------------------------------------
424 d4wnj5j8y1mq7 PL/SQL lock timer 00000000A9787DA0 0000000AA193870 1 0 Lock
424 d4wnj5j8y1mq7 PL/SQL lock timer 00000000A9787DA0 0000000AA193870 2 0 Pin
SQL>
复制
3.5.查杀阻塞源
最终定位节点2上的会话424持有的模式为2(即共享模式)的锁,阻塞了KGLLKREQ 3排它锁的申请,为了能够顺利编译,我们只需要杀掉节点2上的会话424即可。
评论
