必须显式创建为REFRESH ON COMMIT,否则物化视图不会自动刷新;基表需有主键、物化视图日志已建且结构匹配、查询不含分析函数等不支持项,三者缺一不可。
必须显式创建为 refresh on commit,且基表有主键、物化视图定义满足快速刷新限制,否则建不成功或刷新不触发。
为什么直接改基表数据后物化视图没变?
Oracle 不会自动监听 DML 并刷新物化视图——哪怕你已经 COMMIT 了。默认是 ON DEMAND 模式,刷新完全被动。只有明确声明 REFRESH ON COMMIT,才会在事务提交瞬间执行刷新逻辑。
常见错误现象:INSERT INTO emp VALUES (100, 'X'); COMMIT; 后查物化视图仍无该行,不是延迟问题,是根本没配刷新模式。
- 建 MV 时漏写
REFRESH ON COMMIT→ 刷新永远不会发生 - 基表没主键(或唯一约束)→ 创建时报
ORA-12014 - MV 查询含
ROW_NUMBER()、LAG()等分析函数 → 不支持快速刷新,ON COMMIT会拒绝创建
创建时必须满足哪些硬性条件?
REFRESH ON COMMIT 不是开关,是一套联动机制:它依赖物化视图日志 + 基表约束 + 查询结构三者同时达标。
- 基表必须有主键或唯一约束:
ALTER TABLE emp ADD PRIMARY KEY (empno); - 必须先建物化视图日志:
CREATE MATERIALIZED VIEW LOG ON emp WITH ROWID, SEQUENCE(empno, ename) INCLUDING NEW VALUES; - MV 查询不能含:
SYSDATE、子查询嵌套超过一层、UNION ALL、非确定性函数 - 创建语句必须带
ENABLE QUERY REWRITE(虽非强制,但后续重写依赖它)
示例正确建法:CREATE MATERIALIZED VIEW mv_emp REFRESH ON COMMIT ENABLE QUERY REWRITE AS SELECT empno, ename FROM emp;
刷新发生在 commit 的哪一刻?
不是后台异步,也不是“commit 后马上查就看到”,而是和 commit **原子绑定**:刷新动作与事务一起提交,或一起回滚。
- 如果你的事务里修改了
emp表,然后COMMIT→ MV 刷新同步完成,新数据立刻可见 - 如果
COMMIT失败(比如违反约束),MV 也不会刷新 - 多个会话并发更新同一基表时,
ON COMMIT可能引发行级锁等待,大表慎用
验证是否生效:查 USER_MVIEWS.REFRESH_MODE 应为 COMMIT;再查 USER_MVIEW_LOGS 确认日志存在且 ROWIDS = 'YES'。
为什么有时明明 commit 了却没刷?
最常被忽略的是:刷新失败不会报错,而是静默跳过。根本原因往往不在 MV 本身,而在日志消费环节。
- 物化视图日志被 purge 过:
SELECT LAST_PURGE_DATE FROM USER_MVIEW_LOGS WHERE MASTER = 'EMP';若时间晚于你期望的刷新点,那日志已丢 - 日志表里没记录:
SELECT COUNT(*) FROM MLOG$_EMP WHERE SNAPTIME$$ > TO_DATE('2026-06-22 17:00:00', 'YYYY-MM-DD HH24:MI:SS');返回 0 → 说明 DML 根本没写入日志(可能没开日志、或没COMMIT) - MV 定义变更后未重建日志:改过基表结构(如加列)但没重建
MATERIALIZED VIEW LOG,新字段变更不会进日志
复杂点在于:它不像定时任务那样可查 USER_JOBS 是否跑挂,而是在 commit 那一瞬完成或失败,无日志、无告警、无残留痕迹——只能靠前置检查和事后验证兜底。











