案例演示
场景: 双节点RAC环境下,三个不同的会话访问同一张表T:
1.P1申请表的共享模式锁。
2.P2申请表的共享模式锁。
3.P2执行回滚操作。
4.P1申请表的独占模式锁。
5.P3申请表的共享模式锁。
6.P1执行回滚操作。
ksqgtl层:获取enqueue,type =“TM”,id1= table_object_id,id2 = 0,timeout= infinite。在调用ksqcmi之前,在相关联的资源上分配队列锁。
ksqcmi层:使用get-convert函数。注册指定队列相关的队列等待事件,为DLM计算出XID。设置锁获取选项(请求死锁检测)。当kjusuc层等待AST时,使用在kjiwev中注册的等待事件。
ksipget:获取组锁,DLM接口同步,设置DLM资源名称,设置超时时间(unlimit)。 在返回调用kjusuc时,增加“global lock sync gets”和“global lock gettime”计数和时间。
1:分配lock1并更新V$RESOURCE_LIMIT。
2:将锁定状态设置为KJL_OPENING。
3:分配资源1并更新V $RESOURCE_LIMIT。
4:通过前面介绍的算法(后续系列会详细介绍)计算出主节点。
5:向主节点发送消息。(因为这是实例次申请该资源,所以它必须向主节点发送消息)
(1)6:将锁放在转换队列,并将其挂在死锁队列中。此类型锁“TM”并且是无超时限制的,因为它可能成为死锁,因此它不会附加到计时器队列,而是放在死锁队列中。
(1) 7:轮询等待AST,用等待事件“enqueue”表示等待状态。
(2)1:分配进程1描述符和lock 1(相同模式)。
(2)2:因为资源从未在实例2中使用过,所以实例2会创建它,然后将其链接到lock 1。因为它是次在实例2中使用资源1,所以这个申请操作将会成功。
(2)3:排队并向请求者实例发送消息。
8:将lock挂在授权队列中并将它从死锁队列中剔除。
9:设置标识,发送AST给客户端进程。
10:处理AST;清除KJL_OPENING并退出。
第2步:kjusuc流程细节
资源已经存在,因此流程很简单立即授予锁即可,因为:
• 本地没有不兼容的锁。
无需向主实例发送消息。
1.分配lock1并更新V$RESOURCE_LIMIT。
2.将锁定状态设置为KJL_OPENING,KJL_CONVERTING。
3.挂起现有资源1上的锁。
4.处理AST; 清除KJL_OPENING,KJL_CONVERTING然后退出。
在步骤3中,P2通过执行回滚来释放表共享模式锁。
Ksiprls是分布式锁管理针对CLOSE lock操作的同步接口。在返回调用kjuscl时,增加“global lock releases”统计信息。
1.将锁定状态设置为KJL_CLOSING。
2.从资源1中删除lock2和进程2。
3.释放lock2,更新V$RESOURCE_LIMIT。
4.退出。因为删除锁2不会更改资源1的保持模式或其请求模式,所以不会向主节点发送消息。
在步骤4中,P1将表共享模式锁升级为独占锁。ksqcnv提供一个锁定描述,如之前使用kjusuc获得的。
ksipcon是用于锁定转换的DLM的同步接口。调用kjuscv(timeout无限制),然后增加“global lock sync converts”并更新“global lock convert time”。
因为此转换会使资源的保持模式从S变为X并且实例1不是主实例,所以必须将消息发送到主实例以确定转换申请是否可以执行。
1.将锁定状态设置为KJL_CONVERTING。
2.将资源1上的锁从grant队列移动到转换队列。lock1不会未挂起,因为在计时器队列上它是无超时限制的。
3.将lock1挂在死锁队列上,因为lock1可能会成为死锁。
注意,仅当锁是本地锁时,锁才挂在计时器队列和死锁队列上。换句话说,锁的拥有实例与本地实例相同。
4.将消息发送到主实例。
5.轮询等待AST,用等待事件“enqueue”表示等待状态。
1.因为在主实例中并且没有锁模式的冲突,所以lock1的模式从S转换为X,。
2.排队并向请求者实例发送消息。
实例1等待继续。
6.将lock1置于授权队列中,并将其从死锁队列中删除。
7.通过设置其标志将AST发送到客户端进程。
8.响应处理AST; 清除KJL_CONVERTING并退出。
1.分配lock 3和进程3,更新V$DLM_RESOURCE_LIMIT。
2.将lock3的状态设置为KJL_OPENING,KJL_CONVERTING。
3.将lock3放入资源1的转换队列中。因为lock3与lock1冲突,所以不能立即转换。
4.将lock3放置在死锁队列中。
5.发送消息以探测阻塞实例中是否有新变化。这个消息分为两条,一条是针对资源1的授权队列上所有与lock 3有冲突的锁的探测消息。另外一条是转换队列中的与锁3冲突的锁的探测消息。
1.将锁定状态设置为KJL_CLOSING。
2.将锁从S模式转换成N模式。
3.锁模式从X转换为NULL后,因为lock1对resource1的持有模式也发生了变化,所以需要将消息KJX_CONVERT_REQ发送到主实例。
4.释放资源1,并进行更新V$RESOURCE_LIMIT。
5.释放锁1并更新V$RESOURCE_LIMIT。
6.结束退出。
1.锁1从X转换为NULL。
2.尝试为资源1授予转换队列上的所有锁。因为lock1已经被降级为NULL,所以可以授予lock3。
3. AST被发送到P3,P3仍在等待第5步。
4. P3处理AST,完成锁定获取,退出DLM。