Oracle中MLOG$_表“过期”记录指已被所有注册物化视图消费完毕且无任何活跃MV依赖的行,需交叉验证DBA_REGISTERED_SNAPSHOTS(无LOG_OWNER+LOG_NAME组合)和DBA_MVIEW_LOGS(LOG_TABLE未被引用),再用PURGE_MVIEW_FROM_LOG按最晚LAST_REFRESH_DATE清理。

怎么确认 MLOG$_ 表里哪些记录算“过期”
Oracle 不会自动删 MLOG$_ 表里的行,只靠 snaptime$$ 字段标记消费状态。所谓“过期”,是指这些记录已被所有注册的物化视图消费完毕,且再无任何活跃 MV 依赖它。
-
查日志表数据量:
SELECT log_table, master, last_refresh FROM DBA_MVIEW_LOGS WHERE log_table LIKE 'MLOG$%';
若last_refresh长期没更新(比如超过一周),且对应基表 DML 活跃,大概率是卡住了 -
必须交叉验证两个视图:
-
DBA_REGISTERED_SNAPSHOTS中查不到该日志的LOG_OWNER+LOG_NAME组合 → 说明没注册的快照在读它 -
DBA_MVIEW_LOGS中该日志的LOG_TABLE字段未被其他 MV 引用 → 注意多个 MV 可共享一个日志,得逐个核对MASTER和LOG_TABLE
-
别查
DBA_MVIEWS:它不记录日志绑定关系,查了也白查
用 PURGE_MVIEW_FROM_LOG 清理已消费的旧记录
这个过程是逻辑清理,不是物理删表,适合保留日志结构但释放空间的场景。但它不会降低高水位线(HWM),也不会返还文件级空间。
mvid必须来自DBA_BASE_TABLE_MVIEWS(不是DBA_MVIEWS),查BASE_TABLE_OWNER+BASE_TABLE_NAME对应的MVIEW_ID多个 MV 共享一个日志时,清理边界由所有 MV 中最晚的
LAST_REFRESH_DATE决定,不能只按单个 MV 清执行前加锁基表防干扰:
LOCK TABLE owner.table_name IN EXCLUSIVE MODE;-
示例调用:
BEGIN DBMS_MVIEW.PURGE_MVIEW_FROM_LOG(123); END;
其中123是从DBA_BASE_TABLE_MVIEWS查出的有效MVIEW_ID
为什么 DROP MATERIALIZED VIEW LOG 才是真正释放空间的路径
DROP MATERIALIZED VIEW LOG ON owner.table_name 是唯一能彻底删掉日志表、索引、约束的合规操作。但它不会立即返还物理空间:
该语句只是把段标记为“可重用”,尤其在 ASSM 表空间中不会自动缩回
如果想彻底回收文件级空间,需额外执行:
ALTER DATABASE DATAFILE 'xxx.dbf' RESIZE xxxM(前提是该文件内无其他活跃段)别指望
SHRINK SPACE对sys.mlog$_xxx有效——Oracle 明确不支持对系统用户下的这类日志表做 shrink误用
TRUNCATE TABLE sys.mlog$_xxx或DROP TABLE sys.mlog$_xxx会破坏数据字典,后续建日志大概率报ORA-12083,刷新可能静默退化或直接失败
容易被忽略的刷新机制细节
-
PURGE_MVIEW_FROM_LOG 实际清理的是 snaptime$$ 小于指定 MV 最后刷新时间的记录。如果该 MV 的 LAST_REFRESH_DATE 远早于日志中最小的 snaptime$$,调用会因 SCN 断层失败
-
DBA_REGISTERED_SNAPSHOTS 中的 SNAPID 是消费凭证,后续 purge 必须用到它,不能随便填数字
- 重建日志后必须立刻做三件事:收集统计信息、重建
snaptime$$/sequence$$ 索引、确保 WITH 子句参数(如 PRIMARY KEY、INCLUDING NEW VALUES)匹配原刷新逻辑,否则 FAST 刷新会静默退化
PURGE_MVIEW_FROM_LOG 实际清理的是 snaptime$$ 小于指定 MV 最后刷新时间的记录。如果该 MV 的 LAST_REFRESH_DATE 远早于日志中最小的 snaptime$$,调用会因 SCN 断层失败 DBA_REGISTERED_SNAPSHOTS 中的 SNAPID 是消费凭证,后续 purge 必须用到它,不能随便填数字 snaptime$$/sequence$$ 索引、确保 WITH 子句参数(如 PRIMARY KEY、INCLUDING NEW VALUES)匹配原刷新逻辑,否则 FAST 刷新会静默退化 真正的难点不在命令本身,而在判断“谁还在用它”——交叉验证 DBA_REGISTERED_SNAPSHOTS 和 DBA_MVIEW_LOGS 这一步漏掉任何一个结果,后续操作就全是风险。


















