物化视图日志表(MLOG$_)堆积是归档日志暴增的常见原因,需检查user_mview_logs、DBA_MVIEW_LOGS及DBA_SCHEDULER_JOBS,确认刷新状态与日志积压,并用DBMS_MVIEW.PURGE_LOG安全清理后重建日志与刷新链路。
查物化视图日志表(MLOG$_)是否堆积
物化视图日志表是归档日志暴增的常见源头,尤其当刷新失败或长期没跑,它就会像“未取件的快递柜”一样越堆越多。先确认有没有这个表:select * from user_mview_logs。如果查到记录数巨大(比如上百万),且 log_table 列显示类似 mlog$_big_table 的名字,基本就是它了。
关键看两列:LOG_OWNER 和 MASTER,对应基表所属用户和表名;再查该日志表本身:SELECT COUNT(*) FROM MLOG$_BIG_TABLE。若远超基表变更频次(比如基表一天改100行,日志表却有50万条),说明刷新卡住了或压根没触发。
- 刷新失败时,Oracle 不会自动清理日志,只会不断追加
-
DBA_MVIEW_LOGS中的LAST_REFRESH_DATE为空或明显过期,是强信号 - 网络中断、目标库不可达、权限丢失、空间不足都可能导致刷新 Job 静默失败,不报错但停摆
验证刷新任务是否真在运行(DBA_JOBS / DBA_SCHEDULER_JOBS)
很多 DBA 以为建了定时 Job 就万事大吉,其实 Oracle 10g 后默认用调度器(Scheduler),老式 DBMS_JOB 可能已失效。直接查:SELECT job_name, state, last_start_date, next_run_date FROM dba_scheduler_jobs WHERE job_name LIKE '%MV%'。如果 state 是 DISABLED 或 STOPPED,或者 next_run_date 是昨天甚至更早,那刷新早就停了。
- 用
DBMS_MVIEW.REFRESH手动试一次:BEGIN DBMS_MVIEW.REFRESH('BIG_TABLE_MV', 'F'); END;—— 注意传'F'(FAST)而非'C'(COMPLETE),否则又刷全量、又写一堆 redo - 如果报错
ORA-12008: error in materialized view refresh path,说明基表结构变了(比如删了主键)、或物化视图日志损坏,得重建日志 - 别依赖
ON COMMIT模式——高并发 DML 下,它会让每个 commit 都卡住等刷新,业务直接挂
快速清空积压日志并重建刷新链路
别急着删表,先停掉所有相关 Job:EXEC DBMS_SCHEDULER.DISABLE('MV_REFRESH_JOB');。然后安全清日志:EXEC DBMS_MVIEW.PURGE_LOG('BIG_TABLE'); —— 这是官方接口,比 TRUNCATE MLOG$_BIG_TABLE 更稳妥,会同步清理内部状态。
之后必须重建物化视图日志,否则 FAST 刷新无法启用:CREATE MATERIALIZED VIEW LOG ON big_table WITH SEQUENCE, ROWID (id, status) INCLUDING NEW VALUES;。注意:字段列表要覆盖物化视图查询中所有涉及的列,尤其是 GROUP BY 和 JOIN 条件列,漏一个就退化成 COMPLETE 刷新。
-
WITH SEQUENCE必须加,否则增量刷新识别不了顺序 - 如果基表没主键或唯一约束,
ROWID是唯一可靠标识方式,别省 - 重建后立刻手动跑一次
DBMS_MVIEW.REFRESH(..., 'F'),确认返回无错且MLOG$_行数归零
监控归档日志增长是否真由 MV 引起(V$ARCHIVED_LOG + LogMiner)
归档暴增未必全是 MV 背锅。先看趋势:SELECT TRUNC(first_time), COUNT(*) FROM v$archived_log GROUP BY TRUNC(first_time) ORDER BY 1; 找出突增的时间点。再用 LogMiner 锁定具体对象:EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);,然后查 SELECT seg_owner, seg_name, operation FROM v$logmnr_contents WHERE seg_name LIKE 'MLOG$%' AND timestamp > SYSDATE-1;。
如果结果里高频出现你的 MLOG$_ 表名,且 operation 是 INSERT,那基本坐实。这时候再检查物化视图定义:SELECT refresh_method, build_mode, fast_refreshable FROM dba_mviews WHERE mview_name = 'BIG_TABLE_MV'; —— 如果 fast_refreshable 是 NO,说明建的时候就没满足增量条件(比如没建日志、查询含 SYSDATE、用了不支持的函数),后面所有优化都是白忙。
复杂点在于:物化视图日志本身不产生归档,但它的刷新动作(尤其是 COMPLETE)会触发大量 DML,这些 DML 才真正写归档。所以问题永远在“刷新行为”,不在“日志表存在”。

















