绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
Oracle RAC Cache Fusion 系列十一:Oracle RAC Enqueues And Lock Part 2
2019-08-09 10:12:13

案例演示


场景: 双节点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并退出。

第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的保持模式或其请求模式,所以不会向主节点发送消息。

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

第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。


分享好友

分享这个小栈给你的朋友们,一起进步吧。

Oracle数据库技术集
创建时间:2020-05-15 15:15:11
菜鸟教程
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 栈栈
    专家
戳我,来吐槽~