ORA-12034表示物化视图日志中记录的变更时间戳(SNAPTIME$$)晚于该物化视图已知的最后刷新时间,本质是多MV共享日志时,任一MV的last_refresh滞后导致日志校验失败。

ORA-12034到底在报什么
它不是日志“太新”,而是日志里记录的变更时间戳(SNAPTIME$$)比当前物化视图已知的“最后刷新点”还晚,Oracle 拒绝用“未来”的数据去刷“过去”的视图。本质是多个物化视图共享同一张日志时,其中某个 MV 的 last_refresh 落后于其他 MV 的最老刷新时间,导致校验失败。
查清哪个 MV 或日志拖了后腿
先看日志是否被“卡住”:
SELECT log_table, master, last_refresh FROM dba_mview_logs;
再查所有注册的 MV 中哪些没真正刷新过:
SELECT m.owner, m.name, m.mview_site, m.snapid FROM dba_registered_mviews m WHERE m.name NOT IN (SELECT object_name FROM dba_objects WHERE object_type = 'MATERIALIZED VIEW');
重点盯 SNAPID 和 last_refresh 字段——如果某条记录的 last_refresh 是 4000-01-01 或明显过期,基本就是它导致 ORA-12034。
-
SNAPID是 purge 唯一依据,不能猜,必须从上一步查出来 - 多个 MV 共用一个基表日志时,只要有一个 MV 的
last_refresh滞后,整个日志就“不可用” - 别信
DBA_MVIEWS.STALENESS = 'FRESH',它不反映日志内部时间戳状态
安全清理无效注册和残留日志
不能直接删 MLOG$_* 表,也不能 truncate,否则触发 ORA-12034 或 ORA-12091。必须走 Oracle 认可的注销路径:
第一步:锁定基表防干扰
LOCK TABLE <master_table> IN EXCLUSIVE MODE;
第二步:注销已删除但注册残留的 MV
EXEC DBMS_MVIEW.UNREGISTER_MVIEW('OWNER', 'MV_NAME', 'MVIEW_SITE');
注意:MVIEW_SITE 必须和 DBA_REGISTERED_MVIEWS.MVIEW_SITE 完全一致(大小写、域名、端口);填错直接报 ORA-12006。
第三步:用上一步拿到的 SNAPID 清理日志
EXEC DBMS_MVIEW.PURGE_MVIEW_FROM_LOG('OWNER', 'MASTER_TABLE_NAME', SNAPID);
执行完立刻查 MLOG$_<table> 行数,应明显下降;若没变,说明 purge 未生效,大概率是没锁表或 SNAPID 错了。
重建日志前先确认 MV 定义是否真支持 FAST
即使修复了 ORA-12034,FAST 仍可能静默退化为 COMPLETE。关键看 DBA_MVIEWS.FAST_REFRESHABLE 是否为 YES:
- 如果值是
NO,说明 MV 定义本身不满足 FAST 条件(比如用了SYSDATE、分析函数、外连接、漏主键列) - LOB 列被排除出日志,但 MV 查询里还选了它(如
SELECT id, content FROM t),也会让 FAST 失效并报 ORA-12034 或 ORA-12008 - 建日志时漏了
INCLUDING NEW VALUES,UPDATE/DELETE 变更无法捕获,FAST 必然失败
真正容易被忽略的是:日志重建后,必须确保所有依赖它的 MV 都重新注册(即重新创建或刷新一次),否则 SNAPTIME$$ 时间线就断了。


















