FAST刷新必须显式创建物化视图日志,且字段须与MV SELECT列严格对齐、含ROWID和SEQUENCE,基表需主键或唯一约束,MV定义须满足语义限制(如仅支持INNER/部分LEFT JOIN、禁用DISTINCT/GROUP BY等),并明确指定REFRESH FAST ON COMMIT或ON DEMAND,否则静默降级为COMPLETE。

FAST刷新必须显式创建物化视图日志
没建日志,REFRESH FAST 就是空谈。Oracle 不会自动为基表补日志,漏掉这步,后续所有配置都无效。
日志字段必须和物化视图 SELECT 列严格对齐:如果 MV 里写了 UPPER(ename),日志里得包含原始列 ename,不能只记表达式结果;如果 MV 查询含 deptno,日志定义里也必须显式列出 deptno。
-
ROWID和SEQUENCE是强制要求,缺一不可 —— 否则报ORA-12052 - 涉及
UPDATE场景,必须加INCLUDING NEW VALUES,否则旧值丢失导致刷新失败 - 基表加了新列?日志不会自动同步,得手动
ALTER MATERIALIZED VIEW LOG ... ADD (new_col)
物化视图定义必须满足 FAST 语义限制
即使日志齐全、字段对齐,MV 定义本身不合规,Oracle 也会静默降级为 COMPLETE 刷新,且不报错 —— 只在 DBA_MVIEWS 中把 FAST_REFRESHABLE 设为 NO。
- 禁止使用
SYSDATE、ROWNUM、子查询中的聚合嵌套分析函数 -
JOIN仅支持INNER JOIN和部分LEFT OUTER JOIN;FULL OUTER或RIGHT OUTER直接禁用 FAST - 不能有
DISTINCT、GROUP BY(除非是基于主键的聚集 MV,且日志含PRIMARY KEY) - 基表必须有主键或唯一约束,且 MV 定义中要引用全部主键列
刷新触发时机必须明确指定,不能依赖默认
REFRESH FAST 本身不是完整指令 —— Oracle 需要知道“什么时候刷”。默认是 ON DEMAND,意味着不调用就不会刷。
- 要自动刷,必须写
REFRESH FAST ON COMMIT,否则 COMMIT 后数据已变,MV 仍 stale - 若用
ON DEMAND,刷新必须显式执行DBMS_MVIEW.REFRESH('mv_name', 'F');错传'C'就全量刷了 -
FORCE是默认方式,但它只是“尝试 FAST,失败就 COMPLETE”,不解决根本问题
验证是否真走增量路径,别信表面成功
执行 DBMS_MVIEW.REFRESH 返回成功,不代表走了 FAST。真正判断依据是日志表里的变更是否被消费。
- 查日志状态:
SELECT ROWIDS, SEQUENCE FROM DBA_MVIEW_LOGS WHERE MASTER = 'EMP',确认均为YES - 查 MV 能力:
SELECT CAN_USE_LOG, STALENESS FROM DBA_MVIEWS WHERE MVIEW_NAME = 'MV_EMP_DEPT',CAN_USE_LOG = 'NO'就说明日志不匹配 - 验证增量生效:
SELECT COUNT(*) FROM MLOG$_emp WHERE SNAPTIME$$ > (SELECT LAST_REFRESH_DATE FROM DBA_MVIEWS WHERE MVIEW_NAME = 'MV_EMP_DEPT'),结果非零才说明有增量数据被处理 - 刷新失败时先跑
EXEC DBMS_MVIEW.EXPLAIN_MVIEW('mv_name'),再查MVIEW_EXCEPTIONS表,它会指出哪条规则不满足
SNAPTIME$$ 字段不是全局时钟,而是每个 MV 自己维护的水位线;一旦刷新中断或目标库不可达,这个值不会自动回退,后续 FAST 就可能读不到变更,直接报 ORA-12034。这种状态得人工干预,不是重跑一遍就能恢复。


















