物化视图日志本身不生成undo,但会延长主事务undo保留时间;因快速刷新依赖旧镜像,若日志未及时消费,undo无法覆盖,导致ora-01555错误。

物化视图日志本身不生成UNDO,但会显著延长主事务的UNDO保留需求
物化视图日志(MLOG$ 表)记录的是基表的变更向量(DML时间戳、ROWID、变更类型),它本身不写UNDO;但它会让主事务的UNDO“不敢被覆盖”——因为快速刷新依赖这些变更对应的旧镜像来构造增量数据。只要物化视图日志未被消费(如刷新作业卡住、禁用、或刷新间隔远大于 UNDO_RETENTION),主库就必须保留从上次刷新点起的所有UNDO,否则刷新时读取基表老版本就会触发 ORA-01555。
典型现象:某张基表上无长查询、也无大事务,但只要关联的物化视图日志存在且长期未刷新,该表的任意SELECT(甚至简单COUNT)都可能报错;v$undostat.maxquerylen 突然飙升到数小时,远超业务SQL实际耗时。
查物化视图日志是否堆积 + 刷新状态是否异常
先确认问题源头是不是物化视图日志滞留:
- 查未消费的日志条目数:
SELECT master, log_table, oldest_new_time, youngest_new_time FROM dba_mview_logs;—— 若oldest_new_time是 2 天前,说明至少有 2 天的变更没被刷新消费 - 查刷新作业是否失败或停摆:
SELECT name, last_refresh_date, refresh_mode, build_mode FROM dba_mviews WHERE master = 'YOUR_TABLE_NAME'; - 查是否有物化视图处于
BUILD DEFERRED或REFRESH COMPLETE ON DEMAND状态却从未手动刷新过,这类物化视图的日志会无限累积 - 特别注意:如果物化视图是
FAST刷新但基表缺少主键或唯一约束,Oracle会静默退化为完全刷新,导致日志持续堆积却不触发实际刷新
物化视图日志导致的ORA-01555必须从主库UNDO侧解决
备库或只读实例上查物化视图日志毫无意义——日志在主库,UNDO也在主库。你在备库看到 ORA-01555,根源一定是主库的 UNDO_RETENTION 不足以覆盖“最后成功刷新时间”到“当前查询启动时间”的窗口。
关键动作不是删日志,而是让刷新跟上节奏:
- 立即执行一次强制快速刷新:
EXEC DBMS_MVIEW.REFRESH('MV_NAME', 'F');—— 若失败,看报错是否含ORA-12004(需重建日志)或ORA-12034(日志太旧,需全刷) - 若日志已严重滞后,先停掉写入,用
COMPLETE刷新重建物化视图,再重新启用快速刷新 -
UNDO_RETENTION必须 ≥ 最大预期刷新间隔 × 1.5;例如日志每 30 分钟刷一次,设为2700(45 分钟)以上 - 务必同时启用
RETENTION GUARANTEE:ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;—— 否则即使设了 2700,空间紧张时仍会被覆盖
不要手动清空MLOG$表
直接 TRUNCATE TABLE mlog$_xxx 或 DELETE FROM mlog$_xxx 是高危操作:
- 破坏物化视图刷新一致性,后续
FAST刷新必然失败并报ORA-12034 - 不会释放UNDO空间,因为UNDO是否被覆盖取决于
UNDO_RETENTION和空间压力,和日志表是否为空无关 - 可能导致基表DML阻塞(日志锁争用),尤其在RAC中
- 正确做法是先确保刷新正常运行,再通过
DBMS_MVIEW.PURGE_LOG安全清理已消费日志:EXEC DBMS_MVIEW.PURGE_LOG('OWNER', 'TABLE_NAME');
物化视图日志引发的 ORA-01555 本质是“时间窗口管理失控”,不是空间不够——哪怕UNDO表空间有100GB空闲,只要刷新断档超过 UNDO_RETENTION,照样报错。盯紧 oldest_new_time 和 tuned_undoretention 的差值,比调参更有效。











