gc cr request等待过高主因是服务路由错配导致跨节点CR拉取,应优先检查服务绑定、分区策略及客户端连接配置,而非调整SQL或隐式参数。

gc cr request等待过高,不是执行计划写错了,而是SQL被调度到了不该去的节点上执行——服务绑定、分区策略、亲和性参数比hint更管用。
查是不是服务路由错配导致跨节点CR拉取
AWR里看到gc cr request平均等待时间跳到5ms以上,先别调_gc_affinity_time或改SQL hint。真正该看的是业务流量是否被负载均衡器或SCAN IP随机打散到所有节点,而核心表/索引实际只缓存在1个节点。
- 用
srvctl config service -s <service_name>确认该服务是否绑定了首选实例(PREFERRED) - 查
gv$session中对应SQL的inst_id和sql_id,再关联gv$sql_plan看访问的表/索引是否在该实例buffer cache中有高命中率(buffer_gets/executions高但disk_reads/executions极低) - 若发现SQL总在节点2执行,但
gv$bh显示热点块90%在节点1缓存,说明服务没绑定,或者客户端连接串没指定SERVER=DEDICATED导致被重定向
识别并隔离高频CR构造的SQL模式
gc cr request暴涨往往来自几类“看起来合理、RAC下却致命”的SQL写法,它们不报错、不慢在单实例,但在多节点间反复触发CR块构造。
- 未绑定变量的循环插入:
INSERT INTO log_table VALUES (:1, :2)——每次硬解析可能走不同计划,部分走全表扫描,驱动表每行都触发一次远程CR请求 - 按非分区键查询RANGE分区表(如按
status查,但表按created_date分区)——查询分散到所有节点,本地无缓存,只能远程构造CR - 显式使用
USE_NL+INDEX提示——NL Join要求逐行探查,若被驱动表索引叶块集中在某节点,其他节点会排队争抢同一组CR块 - 序列号表高频访问(如
SEQ_ORDER_ID.NEXTVAL)——索引根块成为全局热点,CR请求密集且无法本地化
验证私网延迟是否已传导为CR延迟
私网延迟是gc cr request的底层放大器,但不能只看ping值。必须用私网IP、两两互测、带-c 10参数,且盯住avg而非mdev。
- 在每个节点执行:
ping -c 10 <node2_private_ip>,重复测所有节点对(node1→node2、node1→node3、node2→node3…) - 若某对avg > 0.5ms,立刻检查交换机buffer配置、jumbo frame是否全链路一致——MTU混用(比如部分设1500、部分设9000)是常见死因
- 同时查
GV$SYSTEM_EVENT中gc cr request的等待时间分布桶:若16ms桶占比突增(如从8%升至35%),才说明是真实网络抖动;若集中在1ms/4ms桶,问题大概率在SQL或数据分布
调整亲和性参数前先确认是否真有效
_gc_affinity_time和_gc_affinity_percent能缓解但不能替代架构优化,且效果高度依赖场景。
-
_gc_affinity_time = 10让块在本地多留10秒,仅对读多写少、热点稳定的场景有效;若业务是高频更新+强一致性,反而加剧LMS压力 -
_gc_affinity_percent = 50必须配合_gc_affinity_time使用,否则无效——它表示只有当本地访问占比低于50%时才考虑迁移块 - 修改前务必在测试环境验证:用
ALTER SYSTEM SET "_gc_affinity_time"=10 SCOPE=BOTH SID='*';后,观察gv$ges_enqueue.cum_queue_time是否下降,而非只看gc cr request等待数 - 最易忽略的一点:
_gc_*隐式参数无法解决因全表扫描或索引根块争抢引发的根本流量压力,它们只是让GC“更耐抖动”
真正卡住的点往往不在数据库参数,而在服务绑定没做、分区策略没对齐、或者客户端连接串默认走SCAN IP却没指定preferred instance——这些细节不处理,调再细的隐式参数也白搭。


















