一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

为什么Oracle 12c RAC的Cache Fusion会引发严重的GC等待?

时间:2026-07-08 10:27:52 编辑:袖梨 来源:一聚教程网

GC等待高本质是跨节点争抢同一数据块,而非网络问题;gc buffer busy acquire等待的是其他会话释放数据块锁,常见于热点块并发访问、未绑定变量SQL及非本地master执行全表扫描等场景。

不是cache fusion本身有问题,而是它暴露了应用或数据访问模式的缺陷——gc等待高,本质是跨节点争抢同一块数据。

gc buffer busy acquire 等待到底在等什么

它不是等网络传输,而是等另一个会话释放对某个数据块的持有锁。比如实例1的会话A正在更新某行(持有 XCUR 锁),实例2的会话B同时想读这行(需构造 CR 块),但发现该块正被修改且未提交,就会卡在 gc buffer busy acquire 上。

常见触发场景:

  • 热点主键/索引块被多个实例高频并发访问(如订单号序列、状态字段更新)
  • 未绑定变量的循环 INSERTUPDATE,导致硬解析+缓存块反复迁移
  • 全表扫描类 SQL 在非本地 master 实例执行,强制触发大量 gc cr block busy
  • 应用未按 RAC 意图设计:本该分片的数据,却集中写入单个表分区或索引

别一上来就调网络,先看等待时间分布桶

GV$SYSTEM_EVENTgc cr block busygc current block busy 的等待时间分布:

  • 若 16ms 桶占比突增 → 真实网络抖动或中断(检查 ethtool -S ethXrx_discards 是否非零)
  • 若集中在 1ms / 4ms 桶 → 不是网络问题,是锁争用或 SQL 访问模式问题
  • 注意:ifconfig 显示的 RX/TX 字节数含以太网头,不能直接算 GC 流量利用率;真正要看的是 TCP 层有效载荷和丢包指标

定位 GC 密集 SQL 的三步法

不用猜,用数据说话:

  • GV$SQLbuffer_gets/executions 高但 disk_reads/executions 低的语句——这类 SQL 在单实例快,在 RAC 上就是 GC 杀手
  • 对可疑会话开 ALTER SYSTEM SET EVENTS '10046 trace name context forever, level 8',抓 trace 看 WAIT #1: nam='gc current block 2-way' 后面紧跟着哪条 SQL
  • 结合 GV$SEGMENT_STATISTICSglobal_cache_cr_blocks_served 高的对象,再反查其 master 节点(x$kjbrKJBRMASTER)是否与访问节点错位

能起效的隐式参数,不是越多越好

Oracle 官方不公开推荐这些,但生产验证过有效的有:

  • _gc_affinity_time = 10:让块在本地多留 10 秒,减少无谓迁移;适用于读多写少、热点稳定的场景
  • _gc_affinity_percent = 50:只有本地访问占比低于 50% 才考虑迁走块,避免“刚热起来就被踢走”
  • _gc_read_mostly_locking = TRUE:仅对显式标记为 READ ONLY 的表空间或分区生效,可大幅降低 GES 协调开销
  • 慎调 _gc_lms_processes:默认 2,设为 4 可能有用,但超过 4 容易引发 LMS 进程间竞争,反而抬高 CPU

最常被忽略的一点:GC 等待从来不是孤立存在的——它往往和 enq: TX - contentionbuffer busy waitsgc current grant 2-way 成链出现。看到一个,就得顺着链往下挖,否则只调表面参数毫无意义。

热门栏目