ON COMMIT刷新在生产环境基本不可用,因其每次提交均同步阻塞执行MV增量更新,导致COMMIT延迟达数秒;绝大多数场景必须选ON DEMAND,并确保FAST刷新稳定生效。

ON COMMIT 刷新在生产环境基本不可用,除非你确认写入吞吐下降 30%–60% 且单次提交延迟可接受;绝大多数场景必须选 ON DEMAND。
ON COMMIT 刷新为什么会让 COMMIT 变慢
每次 COMMIT 都会触发物化视图的增量更新逻辑:读取物化视图日志、解析变更、应用到 MV 表、维护索引、可能加锁。这不是“后台悄悄做”,而是同步阻塞事务完成。
- 常见现象:
COMMIT从毫秒级跳到数秒(有实测达 6 秒),尤其含GROUP BY或多表JOIN的 MV - 硬性前提必须全部满足:基表要有主键或唯一约束;
MATERIALIZED VIEW LOG必须含ROWID和所有 SELECT 列(含聚合键);否则建 MV 直接报ORA-12052 - 不支持表达式列(如
TRUNC(sale_date))参与 FAST 刷新,除非日志里也包含原始列sale_date
ON DEMAND 刷新不是“随便刷”,关键在 FAST 是否真生效
REFRESH FAST ON DEMAND 是生产默认选择,但“FAST”不是自动保证的——它依赖物化视图日志是否完备、查询结构是否合规、统计信息是否准确。
- 漏建日志或建日志时没加
INCLUDING NEW VALUES→UPDATE变更丢失,刷新静默降级为COMPLETE - 调度脚本里写
DBMS_MVIEW.REFRESH('MV_NAME')(缺参数)→ 默认走FORCE,一旦某次失败就全量重建,IO/CPU 爆涨 - 必须显式指定模式:用
DBMS_MVIEW.REFRESH('MV_NAME', 'F'),并搭配DBMS_MVIEW.EXPLAIN_MVIEW定期校验是否仍支持 FAST
FORCE 刷新模式是隐藏性能雷区
REFRESH FORCE 看似省心,实际在生产中极易引发雪崩。
- 它不报错也不提示降级,你只能从
DBA_MVIEW_REFRESH_TIMES.LAST_REFRESH_TYPE或V$SESSION_LONGOPS里反查才发现某次已变成COMPLETE - 一次日志损坏、统计信息过期、或基表 DDL 变更(如删列),都可能导致后续所有
FORCE调用 fallback - 临时表空间耗尽、长事务阻塞、甚至拖垮整个调度链路,都是真实发生过的故障模式
真正难的不是选 ON DEMAND 还是 ON COMMIT,而是确保 ON DEMAND 下的 FAST 刷新每次都能稳定命中——这要求日志结构、MV 定义、调度参数、监控手段四者严丝合缝,缺一不可。











