parallelism参数需配合会话级ALTER SESSION ENABLE PARALLEL DML才生效,且仅在atomic_refresh=>FALSE时起作用;设为TRUE会导致假并行,资源争用加剧。

parallelism参数不等于实际并发度,必须配对启用PARALLEL DML
单独在DBMS_MVIEW.REFRESH里设parallelism => 8基本没用——Oracle 19c+要求会话级先执行ALTER SESSION ENABLE PARALLEL DML,否则所有并行参数都被忽略。漏掉这步,哪怕基表加了PARALLEL 32,刷新也全程串行。
验证是否生效:刷新过程中查V$PX_SESSION,若只看到1个Q000进程,说明并行根本没起来;正确应有多个Q00x进程且server_group一致。
- 必须在同一会话中执行:先
ALTER SESSION ENABLE PARALLEL DML,再调用DBMS_MVIEW.REFRESH,不能跨会话或依赖ALTER SYSTEM - 不要全局开启
PARALLEL DML:它会影响其他DML语句行为,会话级控制更安全 -
parallelism值只在atomic_refresh => FALSE时才真正生效;设为TRUE时,并行进程全挤在一个事务里等提交,反而加剧CPU争用
parallelism设太高反而触发资源争用和锁等待
实测稳定区间是4–8;超过这个范围,收益快速递减,且极易引发新问题:
- 超过
parallel_max_servers上限,会排队等待并行slave,出现enq: PS - contention等待事件 - PGA内存被大量抢占,拖慢其他会话,甚至触发
ORA-04030(无法分配PGA) - UNDO段压力陡增,尤其含LOB列时,可能直接报
ORA-12853(并行slaves不足)或ORA-01555(快照太旧) - 检查当前限制:
SHOW PARAMETER parallel_max_servers,再结合SELECT COUNT(*) FROM dba_data_files WHERE tablespace_name = (SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_TEMP_TABLESPACE')确认临时表空间数据文件数
高并发刷新场景下,必须关掉atomic_refresh => TRUE
默认atomic_refresh => TRUE会让刷新走“建临时表→全量插入→原子替换”路径,所有并行进程共享一个大事务,锁、UNDO、PGA全被锁死,CPU使用率飙升且响应时间不可预测。
改为FALSE后,Oracle退回到TRUNCATE + INSERT /*+ APPEND */直写模式,每个并行批次独立提交,资源释放快,CPU曲线更平滑。
- 但必须满足前提:物化视图定义不含聚合、JOIN、子查询、DISTINCT;否则Oracle悄悄忽略
atomic_refresh => FALSE,仍走默认路径 - 业务需容忍TRUNCATE瞬间的不可用(通常毫秒级,但大表可能达秒级)
- 调用示例:
DBMS_MVIEW.REFRESH('MV_SALES', method => 'C', atomic_refresh => FALSE, parallelism => 6)
别让REFRESH_ALL_MVIEWS成为并发放大器
DBMS_MVIEW.REFRESH_ALL_MVIEWS默认按字典顺序刷,不感知依赖关系,也不控制单次并发粒度。若同时调度多个该任务,会叠加触发大量并行进程,CPU瞬间拉满。
替代方案是显式控制刷新链路:
- 用
DBMS_MVIEW.REFRESH_DEPENDENT传入基表名,它自动逆向遍历依赖树,按拓扑顺序逐个刷新,天然限流 - 对关键MV,拆成单个调用+重试逻辑,失败时记录
SQLERRM而非中断整批 - 避免在定时任务中硬编码
parallelism => 16——高峰期应动态降为4,低峰期再升,可通过DBMS_SCHEDULER绑定不同窗口
真正卡CPU的从来不是并行本身,而是并行与事务模型、锁粒度、资源上限三者错配。最常被忽略的是:parallelism > 1 且 atomic_refresh => TRUE 的组合,它把并行变成了“假并行”,所有线程在等同一个事务提交。











