RAC 锁管理与锁问题的定位(二)(内含09年在公司内部讲课时的PPT,有需要者下)
在上一篇中,我们讲述了RAC下锁的管理模式。本篇中,我们总结下出现锁问题后的定位。有上节的基础,你会发现在RAC下查找锁问题,是如此的简单。
(如果还没有阅读前一篇,好先看前一篇,再看本篇。前一篇链接:http://www.itpub.net/thread-1587800-1-1.html)
(另外,PPT有点简单了,大家凑合着看,后面我慢慢再整理稍微深入点的东西)
我们这次以TX锁为例,TX锁的竞争为常见。我们的语句:
update t3 set id=id+0 where id=3;
我在两个节点执行如下语句,肯定会被HANG住一个。下面,我们来说一下RAC下锁问题定位的一般步骤。
一、查找资源名
在被HANG住的节点中执行如下语句,查找请求模式为6、锁类型为TX的行:
select * from v$lock where type='TX' and REQUEST=6;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
320CBB30 320CBB44 193 TX 1048616 291 0 6 1410 0
其实,我们要找的,是正在等待的TX锁的资源名:TX-1048616-291,化成16进制,TX-100028-123。变成V$DLM_RESS、V$GES_ENQUEUE视图中的格式:[0x100028][0x123],[TX]。
下面这条语句,直接输出资源名:
SQL> select '[0x'||lower(trim(to_char(id1,'xxxxxxxx')))||'][0x'||lower(trim(to_char(id2,'xxxxxxxx')))||'],['||type||']' from v$lock where type='TX' and REQUEST=6;
'[0X'||LOWER(TRIM(TO_CHAR(ID1,'
-------------------------------
[0x100028][0x123],[TX]
二、定位主节点
找到资源名后,就可以在V$DLM_RESS中,以资源名为条件,查找此资源的主节点:
SQL> select RESOURCE_NAME, ON_CONVERT_Q,ON_GRANT_Q, MASTER_NODE from V$DLM_RESS where resource_name like '[0x100028][0x123],[TX]%';
RESOURCE_NAME ON_CONVERT_Q ON_GRANT_Q MASTER_NODE
------------------------------ ------------ ---------- -----------
[0x100028][0x123],[TX] 1 0 1
此资源的主节点是1,也就是第二个节点。上面两条语句,还可以合在一起:
select RESOURCE_NAME, ON_CONVERT_Q,ON_GRANT_Q, MASTER_NODE from V$DLM_RESS where resource_name like (select '[0x'||lower(trim(to_char(id1,'xxxxxxxx')))||'][0x'||lower(trim(to_char(id2,'xxxxxxxx')))||'],['||type||']' from v$lock where type='TX' and REQUEST=6)||'%';
三、定位持有锁的节点
仍在审请锁被阻塞的节点,查询GV$GES_ENQUEUE视图,语句如下:
col STATE for a10
select inst_id,GRANT_LEVEL, REQUEST_LEVEL,PID, OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKER from GV$GES_ENQUEUE where resource_name1 like (select '[0x'||lower(trim(to_char(id1,'xxxxxxxx')))||'][0x'||lower(trim(to_char(id2,'xxxxxxxx')))||'],['||type||']' from v$lock where type='TX' and REQUEST=6)||'%';
结果如下:
INST_ID GRANT_LEV REQUEST_L PID OWNER_NODE WHICH_QUEUE STATE BLOCKED BLOCKER
---------- --------- --------- ---------- ---------- ----------- ---------- ---------- ----------
1 KJUSERNL KJUSEREX 5527 0 2 OPENING 1 0
2 KJUSEREX KJUSEREX 6668 1 1 GRANTED 0 1<------------持有锁的进程
2 KJUSERNL KJUSEREX 0 0 2 GRANTED 0 0
资源的主节点是第二个节点,只看INST_ID为2的行就行,例子中第二行,GRANT_LEVEL列为KJUSEREX,说明此行对应的进程,持有独占锁,进程号为6668。但这个进程号对我们没有意义,因为此处进程永远都是LMD。此处对我们有意义的列是OWNER_NODE,本例中为1。也就是第二个节点持有此锁。
四、定位持有锁的会话
我们已经找到是第二节点中某个会话持有锁,接下来,查询v$lock,就可以定位到会话号:
SQL> select * from v$lock where type='TX' and id1=1048616 and id2=291;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
30AA38E4 30AA3A00 192 TX 1048616 291 6 0 6791 2
192号会话持有的TX锁,阻塞了另一个节点的Update语句。
有了这个会话号,我们可以查询192执行的SQL、当前的等待事件等等,这就和单实例的一样了,我就不再说了。
五、视图的注意事项
本文中用到的和RAC相关的视图有两个:V$GES_ENQUEUE、V$DLM_RESS。其实RAC相关的视图,在早期全是以V$DLM_……开头,在10G后,Oracle又搞了一套V$GES……开头的同义词。不过有些机器上,可能因为建库时少跑了一些脚本,可能没有V$GES……开头的同义词,查询的话,会报对象不存在,就只能查V$DLM_类的视图了。但如果你在Oracle文档中找视图说明的时候,10G后的文档中,已经找不到V$DLM_类的视图说明了,只能查看它们对应的V$GES……类视图。
好,我们用到的两个视图,注意事项如下:
·V$GES_RESOURCE (V$DLM_RESS):资源结构
资源信息只在主节点和申请节点保存。
主节点编号规则,以初创建节点的的顺序为准,不以Cluster或数据库实例的启动顺序为准。
·V$GES_ENQUEUE (V$DLM_ALL_LOCKS):锁结构
Lock没有主节点,或者说申请锁的节点,如果请求成功,持有了锁,它就是此锁的主节点。OWNER_NODE就是持有锁的节点。
相关文章