根本原因是MLOG$_xxx空间释放完全依赖关联物化视图的FAST刷新,而非基表DML;其清理由DBA_REGISTERED_SNAPSHOTS注册状态驱动,未消费日志(SNAPTIME$$=0x7FFFFFFF)不会因基表删除而减少,唯一安全清理方式是DROP MATERIALIZED VIEW LOG ON owner.table_name。
物化视图日志(mlog$_xxx)在大量删除基表数据后不释放空间,根本原因不是“删得不够多”,而是它压根就**不靠基表dml触发清理**——它的空间增长和释放完全由关联的物化视图(mv)刷新行为驱动。
为什么 TRUNCATE 或 DELETE 基表对 MLOG$_xxx 没影响
MLOG$_xxx 是独立段,记录的是基表变更的“增量快照”,不是基表数据的镜像。你删基表 1000 万行,只要没触发 MV 刷新,日志表里那 1000 万条变更记录就原封不动挂着,SNAPTIME$$ 字段仍为 0x7FFFFFFF(未消费标记),Oracle 认为“这些变更还没被任何 MV 拿走”。
-
TRUNCATE TABLE基表:只清空基表段,MLOG$_xxx完全不受影响 -
DELETE FROM base_table:哪怕加了 WHERE 条件,也只会往MLOG$_xxx新增一条“DELETE”类型日志,不会删旧日志 - 唯一能推动日志清理的动作是:某个依赖该日志的 MV 成功执行了
FAST刷新
空间不释放的真正瓶颈在 DBA_REGISTERED_SNAPSHOTS
日志是否可清理,不看 DBA_MVIEWS,而要看 DBA_REGISTERED_SNAPSHOTS —— 这张表才是 Oracle 内部维护“谁正在用这个日志”的权威注册表。只要其中还存在一条 LOG_OWNER + LOG_NAME 匹配的记录,哪怕对应 MV 已被 DROP,日志也不敢删。
- 常见陷阱:测试环境建过 MV 后 DROP,但忘了执行
DBMS_MVIEW.UNREGISTER_MVIEW,注册信息残留 - 多库同步场景下:
SC1.SOUCHANG.COM和SC2TEST.SOUCHANG.COM都注册了同一日志,只要其中一个 LAST_REFRESH_DATE 是 2006 年,整个日志就卡死 - 验证命令:
SELECT * FROM DBA_REGISTERED_SNAPSHOTS WHERE LOG_NAME = 'MLOG$_EMP',结果非空即风险
PURGE_MVIEW_FROM_LOG 为什么常失效
DBMS_MVIEW.PURGE_MVIEW_FROM_LOG 只清理“已被所有活跃 MV 消费”的旧记录,但它不判断 MV 是否真的还在运行,只查 DBA_BASE_TABLE_MVIEWS.MVIEW_ID 对应的 LAST_REFRESH_DATE。如果该值为空、或远早于 MIN(SNAPTIME$$),过程直接跳过,不报错也不清理。
- 典型失败场景:MV 停用半年,
LAST_REFRESH_DATE是 2025-12-01,而日志中MIN(SNAPTIME$$)是 2025-08-15 → SCN 断层,拒绝 purge - 必须先确认:
SELECT MIN(SNAPTIME$$) FROM MLOG$_EMP和SELECT LAST_REFRESH_DATE FROM DBA_MVIEWS WHERE MVIEW_NAME = 'XXX'的时间差 - 安全做法:对长期停用的 MV,先手动
UNREGISTER,再DROP MATERIALIZED VIEW LOG ON owner.table
SHRINK SPACE 和 DEALLOCATE UNUSED 都不适用
ALTER TABLE sys.mlog$_xxx SHRINK SPACE 会报错 ORA-10636,因为系统表空间下的 sys.mlog$_xxx 不支持在线收缩;DEALLOCATE UNUSED 也无效——日志表的高水位(HWM)由 Oracle 内部机制控制,不是普通段管理逻辑。
- 别试
TRUNCATE TABLE sys.mlog$_xxx:破坏数据字典,后续建同名 MV 必报ORA-12003 - 别试
DROP TABLE sys.mlog$_xxx:元数据损坏,DBA_MVIEW_LOGS视图可能异常,甚至影响其他 MV 创建 - 唯一合规路径:
DROP MATERIALIZED VIEW LOG ON owner.table_name,它会原子性清理日志段 + 注册信息 + 数据字典项
最易被忽略的一点:多个 MV 共享一个日志时,清理窗口由“最晚刷新的 MV”决定,而不是“最早停用的”。哪怕 99% 的 MV 都三年没动过,只要剩下一个每小时刷新的,日志就永远不能物理清理——得逐个核对 DBA_REGISTERED_SNAPSHOTS 和 DBA_MVIEWS.LAST_REFRESH_DATE,一个都不能漏。


















