Oracle RAC Cache Fusion 系列十一:Oracle RAC Enqueues And Lock Part 2

案例演示


场景: 双节点RAC环境下,三个不同的会话访问同一张表T:

1.P1申请表的共享模式锁。

2.P2申请表的共享模式锁。

3.P2执行回滚操作。

4.P1申请表的独占模式锁。

5.P3申请表的共享模式锁。

6.P1执行回滚操作。

第1-2步:核心流程
在步骤1中,P1将表锁定在共享模式下。在步骤2中,P2在共享模式下锁定同一个表。差异出现在kjusuc层。

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步:详细流程

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并退出。

gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==

第2步:kjusuc流程细节

资源已经存在,因此流程很简单立即授予锁即可,因为:

• 本地没有不兼容的锁。

• 请求模式为S,与之前持有的模式相同。因为授予另一个共享模式锁不会涉及到锁模式的升级。

无需向主实例发送消息。

1.分配lock1并更新V$RESOURCE_LIMIT。

2.将锁定状态设置为KJL_OPENING,KJL_CONVERTING。

3.挂起现有资源1上的锁。

4.处理AST; 清除KJL_OPENING,KJL_CONVERTING然后退出。

第3步:核心流程

在步骤3中,P2通过执行回滚来释放表共享模式锁。

Ksiprls是分布式锁管理针对CLOSE lock操作的同步接口。在返回调用kjuscl时,增加“global lock releases”统计信息。

第3步: kjuscl详细流程
因为资源1上一直挂着lock1,因此释放p2申请的资源后资源1依然无法释放。

1.将锁定状态设置为KJL_CLOSING。

2.从资源1中删除lock2和进程2。

3.释放lock2,更新V$RESOURCE_LIMIT。

4.退出。因为删除锁2不会更改资源1的保持模式或其请求模式,所以不会向主节点发送消息。

gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg== 第4步:核心流程

在步骤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”表示等待状态。

实例2

1.因为在主实例中并且没有锁模式的冲突,所以lock1的模式从S转换为X,。

2.排队并向请求者实例发送消息。

实例1等待继续。

6.将lock1置于授权队列中,并将其从死锁队列中删除。

7.通过设置其标志将AST发送到客户端进程。

8.响应处理AST; 清除KJL_CONVERTING并退出。

gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg== 第5步:详细流程 在步骤1中,P3请求以共享模式锁定表。代码路径与步骤1和2相同,在kjusuc中进行处理。

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冲突的锁的探测消息。

第6步:详细流程 P1通过在实例1中执行回滚来释放其独占表锁。

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.结束退出。

实例2从实例1收到KJX_CONVERT_REQ消息后:

1.锁1从X转换为NULL。

2.尝试为资源1授予转换队列上的所有锁。因为lock1已经被降级为NULL,所以可以授予lock3。

3. AST被发送到P3,P3仍在等待第5步。

4. P3处理AST,完成锁定获取,退出DLM。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28218939/viewspace-2653134/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28218939/viewspace-2653134/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值