MLOG$_表空间暴涨最直接原因是日志未被消费或清理;Oracle仅用snaptime$$标记消费状态而不自动删数据,孤立日志持续写入却永不清理,需通过DBA_MVIEW_LOGS和DBA_REGISTERED_SNAPSHOTS确认是否孤立,再用DROP MATERIALIZED VIEW LOG或PURGE_MVIEW_FROM_LOG安全清理。

MLOG$_ 表没被消费或清理,是空间暴涨最直接的原因。
Oracle 的物化视图日志表(命名如 MLOG$_EMP)不会自动删数据,只靠 snaptime$$ 字段标记“是否已被某个物化视图消费”。一旦绑定的物化视图被删、停用,或刷新失败卡住,日志就变成“孤儿”,持续写入但永不清理。
怎么确认 MLOG$_ 表是不是真在撑爆空间
别猜,查系统视图:
- 运行
SELECT log_owner, log_table, master, rowids, primary_key FROM DBA_MVIEW_LOGS WHERE log_table LIKE 'MLOG$%';—— 看哪些日志还绑着活跃主表 - 执行
SELECT * FROM DBA_REGISTERED_SNAPSHOTS WHERE LOG_OWNER = 'OWNER' AND LOG_NAME = 'MLOG$_XXX';—— 若无返回,说明这个日志已无任何物化视图在用,就是孤立日志 - 注意:
DBA_MVIEWS不记录日志绑定关系,查它没用
为什么不能 TRUNCATE TABLE MLOG$_XXX 或 DROP TABLE
这不是权限问题,是 Oracle 数据字典层面的硬性约束:
-
TRUNCATE后高水位(HWM)下降,但段头块残留元信息,后续插入可能触发异常扩展,甚至报ORA-00604 -
DROP TABLE会破坏数据字典一致性;再执行CREATE MATERIALIZED VIEW LOG时大概率报ORA-12083 -
snaptime$$不更新,Oracle 仍认为“日志有效”,下次刷新继续往里写,空间又涨回来
安全清理的唯一路径:走 DDL,不是 DML
分两种情况处理:
- 确认日志已孤立(
DBA_REGISTERED_SNAPSHOTS无记录)→ 直接执行:DROP MATERIALIZED VIEW LOG ON owner.table_name; - 还想保留日志,只清已消费旧记录 → 调用
DBMS_MVIEW.PURGE_MVIEW_FROM_LOG(mvid),其中mvid必须来自DBA_BASE_TABLE_MVIEWS(不是DBA_MVIEWS),且多个 MV 共享一个日志时,清理边界由所有 MV 中最晚的LAST_REFRESH_DATE决定 -
SHRINK SPACE对sys.mlog$_xxx无效,Oracle 明确禁止对这类系统表做 segment shrink
真正容易被忽略的是:多个物化视图共享一个日志时,哪怕你只关心其中一个 MV 的刷新状态,也必须以所有 MV 中最晚的那个 LAST_REFRESH_DATE 为清理下限——早于它的记录才能安全 purge。否则会破坏未刷新 MV 的增量刷新逻辑。










