RAC 锁管理与锁问题的定位(二)(内含09年在公司内部讲课时的PPT,有需要者下)

2020-06-25 00:00:00 视图 语句 数据库 节点 资源
在上一篇中,我们讲述了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就是持有锁的节点。

相关文章