GRD由处理数据块的全局缓存服务(GCS)和处理队列的全局队列服务(GES)组成。高速缓存一致性通常用于指保持数据缓冲区高速缓存在实例之间的一致性,因为它确实代表了高速缓存一致性活动的大部分。此缓存一致性由PCM锁处理。块缓存一致性可以通过两种方式处理:磁盘ping和Cache Fusion。
Oracle 9i以前处理方式:
ping协议:
检查实例是否锁定,请求DLM以指定模式获取锁定:
如果存在冲突,主机请求持有者写入磁盘并降级。
发送BAST。
成功降级后发送AST。
从磁盘读取块
该协议也用于Oracle7及早期版本。所有块数据传输都是通过磁盘进行的。 DLM跟踪区块所有权; 也就是说,一个实例具有独占访问权限,或者多个实例具有共享读访问权限。因此,任何读取请求都涉及从独占模式降级到共享模式,通过:
刷新重做日志
将块写入磁盘
一致性读:
专为写/读争用而设计的构建一致的读取副本。CR块通过内部通信网络发送,fairness计数器实现light work rule。在接收到一致读取(CR)请求时,数据块的持有者使用undo数据(其块在本地驻留在缓存中)来构造块。如果创建一致的读取版本块涉及太多工作(例如从磁盘读取块),则持有者将块发送给请求者,并且请求者完成CR构造。持有者维护cr请求的fairness 计数器。当达到阈值后,持有者将其锁定模式进行降级。CR服务核心由专用进程Block Server Process执行(BSP)。Oracle8 ping协议用于写/写争用或除一致读取之外的任何请求。
Oracle 9i以后 Cache Fusion协议
解决写/写争用的问题
消除磁盘ping协议; 通过私有网络发送当前块
处理已通过缓存传输的块的恢复
使用CR服务功能解决写/读争用
在实例之间运送当前块时存在问题。简单的案例:
1.实例A修改块,然后将块传送到实例B.在发送任何脏块之前,进行日志刷新。
2.实例B修改块,然后将块运回实例A。
3.实例A再次修改块。没有任何步骤是将块写入磁盘。
假如A块的崩溃恢复,必须合并两个日志才能应用它们。实例B是否进行崩溃恢复并不重要。
GCS(PCM)锁
实例锁的同步成本可能很高。 PCM锁通常比非PCM锁多得多。 non-PCM锁的数量不会增加到PCM锁一样的数量。在V$LOCK视图中仍然可以看到变为全局的本地队列但是无法看到某些实例锁和PCM锁。缓存融合改变了Oracle服务器中关于数据块块和锁的传输以及PCM锁的使用。将锁模式与分配给锁持有者的角色分开,使整个缓存一致性的协调更加高效。
PCM锁管理缓冲区高速缓存中的数据块锁定。
PCM锁内部与锁元素块类型映射对应。
块类型可以通过V$LOCK_ELEMENT(X$LE)视图查看。
PCM锁状态信息存储在称为锁定元素LE的数据结构中。
LMSn进程处理PCM锁。
Lock Elements (LE)
PCM锁通过锁元素(lock Elments)来进行描述。它保存在SGA中,保存锁状态信息(转换、持有者等)由锁进程管理以确定锁的模式(独占、空、共享等)。LE要链接的块具有绝对文件ID(AFN)和块编号(BNO),LE由<“BL”,id1,id2>标识。使用哪个LMSn由:(id1 + id2)%(number_of_LMS_procs)判断
UNDO以外的块:
id1 = BNO位或(AFN << 22)
id2 =(AFN >> 10)<< 15
UNDO块:
id1 =(BNO _kcl_undo_grouping)%_kcl_undo_locks
id2 =块类型
注意:缓存融合仅适用于UNDO以外的块。
哈希链表
Oracle RAC环境中的每一个活跃的可释放使用的锁元素都是通过Oracle常用的hash链表的方式进行挂载。正常情况下Hash桶的数量是比要比_db_block_buffers数量要少。
数据块与LE的映射关系
Oracle通过上面介绍的id1,id2来进行LE与数据块的相互映射。Oracle现根据id1和id2扫描LE的hash链表。如果匹配上则使用这个匹配的LE,结束。如果没要找到者尝试申请在空闲列表上的LE,如果申请成功则开始初始化id1,id2然后把它挂在上述的链表上,结束。如果还没申请到,则通过LMS尝试释放一部分LE并开始等待“Global cachefreelist wait”,然后重复上述循环。当需要释放LE时,必须发送消息给与LE<id1,id2> 相关联的LMS。
LMS的LE队列
每个LMS进程都有许多锁存器(gc_latches),每个Latch都会保护多个队列。一般情况下有如下几种队列:
LMSn释放LE
首先LMS从与之关联的lazy-close队列选择一个LE。然后获得该队列上的Latch。然后判断是否有buffer块与它相互链接。如果有,则获得buffer块的hash链表,释放队列latch,返回下一次循环。如果没有,则通过LE继续计算rdba,tsn获得hash链表。请求hash链表的latch,如果请求成功,则表示该LE可以释放,释放LE。如果请求失败则进行Latch的短暂等待后继续下一次循环。
相关链接
Oracle RAC Cache Fusion 系列五:RAC环境下的崩溃恢复
更多干货,欢迎来撩~