gc cr request等待时间长主因是rac下执行计划被调度至不合适的节点,引发跨节点cr块拉取、索引块争抢及残留并行资源干扰;优化需服务绑定、强制本地并行、调整亲和性与分区策略,而非固化执行计划。
gc cr request 等待时间长,不是 sql 执行计划本身错了,而是计划在 rac 架构下被调度到了不合适的节点上执行——尤其当它引发大量单块访问、跨节点索引扫描或残留并行资源时。
为什么 USE_NL + INDEX 提示在 RAC 下反而拖慢 gc cr request
显式写 USE_NL 和 INDEX 在单实例可能快,但在 4 节点 RAC 中极易放大 gc cr request:
-
USE_NL要求驱动表逐行探查被驱动表,若被驱动表数据块分散在多个节点 buffer cache 中,每次探查都触发一次跨节点 CR 块拉取 -
INDEX(MBF, IDX_MT_BIZ_FIN_DATE)若该索引是非分区本地索引,且查询条件(如时间范围)导致叶块集中在某节点,其他节点反复争抢同一组索引块,CR 构造压力陡增 - 更隐蔽的是:前一次并行查询中断后,部分 PX slave 或临时段未清理,后续串行执行仍受残留 latch 影响,使原本应本地完成的索引访问被迫走 GC 路径
优化方向不是“锁死执行计划”,而是让 SQL 在合适节点以合适方式运行
盲目用 SQL Plan Baseline 或 OUTLINE 固定计划,可能把问题从“等 GC”变成“等磁盘读”或“等 LMS”。真正有效的做法是分层干预:
- 服务绑定:用
srvctl modify service将业务模块绑定到特定节点组,确保关联表/索引的主数据块尽量落在该节点 buffer cache 中 - 强制本地并行:设置
ALTER SESSION SET parallel_force_local = TRUE,避免并行服务器跨节点分配,减少 GC 协调开销 - 调整亲和性:增大
_gc_affinity_time(默认 300 秒),降低主节点频繁切换概率;配合分区表按时间列做范围分区,使热点月度数据天然集中在某节点
减少物理读不能只盯执行计划,要先确认是不是“假高读”
AWR 中看到 direct path read 占 DB Time 63.1%,但 Top Read SQL 的逻辑读并不高——这往往说明物理读来自其他库的 IO 冲突,而非本 SQL 真实需要读盘:
- 用
SELECT * FROM gv$session_wait WHERE event = 'gc cr request'查看当前会话是否真在等 GC,还是卡在db file sequential read上 - 对比故障时段与基线时段的
Segments by CR Blocks Received,确认是否某张小表全扫成了跨节点热点(典型表现是gc buffer busy acquire与gc cr request同时飙升) - 检查私有网络:用
netstat -su看 UDP receive errors 是否 > 0;ping -s 8972(Jumbo Frame)测延迟,> 1ms 就需排查 MTU 或网卡中断合并设置
GC 等待的本质是块级协调,不是语句逻辑问题。最常被忽略的一点是:即使执行计划完全一样,只要服务路由、分区策略或网络状态变了,gc cr request 的实际耗时就可能从 0.3ms 涨到 8ms——而这个变化不会体现在 EXPLAIN PLAN 或 display_cursor 的输出里。











