物化视图日志(MLOG$_表)不会自动物理清理,仅更新snaptime$$字段标记消费状态;确认孤立日志需同时查DBA_REGISTERED_SNAPSHOTS和DBA_MVIEW_LOGS;必须用DROP MATERIALIZED VIEW LOG而非TRUNCATE/DROP TABLE操作;purge_mview_from_log可清理已消费旧记录但不释放空间;SHRINK SPACE不适用于sys.mlog$_xxx;多MV共享日志时清理边界由最晚LAST_REFRESH_DATE决定。

物化视图日志(MLOG$_ 表)不会自动物理清理,即使所有物化视图都完成了 FAST 刷新——Oracle 只更新 snaptime$$ 字段标记已消费,不删行。空间涨到 200GB 而基表才 120MB,基本就是日志堆积没被真正清理。
如何确认 MLOG$ 表是否孤立、可安全删除
不能看 DBA_MVIEWS,它不记录日志绑定关系;也不能只查有没有物化视图存在。必须验证两点:
- 查
DBA_REGISTERED_SNAPSHOTS:若LOG_OWNER和LOG_NAME(如MLOG$_EMP)组合查询返回空,则说明没有物化视图正在注册使用该日志 - 查
DBA_MVIEW_LOGS:确认该日志未被其他物化视图引用,尤其注意多个 MV 可共享一个日志,得逐个核对LOG_TABLE和LOG_OWNER - 执行前务必导出当前依赖快照:
SELECT LOG_OWNER, LOG_TABLE, MASTER, ROWIDS, PRIMARY_KEY FROM DBA_MVIEW_LOGS WHERE LOG_TABLE = 'MLOG$_EMP';
为什么不能 TRUNCATE 或 DROP TABLE sys.mlog$_xxx
直接操作 sys.mlog$_xxx 表会破坏数据字典一致性,后续建同名物化视图时大概率报 ORA-12003 或刷新失败。更隐蔽的问题是:TRUNCATE 后高水位线(HWM)虽下降,但段头块仍残留旧日志结构信息,后续插入可能触发异常扩展,甚至引发 ORA-00604 级错误。
-
TRUNCATE TABLE sys.mlog$_emp→ 立刻释放空间,但元数据未清理,Oracle 认为“日志还在”,下次CREATE MATERIALIZED VIEW会拒绝复用 -
DROP TABLE sys.mlog$_emp→ 数据字典损坏,后续 DDL 可能报ORA-12083(无法删除日志) - 唯一合规路径是走 DDL:
DROP MATERIALIZED VIEW LOG ON owner.table_name;
如何用 purge_mview_from_log 清理部分日志而非全删
当某个物化视图长期停用,但你还想保留日志供其他 MV 使用时,可用 Oracle 内置过程精准清理「已被所有活跃 MV 消费」的旧记录。关键在获取正确的 mvid:
-
mvid来自DBA_BASE_TABLE_MVIEWS(不是DBA_MVIEWS),查BASE_TABLE_OWNER+BASE_TABLE_NAME对应的MVIEW_ID - 执行前先确认该 MV 的
LAST_REFRESH_DATE是否远早于日志中MIN(SNAPTIME$$),否则purge_mview_from_log会因 SCN 断层失败 - 示例:
BEGIN DBMS_MVIEW.PURGE_MVIEW_FROM_LOG(123); END;—— 123 是从DBA_BASE_TABLE_MVIEWS查到的有效MVIEW_ID - 注意:该过程不释放段空间,仅逻辑标记清理;要收缩 HWM 还得配合
ALTER TABLE ... SHRINK SPACE(需启用行移动)
清理后空间没释放?检查表空间和 HWM
即使日志表被 DROP MATERIALIZED VIEW LOG 成功删除,对应段可能仍占空间——尤其当它属于独立表空间(如 MLOG_NORM_SPACE)时:
- 查表空间使用率:
SELECT tablespace_name, round((bytes - free_bytes)/bytes*100, 2) pct_used FROM (SELECT a.tablespace_name, a.bytes, NVL(b.free_bytes,0) free_bytes FROM (SELECT tablespace_name, SUM(bytes) bytes FROM dba_data_files GROUP BY tablespace_name) a LEFT JOIN (SELECT tablespace_name, SUM(bytes) free_bytes FROM dba_free_space GROUP BY tablespace_name) b ON a.tablespace_name = b.tablespace_name) WHERE tablespace_name = 'MLOG_NORM_SPACE'; - 若使用率 >90%,且数据文件已
AUTOEXTEND ON但接近MAXSIZE,需手动加数据文件:ALTER TABLESPACE MLOG_NORM_SPACE ADD DATAFILE '/path/to/new.dbf' SIZE 10M AUTOEXTEND ON MAXSIZE 20G; -
SHRINK SPACE不适用于sys.mlog$_xxx(系统表),只对用户创建的日志表有效;而真正被DROP掉的日志,其空间释放依赖 SMON 进程异步回收,有时需等待几分钟
最易被忽略的一点:多个物化视图共享一个日志时,清理边界由「所有依赖 MV 中最晚的 LAST_REFRESH_DATE」决定,而不是任意一个。哪怕 9 个 MV 都刷过了,只要第 10 个卡在三天前没刷,日志就一动不能动。

















