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

青旅半醒 2021-11-05 20:24 376阅读 0赞

案例演示

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

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

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

3.P2执行回滚操作。

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

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

6.P1执行回滚操作。

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERWQTZ5WGdham5JbDZPSGwxaHFJRVhwZUVJYlZiR2dxWmxMUnlPU3l6U0ZLSUU1RVlwcmdrZGcvNjQwP3d4X2ZtdD1wbmcmdHA9d2VicCZ3eGZyb209NSZ3eF9sYXp5PTEmd3hfY289MQ

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERhS29nTDZwTXh2NVdHY2VzZ2poUHhKYzFMUURDY04yVG03a0NvbURuMmVzUVk4T2t2YkVIUEEvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

第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”计数和时间。

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERYZ0dYM0NVeHZkUWZheGliRVREazZJcFFrWWlieVFBWGJ3RXhKZm40ZVhGOUFBQTBOQTg5N3kydy82NDA_d3hfZm10PWpwZWcmdHA9d2VicCZ3eGZyb209NSZ3eF9sYXp5PTEmd3hfY289MQ

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERhS29nTDZwTXh2NVdHY2VzZ2poUHhKYzFMUURDY04yVG03a0NvbURuMmVzUVk4T2t2YkVIUEEvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERJZ25BVkVLaWIyR2t0ZGpzYk8wbDNaTHY1Q2NyWlFKbTg4Rkw5cjhxOE5ieHl1RmNubWljVWFmdy82NDA_d3hfZm10PXBuZyZ0cD13ZWJwJnd4ZnJvbT01Jnd4X2xhenk9MSZ3eF9jbz0x

20190809101503818.gif

第2步:kjusuc流程细节

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

• 本地没有不兼容的锁。

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

无需向主实例发送消息。

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

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

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

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERMZ2t3U08xU3ZLZUk1NWQwZmFjQUR6VnNxWmdwNHVKMm5teERFY0dFckh2S2NSclJCRnBlb3cvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERhS29nTDZwTXh2NVdHY2VzZ2poUHhKYzFMUURDY04yVG03a0NvbURuMmVzUVk4T2t2YkVIUEEvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

第3步:核心流程

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

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERWVFhOdWtmSnp1VXRnVGQ2aWFicUJGNHQ2ZG9wN0NZWXJVb2xXaWNDdmliZTc1NlR2RnNoRFNsV3cvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

第3步: kjuscl详细流程

因为资源1上一直挂着lock1,因此释放p2申请的资源后资源1依然无法释放。

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

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

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

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERQQkUxSW81YnlpYlJhVW5veFFkejJRMGFOaWFCcXhzMWxkNzdDR01YY2lhVFBvYkhZTGNHdlVJQ3cvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

第4步:核心流程

在步骤4中,P1将表共享模式锁升级为独占锁。ksqcnv提供一个锁定描述,如之前使用kjusuc获得的。

ksipcon是用于锁定转换的DLM的同步接口。调用kjuscv(timeout无限制),然后增加“global lock sync converts”并更新“global lock convert time”。

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERCRXNhNzVMYW5MSHU0MHp5aEV4Y3NrcFQ2Q283MW51emRUYmtxZkhKaWJpY0JpYURNU2FuakExc1EvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

因为此转换会使资源的保持模式从S变为X并且实例1不是主实例,所以必须将消息发送到主实例以确定转换申请是否可以执行。

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

2.将资源1上的锁从grant队列移动到转换队列。lock1不会未挂起,因为在计时器队列上它是无超时限制的。

3.将lock1挂在死锁队列上,因为lock1可能会成为死锁。

注意,仅当锁是本地锁时,锁才挂在计时器队列和死锁队列上。换句话说,锁的拥有实例与本地实例相同。

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaER4bW9mam1jeTNkbTZXYmlhV2FUNTQ3aWFpYUxpY09ScXBpY1dyT3NPUEpHNTZMaWFWR1Z1Zllqb3pjZVEvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

4.将消息发送到主实例。

5.轮询等待AST,用等待事件“enqueue”表示等待状态。

实例2

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

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

实例1等待继续。

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

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

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaER0N0dlMG9GejlmRktrdzZzNm80WEluTktsWXh2Wk5WanJqbEZqRndoZVlIb1VUcUM3R0ZyVWcvNjQwP3d4X2ZtdD1wbmcmdHA9d2VicCZ3eGZyb209NSZ3eF9sYXp5PTEmd3hfY289MQ

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaER6aGljUGRrWklKUXJGRUNsQjhLbVJuTHJpY2Zyb2x0ZnlvU2xTSXlQaWJYV09jVjdMY3RZNFU5MEEvNjQwP3d4X2ZtdD1wbmcmdHA9d2VicCZ3eGZyb209NSZ3eF9sYXp5PTEmd3hfY289MQ

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERhS29nTDZwTXh2NVdHY2VzZ2poUHhKYzFMUURDY04yVG03a0NvbURuMmVzUVk4T2t2YkVIUEEvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERYTTZuWEFDUEcza25RU2dseTZiQ2dpYm5hckNkS2RHZnJ1RFRHVFl6Mm5yUFdGdExqRjF5Nlp3LzY0MD93eF9mbXQ9cG5nJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

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

1.锁1从X转换为NULL。

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

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

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

aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy85UmpScnZPNjN6ZmJwZkZpYWhsdU5iR1A0YlpQb0JhaERGSnZqeXFmR2hwRzA0MW1RNkdIeDJmVGpGQnZ3R2ljUUJDU2lic1NvUTM0bnpSSU5SSndlM2liV3cvNjQwP3d4X2ZtdD1qcGVnJnRwPXdlYnAmd3hmcm9tPTUmd3hfbGF6eT0xJnd4X2NvPTE

发表评论

表情:
评论列表 (有 0 条评论,376人围观)

还没有评论,来说两句吧...

相关阅读