根本原因是并行全表扫描强制触发大量跨节点GC块传输,因未启用Direct Path Read、未绕过Buffer Cache且并行负载未合理分发,导致私网被gc cr/current block busy等待塞满。

Oracle RAC跨节点大表全表扫描引发私网拥堵,根本原因不是“扫描本身慢”,而是并行执行路径强制触发大量跨实例Global Cache(GC)块传输,而默认配置下这些流量未绕过Buffer Cache、未启用Direct Path Read、也未合理分发并行负载——结果就是私网瞬间被海量gc cr block busy和gc current block busy等待填满。
为什么全表扫描会走GC路径而不是本地读?
默认情况下,RAC中全表扫描仍依赖Buffer Cache,哪怕数据块物理上只存于一个节点的磁盘。当其他节点的PX进程发起扫描请求时,Oracle必须通过私网把目标块从“拥有实例”拉到“请求实例”的buffer cache中——这本质是gc cr request流程。只要没触发Direct Path Read,就绕不开GC协调。
- 表段大小 _small_table_threshold(默认约Buffer Cache的2%),优化器直接判定为“小表”,强制走cache路径
-
parallel_force_local = TRUE被启用,即使写了/*+ parallel(t 8) */,所有PX进程也被钉死在单节点,但 coordinator 仍需跨节点拉取非本地块 - 统计信息陈旧,
NUM_ROWS被严重低估,优化器误判为“小表”,跳过Direct Path Read决策
并行度设置不当会放大私网压力
RAC中盲目提高parallel值,不等于吞吐翻倍,反而可能让私网带宽成为瓶颈。因为每个PX进程都独立发起GC请求,而LMS进程无法合并请求,导致相同块被反复传输。
- 未分区的大表 +
parallel > 4→ 多个PX进程同时争抢同一组数据文件块,触发高频gc current block busy - 基表无分区,但物化视图日志表(
MLOG$_xxx)也未按相同列分区 → 刷新与扫描并发时,GC热点集中在日志表头部块 -
parallel_max_servers设得过高,大量PX进程挤占私网UDP缓冲区,触发netstat -su中UDPInOverflows上升
如何验证私网是否真因扫描而过载?
别只看top或vmstat,要抓RAC特有指标:
- 查AWR报告中“Global Cache and Enqueue Statistics”部分:
gc cr block lost或gc current block lost持续 > 0.1%,说明私网已丢包 - 运行
SELECT * FROM v$sysstat WHERE name LIKE 'gc%block%';,对比gc cr blocks served与gc cr blocks received比值:若远大于1,说明大量块被重复服务 - 用
tcpdump -i <private_if> udp port 61000-65000 -w gc_trace.pcap</private_if>抓包,过滤出巨量小包(8900字节),即MTU未生效或流量未走Jumbo Frame
真正卡点往往藏在“默认行为”里:比如_serial_direct_read=auto在19c中对并行扫描不生效,必须显式加/*+ direct */ hint;又比如ALTER TABLE ... PARALLEL 8没带INSTANCES子句,实际并行仍被限制在单实例——这些细节不验就不知道。


















