RAC 锁管理与锁问题的定位(二)
在上一篇中( http://space.itpub.net/321157/viewspace-718009),我们讲述了RAC下锁的管理模式。本篇中,我们总结下出现锁问题后的定位。有上节的基础,你会发现在RAC下查找锁问题,是如此的简单。
我们这次以TX锁为例,TX锁的竞争最为常见。我们的语句:
update t3 set id=id+0 where id=3;
update t3 set id=id+0 where id=3;
我在两个节点执行如下语句,肯定会被HANG住一个。下面,我们来说一下RAC下锁问题处理的一般步骤。
一、查找资源名
在被HANG住的节点中执行如下语句,查找请求模式为6、锁类型为TX的行:
select * from v$lock where type='TX' and REQUEST=6;
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
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
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
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]
-------------------------------
[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]%';
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
------------------------------ ------------ ---------- -----------
[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
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 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;
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
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
30AA38E4 30AA3A00 192 TX 1048616 291 6 0 6791 2
192号会话持有的TX锁,阻塞了另一个节点的Update语句。
有了这个会话号,我们可以查询192执行的SQL、当前的等待事件等等,这就和单实例的一样了,我就不再说了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/321157/viewspace-719777/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/321157/viewspace-719777/