
Oracle的使用的队列大致可以分为三种类型:
1.实例类:比如实例启动和恢复,SCN同步;
2.事务类:比如library cache,dictionary cache,并行查询。
3.用户类:用户自定义的队列(enq:UL-contention)
当会话需要访问指定资源的时候,就需要获得锁结构(ksqlk),请求以特定锁模式获得对资源的访问。锁请求的锁结构属于如下三个链表之一(所有者,等待者和转换者)。可以根据v$lock视图的LMODE列和REQUEST列区分所有者,等待者还是转换者。平均等待时间可以通过v$enqueue_stat的cum_wait_time/total_wait#计算得到,单位为千分之一秒。
REQUEST | ENQUEUE | |
非零 | 零 | 所有者 |
非零 | 非零 | 转换者 |
零 | 非零 | 等待者 |
Oracle的本地队列的申请在ksq层完成即可,对于全局队列则需要经历ksi和kju层的申请。每一个队列资源和锁都对应分布锁管理的资源和锁。如果存在当前事务,则事务标识符(XID)是分布锁锁定标识的一部分(Oracle使用它来做死锁检测)。如果没有当前事务,锁定标识则使用连接线程号(2个字节),Oracle进程ID(2个字节)和ksuseq的标识符组成。对于每个Oracle进程而言,它们的ksuseq值始终以0开始然后递增。
ksq层始终使用XID调用ksi层以申请创建分布式锁。其他层(例如kqr或kqlm)在没有XID(进程拥有)的情况下调用ksi层,因而不能使用DLM的死锁检测功能。
锁兼容性原则
1.相互兼容的锁可以同时存在于授权队列中。
2.请求队列上的锁与授予队列上的锁不兼容,并且与转换队列上的其他锁不兼容。
3.PR和CW组合存在特殊情况,PR与较小模式CW不兼容。这就不允许从PR到CW的锁降级。
4.GCS锁定模式是用下划线表示的。
锁存在于资源授予或转换队列中。如果锁模式发生更改,则它会在队列之间发生移动。授予队列中可以存在多个锁,但是它们必须是相互兼容的。相同模式的锁不一定与另一个相同模式兼容。在GES和GCS锁之间各种锁的兼容性矩阵不同。同队列的锁转换通常是降级,即转换为较小的模式。存在一些例外情况,稍后会介绍。
锁可以在以下任何条件下离开转换队列:
进程请求锁定终止(删除锁定)。 进程取消转换; 锁被移回到授权队列中以前的模式。 请求的模式与Grant队列中最高级别的锁兼容,请求的锁在转换队列的前列(FIFO)并与先前的锁模式兼容。
1.会话A尝试读取一个资源这时它会在Grant队列对资源添加授共享锁(一致性)。
2.这时会话B申请共享读锁定。因为共享锁是相互兼容的,因此它们可以同时驻留在Grant队列。
3.会话C申请共享读锁定,共享读锁被放置于Grant队列中。
4.会话A持有的共享锁转换为NULL模式。因为这是一个简单的降级, 这种转换可以在Grant队列直接完成。
5.会话C尝试更改资源因此持有的锁尝试转换为独占模式,这时它必须放在转换队列。


由于转换队列是先进先出(FIFO),这种情况下可能就会产生死锁情况。
相关链接
Oracle RAC Cache Fusion 系列九:Oracle RAC 分布式资源管理(二)
Oracle RAC Cache Fusion 系列八:Oracle RAC 分布式资源管理(一)
Oracle RAC Cache Fusion 系列七:RAC Messaging System
深入浅出Kubernetes网络:跨节点网络通信之Flannel

更多干货,欢迎来撩~