在Oracle RAC环境中,每个实例都拥有独立的SGA,但数据文件是共享的。当一个实例需要读取或修改某个数据块时,必须通过全局缓存服务(Global Cache Service)与可能持有该块的实例进行协作。这里所说的KR mode,实际就是全局缓存块请求中的读模式(Read Mode),它涵盖了当前读和一致性读两种典型的访问路径。理解KR mode的锁协商和块传递过程,是分析gc类等待事件、定位跨节点热点块的先决条件。

KR mode在全局缓存中的角色与请求流程
在RAC环境下,全局缓存服务(GCS)通过Cache Fusion让实例间共享数据块,避免频繁的磁盘I/O。当一个实例(请求节点)需要访问某个数据块时,它会先向该块的主节点(Master Node)发起锁请求。主节点根据锁状态决定是允许直接读取、要求从持有节点(Holder Node)传输块,还是将请求排队等待。KR mode指的是请求节点在锁协商阶段声明的读模式,它通常对应共享锁(Shared Lock)或空锁(Null Lock)状态。如果块已经在另一个实例的缓存中并且持有兼容锁,主节点会指示持有节点将块发送给请求节点,可能是通过高速互联直接传递,也可能需要先刷盘。
需要明确的是,KR mode并不是单指某一种固定的锁模式,而是读操作在全局缓存中的统一抽象。读操作又细分为当前读(Current Read)和一致性读(Consistent Read)。当前读要求获取数据块的最新版本,常见于SELECT FOR UPDATE、DML操作或者使用CURRENT方式的块访问。一致性读则可能使用回滚段构造一个早期的块版本,对应CR块请求。在AWR报告里,这两种读请求通常分别记录在“Global Cache Current Blocks Received”和“Global Cache CR Blocks Received”指标中。虽然官方术语多为CR和CUR,但在一些内部视图和旧文档中也会看到KR的提法,本质就是“Kernel Read”或者“读模式”的缩略。
以下SQL可以查看数据库当前支持的锁类型,其中与全局缓存读模式相关的锁会出现在结果中。通过分析这些锁的请求和转换,可以了解KR mode在实例间的具体行为。
SELECT type, name, id1_tag, id2_tag, is_user FROM v$lock_type WHERE type LIKE 'KJ%' OR type LIKE 'KR%' ORDER BY type;
执行结果中,像KJUSERNL、KJUSERPR、KJUSERSH、KJUSEREX等就是GCS层使用的锁模式。其中KJUSERSH对应共享读权限,KJUSEREX对应独占写权限。KR mode的读请求通常先申请KJUSERSH模式,如果发生写操作并且存在并发读,就会触发锁升级和块传递。真正产生等待的瞬间,往往是请求节点需要的模式与持有节点当前持有的模式不兼容,或者请求需要跨多个节点完成三向协商(3-way),这时就会出现gc cr block 2-way或gc current block 3-way等事件。
常见KR mode相关等待事件与诊断方法
KR mode最直接的表现就是各种gc等待事件。比如gc cr block 2-way表示一致性读块请求只涉及两个节点之间的传递,而gc cr block 3-way表示请求节点、持有节点和主节点三者之间的协商。通常3-way事件的平均等待时间会高于2-way,因为多了一次网络往返。gc current block busy表示请求当前读时持有节点正忙于处理其他请求,导致请求节点必须等待。gc buffer busy acquire/release则对应全局缓存层面的缓冲区忙等待,与本地buffer busy waits类似,但跨节点影响更大。
要诊断KR mode下的性能问题,首先应查看AWR报告中的“Global Cache Statistics”部分。重点关注两项:一是“Global Cache blocks received”与“Global Cache blocks served”的比例,如果接收远大于本地读取,说明应用跨节点访问严重;二是各gc等待事件的“Avg Wait Time”,如果gc cr block 3-way的平均等待超过几个毫秒,可能意味着私有网络延迟偏高或LMS进程吞吐不足。其次是查询动态性能视图,找出当前正在等待gc事件的会话以及它们访问的对象。
SELECT s.inst_id, s.sid, s.serial#, s.sql_id,
s.event, s.p1text, s.p1, s.p2text, s.p2,
o.owner, o.object_name, o.object_type
FROM gv$session s
LEFT JOIN dba_objects o
ON s.row_wait_obj# = o.object_id
WHERE s.event LIKE 'gc%'
ORDER BY s.inst_id, s.sid;
上面的查询将当前等待gc事件的会话与热点对象关联起来。如果p1或p2中带有数据块地址和文件号,可以进一步结合dba_extents定位具体段。对于历史问题,可以分析DBA_HIST_ACTIVE_SESS_HISTORY,按event和current_obj#聚合,找出过去一段时间内KR mode相关等待最严重的对象。
SELECT ash.event,
ash.current_obj#,
o.owner,
o.object_name,
COUNT(*) AS wait_count,
AVG(ash.wait_time + ash.time_waited) / 1000 AS avg_wait_ms
FROM dba_hist_active_sess_history ash
LEFT JOIN dba_objects o
ON ash.current_obj# = o.object_id
WHERE ash.event LIKE 'gc%'
GROUP BY ash.event, ash.current_obj#, o.owner, o.object_name
ORDER BY wait_count DESC;
需要注意的是,DBA_HIST_ACTIVE_SESS_HISTORY中的等待时间单位是微秒,除以1000转换为毫秒。诊断时不要只看总等待次数,还要结合平均等待时间判断是网络问题还是锁争用问题。例如,如果gc cr block 3-way的平均等待很低但次数极高,可能只是正常的缓存融合流量;如果平均等待持续偏高,则需要检查私有网络和LMS进程。
优化KR mode全局缓存性能的实用策略
减少KR mode等待的核心目标是降低跨实例的数据块请求频率和缩短单次请求的延迟。从应用设计层面,最有效的手段是数据分区和实例亲和性。通过将经常被同一类事务访问的分区固定到特定实例,可以大幅减少Cache Fusion的块传递。Oracle的Services特性允许将连接路由到首选实例和备用实例,配合应用侧的连接池配置,能够让读请求尽量在本地完成。对于高频更新的小表,可以考虑使用本地缓存或者将表设计为哈希分区并按照业务键路由,从而物理隔离热点。
在SQL和对象层面,减少不必要的全表扫描和低效索引扫描同样重要。一条SQL如果执行计划有误,可能扫描几百万个块,而这些块分布在其他实例的缓存中,自然会引发大量gc cr request。通过优化执行计划、建立合适索引、避免函数索引失效等手段,可以从源头减少KR mode的请求量。此外,对于序列(Sequence),可以考虑使用CACHE和NOORDER选项,降低跨实例获取下一个值时产生的全局锁竞争。
在集群和网络层面,务必使用专用的高速互联(如万兆以太网、InfiniBand),并将私有网络的MTU设置为最大值,减少分片。LMS(Global Cache Service Process)进程的数量和优先级也直接影响块传递速度。默认情况下Oracle会自动设置LMS数量,但在高并发环境下可以适当增加,但不要超过CPU核数的一半。可以通过以下SQL查看实例上的LMS进程数量以及它们的活动状态。
SELECT inst_id, program, status, COUNT(*) AS process_count FROM gv$process WHERE program LIKE '%LMS%' GROUP BY inst_id, program, status ORDER BY inst_id, program;
除了LMS,还应该监控私有网络的吞吐量和延迟。使用操作系统命令如ping、netstat、mpstat可以初步判断网络是否成为瓶颈。如果网络延迟超过1毫秒,或者在业务高峰期出现丢包,那么任何KR mode请求都会被放大。最后,定期收集AWR基线,对比优化前后的Global Cache Statistics,可以量化调优效果。对于极少数情况,可以考虑调整隐含参数如_gc_defer_time或_gc_policy_time,但必须在Oracle Support指导下进行,否则可能引发更严重的性能抖动。
通过应用、SQL、网络和实例参数四个维度的协同优化,KR mode带来的等待可以从数百毫秒降低到几毫秒,从而显著改善RAC集群的整体响应速度和扩展能力。
Oracle RACglobal cacheKR mode修改时间:2026-09-24 14:54:31