本文会对RAC中锁的管理进行介绍,其中包括以下三部分内容。
1. RAC 中锁的介绍
2. RAC如何发现死锁
3. 搜集RAC 中锁的诊断信息
适用范围:9.2 及以上版本。
首先,我们对RAC中锁的基本概念进行一些介绍。对于RAC数据库,我们可以把锁分为两类,第一类我们可以称之为buffer lock, 这种锁针对数据库的buffer,另一种锁就是我们经常提到的排队(enqueue)。本文主要介绍后一种( buffer lock 会在今后的文章中介绍)。
既然是锁,那么就会包含等待者(convert)和持有者(grant)队列,类型(用来表示所保护的资源),以及访问的模式。另外,对于RAC系统,由于需要在多个实例间维护访问的一致性,每个锁也会有一个master 节点,在master 节点中会包含这个锁的完整的grant 和convert 队列,而每一个访问过这个锁的节点,也会保存本地的grant 和convert 队列。我们在共享池中看到的’ges resources’部分,就包含了锁的master信息,当然,也可以认为master信息是GRD 的一部分。
对于锁,另一个重要的概念就是模式(或级别),针对不同的操作,需要获得不同模式的锁,毕竟锁是一种串行的机制,串行在很多时候意味着等待,而我们并不希望看到等待,所以我们需要锁具有不同的模式,来尽量避免等待。同时,也为了保证数据的一致性,锁的有些模式之间是可以兼容的,而有些是不能兼容的。对于RAC系统,我们可以参照以下的表格,了解锁的模式和兼容性。
当用户进程需要申请锁的时候,会发生以下的过程。
1. 申请进程发送消息给master节点,找到关于锁的全部grant 和 covert 队列信息。
2. Master 节点通知持有者释放(Down convert)相应模式的锁。
3. 如果持有者不能释放,即申请锁的兼容模式无效(进程不能以申请的模式获得锁,因为其他进程正在以不兼容的方式持有这个锁),申请进程进入等待者队列。
4. 当持有者释放锁之后,master节点通知申请进程能够以所申请的模式获得锁并进入持有者队列,申请请求成功结束。
对于RAC环境中的死锁(对于死锁的概念,本文不做介绍),是由LMD进程处理的。基本的过程是。
1. LMD进程定期搜索各个实例的锁信息,发现可能的死锁。
2. 在可能的死锁进程被发现之后,LMD会验证死锁。
3. 在得到验证之后,LMD会选择回滚导致死锁的进程的当前SQL语句,来打破死锁。
接下来,我们通过下面的例子,对诊断RAC 中锁相关的问题进行简单的介绍。我们用下面的步骤制造一个DML 死锁。
1. Session1: update emp set ename='new name' where empno=7934;
2. Session2 : update emp set ename='new name1'where empno=7902;
3. Session1 : update emp set ename='new name1'where empno=7902;
4. Session2: update emp set ename='new name' where empno=7934;
之后我们在数据库实例1的alert log 中会找到死锁的信息。
Sun Apr 7 04:45:39 2013
Global Enqueue Services Deadlock detected. More info in file
/u01/app/oracle/admin/ONEPIECE/bdump/onepiece1_lmd0_6257.trc
从实例1的lmd 跟踪文件中,我们能够找到类似的信息。
DUMP LOCAL BLOCKER/HOLDER: block level 5 res [0x70022][0x1de6],[TX]
----------resource 0x0x3f969794----------------------
resname : [0x70022][0x1de6],[TX]
……
GRANTED_Q :
lp 0x3f9714e0 gl KJUSEREX rp 0x3f969794 [0x70022][0x1de6],[TX]
master 0 gl owner 0x456339e8 possible pid 14942 xid 1D000-0001-000000A6 bast 0 rseq 39 mseq 0 history 0x95
open opt KJUSERDEADLOCK
CONVERT_Q:
lp 0x3f9715b4 gl KJUSERNL rl KJUSEREX rp 0x3f969794 [0x70022][0x1de6],[TX]
master 0 owner 1 bast 0 rseq 8 mseq 0x1 history 0x97ad
convert opt KJUSERGETVALUE
以上的信息说明对于enqueue [0x70022][0x1de6],[TX],它的master 节点为节点1,grant 队列中有一个进程14942,convert队列中包含一个进程,但是这个进程在节点2,不会在节点1的跟踪文件中显示出进程的详细信息,需要到节点2的lmd 跟踪文件中查找。所以,我们能够看到master节点会包含enqueue 的全局信息。
----------resource 0x0x423753fc----------------------
resname : [0xb0004][0xf8f],[TX]
……
GRANTED_Q :
CONVERT_Q:
lp 0x4488c5b0 gl KJUSERNL rl KJUSEREX rp 0x423753fc [0xb0004][0xf8f],[TX]
master 1 gl owner 0x456339e8 possible pid 14942 xid 1D000-0001-000000A6 bast 0 rseq 113 mseq 0 history 0x1495149a
convert opt KJUSERGETVALUE
以上的信息说明对于enqueue [0xb0004][0xf8f],[TX],它的master节点为节点2,grant 队列为空,而convert队列中有1个进程14942, 但是,由于节点1并不是这个enqueue的master节点,所以只能显示本地节点的信息。如果要获取这个enqueue的全部信息,需要查看节点2的lmd跟踪文件。
对于RAC中死锁的问题,LMD跟踪文件会描绘死锁的图像。也就是经常提到的WFG。
Global Wait-For-Graph(WFG) at ddTS[0.1] :
BLOCKED 0x4488c5b0 5 wq 2 cvtops x1 [0xb0004][0xf8f],[TX] [1D000-0001-000000A6] 0
BLOCKER 0x5d8512dc 5 wq 1 cvtops x8 [0xb0004][0xf8f],[TX] [16000-0002-00000043] 1
BLOCKED 0x5d88d58c 5 wq 2 cvtops x1 [0x70022][0x1de6],[TX] [16000-0002-00000043] 1
BLOCKER 0x3f9714e0 5 wq 1 cvtops x8 [0x70022][0x1de6],[TX] [1D000-0001-000000A6] 0
以上信息的含义,可以参考Note 242263.1 : Analyzing ORA-60 Deadlocks in a RAC Environment。
最后,对于诊断RAC中锁的问题,我们还可以通过以下的信息进行诊断
查询视图gv$lock, gv$ges_enqueue
搜集 systemstate dump, hanganalyze dump 文件
搜集 lmd 跟踪文件和产生的用户进程跟踪文件。