根本原因是跨节点DML触发缓存融合全局协调开销且配置未对齐;必须显式启用并行DML、统一_parallel_cluster_cache_policy为ADAPTIVE、确保表空间管理合规、授予PARALLEL_DML权限、优化undo策略并避免gc_files_to_locks误配,缺一即退化串行。
根本原因不是“rac天生慢”,而是跨节点dml触发了缓存融合(cache fusion)的全局协调开销,而多数配置没对齐这个机制——它默认不为你优化,得手动调。
并行DML在RAC中默认退化为串行
即使你写了 UPDATE /*+ PARALLEL(t,16) */,只要没显式启用并行意图且满足全部前提,Oracle 就走串行路径。关键卡点有:
-
ALTER SESSION ENABLE PARALLEL DML必须执行,但仅此不够; - 目标表所在表空间必须是
AUTOALLOCATE或UNIFORM(不能是SYSTEM管理方式); - 所有实例的隐含参数
_parallel_cluster_cache_policy必须统一设为ADAPTIVE(默认是CLUSTER,会抑制跨节点并行); - 执行用户必须显式授予
PARALLEL_DML权限,且不能在FORALL块内隐式调用; - 若用
ROWID批量更新,ROWID必须来自与目标表同实例缓存的数据源,否则触发gc current block 2-way等待。
Undo配置不当直接拖垮吞吐
RAC 中每个实例独占自己的 undo 段,但并行 DML 可能跨节点修改数据,导致 undo 写入争用。常见错误配置:
-
undo_retention设得过高(如 > 3600),长事务阻塞 undo 段重用,引发enq: US - contention; - 未禁用自动调优:
ALTER SYSTEM SET "_undo_autotune" = FALSE SCOPE=SPFILE,AUM 动态延长保留时间会造成空间“假性耗尽”; - undo 表空间数据文件和 redo 日志共盘,私网广播已放大 IO 压力,再叠加共盘会雪上加霜;
- 监控时只看
V$UNDOSTAT.TUNED_UNDORETENTION,却忽略MAXQUERYLEN—— 若长期 > 1800 秒,说明长查询正在拖累整个集群的 undo 复用效率。
gc_files_to_locks误配放大GES锁争用
当 DML 集中更新几张大表时,gc_files_to_locks 配错会让全局锁争用从“文件级”恶化成“块级”,直接卡死 GES 队列:
- 查当前值:
SHOW PARAMETER gc_files_to_locks,返回*是推荐状态(自动计算),**不要手动覆盖**; - 仅当
V$SEGMENT_STATISTICS显示某文件logical reads占比超 70% 且enq: HW - contention高发时,才考虑按文件指定,例如:ALTER SYSTEM SET gc_files_to_locks='5=800' SCOPE=SPFILE; - 绝对禁止写成
'*=1000'或全文件统一调大——GES 进程会忙于分发锁,而非处理实际 DML; - 配合关闭 DRM:
ALTER SYSTEM SET "_gc_policy_time" = 0 SCOPE=SPFILE(需重启生效),避免节点间无谓迁移数据块。
私网质量差让缓存融合变成“远程取货”
Cache Fusion 不是共享内存,而是靠私网传输数据块(cr/current)。一旦私网延迟高或丢包:
-
gc cr blocks received和gc current blocks received等待陡增; -
global cache cr block receive time平均值 > 5ms 就值得警惕; - 物理读(
physical reads direct)占比升高,说明本地缓存失效频繁,被迫绕路读磁盘; - 盲目调大
db_cache_size不但无效,还可能挤压shared_pool_size,引发ORA-4031。
真正要盯的是各实例的 gv$sysstat 中 gc cr blocks served 与 gc current blocks served 的比值——如果后者远高于前者,说明写热点集中,加缓存只会加剧争用。


















