运维管理7 分钟阅读
Oracle RAC 的 gc 等待高,是不是集群网络有问题?
2026年10月18日阅读—点赞—收藏—
OracleRAC
在知识库中专注阅读,并随时返回相关工具与课程
最近分析一套 Oracle 19c RAC 数据库的 AWR 报告时,看到几个等待事件:
1gc cr grant 2-way2gc cr block 2-way3gc current block 2-way看到 gc 等待,很多人首先想到的可能是 RAC 私网。这个思路并没有错,RAC 实例之间需要通过私网通信,网络延迟确实可能影响 Cache Fusion 的性能。
但问题是,
gc等待高,就一定是网络慢吗?
之前分析的这套 MES 数据库,两个实例的 AAS 分别只有 1.26 和 1.38,CPU 也有较多空闲。虽然 AWR 中出现了几个 gc 等待事件,但并没有足够证据说明 RAC 私网存在问题。
所以这次想聊的不是某个 gc 事件的定义,而是实际排查时,怎么区分正常的全局缓存访问、SQL 引起的跨实例访问,以及真正的网络异常。
Oracle RAC 的每个实例都有独立的 Buffer Cache,但访问的是同一套数据库。
假设实例 1 需要读取一个数据块,而这个数据块的合适版本可以由实例 2 提供,那么 Oracle 就可能通过 Cache Fusion 完成数据块传输,而不是重新从磁盘读取。
此外,多个实例访问同一个数据块时,还需要协调访问权限和数据块状态。这些操作都会产生一定的等待,因此,gc 等待本身并不是故障。
下面几个常见的 gc 事件,可以先这样理解:
这里最容易混淆的是 grant 和 block:
grant 主要涉及访问授权,并不意味着一定有完整的数据块从另一个实例传过来。block 则表示等待的数据块通过全局缓存机制传输。至于 2-way、3-way,描述的是消息交互形式,不是性能等级,不能简单认为 3-way 就一定比 2-way 慢。
这些概念了解即可,没必要一口气记住所有 gc 等待事件。
AWR 中出现 gc 等待,先不要急着检查网卡。
我一般先看四个指标:
这几个指标要放在一起看。
例如,同样是累计等待 200 秒:
虽然累计等待时间一样,但表现明显不同。
前者可能是高频访问带来的累计开销,后者则更值得关注单次等待延迟。不过,单次等待时间也没有一个适用于所有 RAC 环境的固定正常值。
网络架构、节点负载、数据块处理成本和业务访问模式不同,等待时间也会不同。所以,与其记一个所谓的正常阈值,不如拿异常时段和数据库平时的表现比较。
例如,平时 gc cr block 2-way 平均等待很短,某天突然升高了数倍,同时业务开始出现超时,这就值得继续排查。
还有一点需要注意:AWR 是时间段内的汇总统计。
如果业务只是偶发卡顿,最好进一步通过 ASH 查看具体时间点,而不是只看几个小时的平均值。
这是本篇文章最需要区分的地方。
如果主要是 gc cr block 2-way,说明会话在等待一致性读数据块。
这时可以重点关注:
如果主要是 gc current block 2-way,则需要进一步关注当前数据块的访问和修改情况。
例如,两个实例上的会话频繁更新相同的数据块,可能导致数据块在实例之间反复协调或传输。这种情况下,除了检查 SQL,还需要留意热点表、热点索引块,以及应用连接分布。
至于 gc cr grant 2-way,不能直接按照数据块传输等待来分析。它主要涉及一致性读访问授权,可能与数据块访问路径、资源状态等有关,需要结合其他等待事件判断。
这里并不是说:gc cr 高就一定是查询问题,gc current 高就一定是 DML 问题。
而是说,不同事件反映的等待环节不同,后续检查的重点也应该有所区别。
如果 AWR 确认 gc 等待比较突出,下一步就要找到具体的 SQL。
下面这条 SQL 可以统计指定时间段内的 gc 等待样本:
1SET LINESIZE 2002SET PAGESIZE 1003COL EVENT FORMAT A3545SELECT inst_id,6 sql_id,7 event,8 COUNT(*) samples9FROM gv$active_session_history10WHERE sample_time >=11 TIMESTAMP '2026-10-16 02:00:00'12 AND sample_time <13 TIMESTAMP '2026-10-16 03:00:00'14 AND session_state = 'WAITING'15 AND event LIKE 'gc %'16GROUP BY inst_id, sql_id, event17ORDER BY samples DESC;时间需要替换成实际异常时段。
这里的 samples 是 ASH 采样次数,不是等待事件发生次数,也不能直接当成精确的等待总时长。
查询结果出来以后,先看等待是不是集中在少数 SQL:
接下来可以按对象统计:
1SELECT inst_id,2 event,3 current_obj#,4 COUNT(*) samples5FROM gv$active_session_history6WHERE sample_time >=7 TIMESTAMP '2026-10-16 02:00:00'8 AND sample_time <9 TIMESTAMP '2026-10-16 03:00:00'10 AND session_state = 'WAITING'11 AND event LIKE 'gc %'12GROUP BY inst_id, event, current_obj#13ORDER BY samples DESC;如果发现等待集中在某个对象上,可以进一步结合 DBA_OBJECTS 定位表或索引。但要注意,CURRENT_OBJ# 不一定在所有等待场景下都有有效对象编号。
如果怀疑热点块,还需要继续检查 ASH 中的文件号、块号,以及相关 SQL 的访问情况,不能只凭对象编号判断。
如果 gc 等待集中在少数 SQL 或对象上,我一般会优先检查 SQL 和数据访问方式。
但如果出现下面几种情况,就需要进一步关注私网:
gc 等待延迟同时明显增加。检查时先确认 RAC 私网接口:
1oifcfg getif然后查看对应接口的状态和错误计数:
1ip -s link show检查网卡驱动统计:
1ethtool -S <网卡名称>如果系统启用了 sysstat,还可以查看故障期间的网络流量:
1sar -n DEV -f /var/log/sa/sa16其中 /var/log/sa/sa16 是示例路径,实际位置需要根据操作系统确认。另外,还应该结合 Clusterware 日志、网络链路及交换机侧的监控数据分析。
需要注意,ping 正常不代表 RAC 私网一定没有问题;但仅凭 gc 等待升高,也不能认定是交换机或网卡故障。
网络检查最终还是要回到同一个问题:有没有证据证明实例间通信延迟在故障时段确实出现了异常?
实际遇到 gc 等待高,我通常会按下面这个顺序分析:
1AWR 发现 gc 等待2 |3 v4等待时间和 DB Time 占比高吗?5 |6 v7与正常时段相比是否明显升高?8 |9 v10比较两个 RAC 实例11 |12 v13ASH 定位 SQL 和对象14 |15 +----------------------+16 | |17 v v18集中在少数 SQL/对象 多 SQL、多对象19 | |20 v v21检查执行计划、热点块 检查实例间通信延迟22和跨实例访问方式 及系统资源23 | |24 v v25SQL/业务访问优化 私网、CPU、日志26 | |27 +-----------+----------+28 |29 v30 调整后对比验证这不是说 SQL 和网络只能二选一,实际故障中,业务访问量增加、热点块争用和网络延迟也可能同时存在。
这个流程的作用,是根据已经掌握的证据决定先查哪里,而不是看到 gc 就直接把问题归到网络。
之前分析的这套 MES 数据库,确实出现了几个 gc 等待事件,但当时两个实例的 AAS 分别约为 1.26 和 1.38,CPU 也比较空闲。
从已经掌握的数据来看,还不能判断 gc 等待是否构成主要性能瓶颈,更没有证据证明 RAC 私网存在异常。
如果后续再次出现业务超时,我会优先获取对应时间段的 AWR 和 ASH,确认:
gc 等待是否在业务超时期间明显升高。只有把这些信息对应起来,才能进一步判断问题出在 SQL、数据访问方式,还是底层通信。
Oracle RAC 出现 gc 等待并不奇怪,关键是看等待是否异常,以及异常发生在哪个环节。排查时,不要只看等待次数,也不要看到 gc current block 2-way 就认定存在热点块。
先通过 AWR 判断等待影响,再用 ASH 找到 SQL 和对象。如果等待集中在少数业务对象上,就优先分析数据访问方式;如果多个实例、多个 SQL 的等待延迟同时升高,再结合操作系统和 Clusterware 检查私网。
gc 等待高,不一定是网络慢。先弄清楚数据块为什么需要跨实例访问,再判断通信过程是否真的变慢。
这比直接从网卡和交换机开始排查更有针对性。