90%是因为atomic_refresh仍为默认true;必须配对设为false且日志支持fast(rowids、primary_key、sequence至少两个yes),否则parallelism无效,刷新仍串行。
为什么parallelism设了却没提速
并行刷新不生效,90%是因为atomic_refresh仍为默认true。oracle不会因为你传了parallelism => 4就自动并行——它只在atomic_refresh => false且日志结构支持fast时才真正启用并行dml。
常见现象:执行DBMS_MVIEW.REFRESH后查v$session_longops,sofar和totalwork始终相等;或v$px_session里只看到1个PX进程。
- 确认日志是否真支持FAST:
SELECT ROWIDS, PRIMARY_KEY, SEQUENCE FROM USER_MVIEW_LOGS WHERE MASTER = 'YOUR_TABLE',三者至少两个为YES - 检查物化视图状态:
SELECT broken FROM user_mviews WHERE mview_name = 'YOUR_MV',BROKEN = 'YES'时所有参数无效 - 别在12c RAC上盲目设高值:
parallelism > 4易触发enq: PS - contention,尤其当PARALLEL_MAX_SERVERS未同步调优时
atomic_refresh => FALSE必须配对使用
单独设parallelism而保留atomic_refresh => TRUE,等于给4个工人发同一把锁——他们只能排队干活。设成FALSE后,刷新变成分批提交(如每5万行commit一次),锁粒度变小,但MV在刷新中可能短暂返回新旧混合数据。
注意:这不是“最终一致性”,而是明确的中间态。如果你的应用不能容忍查询到部分新、部分旧的数据,就别开这个参数。
- 大MV刷新时务必加:
atomic_refresh => FALSE,否则极易因ORA-01555或超时中断 - 禁止同时设
refresh_after_errors => TRUE:出错跳过批次后,已提交的部分无法回滚,状态不可逆 - 验证是否生效:刷新期间查
v$transaction,应看到多个独立事务(addr不同),而非单个长事务
LOB字段让并行完全失效
含CLOB或BLOB列的物化视图,FAST刷新必然失败,因为MLOG$无法记录LOB内容差异,Oracle会静默退化为COMPLETE刷新。而COMPLETE刷新下,并行参数仅对全量重建阶段生效,且LOB复制路径本身不走并行DML。
典型报错:ORA-12008 + ORA-22992,即使源表是本地的也会触发。
- 强制走COMPLETE时,
parallelism仍有作用,但收益有限——LOB物理复制不参与并行调度 - 目标表LOB列必须与源表严格匹配:
SECUREFILE属性、CHUNK大小、MAXSIZE定义,否则刷新静默截断无警告 - 真正可行的优化是剥离LOB:把
DOC_CONTENT换成DOC_HASH和DOC_SIZE,另建按需关联视图
如何验证并行真的在跑
调度作业返回“Job created”或DBMS_MVIEW.REFRESH执行成功,不代表并行生效。你得看底层资源占用和执行痕迹。
- 刷新期间实时查:
SELECT * FROM v$px_session WHERE qcsid = (SELECT sid FROM v$mystat WHERE rownum = 1),应看到多个slave进程 - 刷完后查:
SELECT opname, sofar, totalwork FROM v$session_longops WHERE opname LIKE '%refresh%',若sofar逐步增长且小于totalwork,说明有分片 - 检查日志表膨胀:
SELECT bytes/1024/1024 AS mb FROM dba_segments WHERE segment_name = 'MLOG$_YOUR_TABLE',如果远大于实际变更行数,说明HWM悬空,先收缩再刷
并行不是银弹。在12c生产环境里,最常被忽略的是日志表清理节奏和LOB列的存在——它们会让所有并行参数形同虚设。











