物化视图日志(MLOG$_)膨胀是IO飙升的直接原因,主因是DML频繁但日志未及时消费,导致append写和全表扫描激增;需检查日志表大小、刷新配置、错峰调度、ATOMIC_REFRESH=FALSE及Checkpoint滞后。

物化视图日志(MLOG$_)膨胀是IO飙升的直接推手
高频刷新本身不写IO,但刷新频率高往往意味着源表DML频繁,而物化视图日志
- 查日志表大小:
SELECT owner, segment_name, bytes/1024/1024 mb FROM dba_segments WHERE segment_name LIKE 'MLOG$%' ORDER BY mb DESC,单个超5GB基本就是IO瓶颈源 - 确认是否建了日志但没配刷新:
SELECT log_table, master, rowids, primary_key FROM user_mview_logs,若rowids为NO且没主键,增量刷新会退化成全量扫描 - 别依赖“自动刷新”:
DBMS_MVIEW.REFRESH_ALL_MVIEWS这种批量调用会让多个MLOG$_在同一窗口被扫,IO瞬间叠加
刷新策略必须按业务节奏切分,不能一刀切
把“每天刷一次”改成“每小时刷一次”,IO压力未必线性上升——但若所有物化视图都在整点触发,就会形成IO脉冲。关键不是频次数字,而是错峰+粒度。
- 拆list参数:不要用
list => 'MV_A,MV_B,MV_C'一次性刷,改用三次独立调用,中间间隔3–5分钟 - 区分冷热:报表类MV(如
MV_SALES_MONTHLY)用COMPLETE+ 低频(每周日凌晨);明细类MV(如MV_ORDERS_REALTIME)用FAST+ 高频(每15分钟),但必须确保基表有ROWID或主键 - 禁用无效刷新:检查
dba_mviews里last_refresh_date和staleness,对长期STALE但实际无人查询的MV,直接停掉调度
ATOMIC_REFRESH=FALSE + parallelism=2 是IO可控的黄金组合
ATOMIC_REFRESH=TRUE(默认)等于强制事务级truncate+insert,每行都记undo;而ATOMIC_REFRESH=FALSE走DDL级交换段,跳过undo生成、减少redo、释放临时段更快——这对IO是实打实的减压。
- 并行度别贪大:
parallelism => 4在OLTP时段可能抢光buffer cache,建议从2起步,配合ATOMIC_REFRESH => FALSE测试 - 显式指定临时表空间:
ALTER SESSION SET TEMPORARY_TABLESPACE = 'TEMP_MV',避免和OLTP共用TEMP引发争用 - 失败不回滚:
refresh_after_errors => TRUE防止单个MV刷崩导致整个列表卡死、undo段持续膨胀
Checkpoint滞后才是IO问题的隐藏放大器
当MLOG$_写得太快,DBWn忙于刷它的脏块,其他业务表的脏块就堆着不动——这会拖慢Checkpoint,反过来又让redo buffer flush变慢,log file sync等待飙升,IO看起来更糟。
真要定位,别只看v$sysstat,盯住:SELECT (CHECKPOINT_CHANGE# - LAST_CHANGE#) diff FROM v$database,差值长期>10万SCN,说明Checkpoint已脱节。此时压低物化视图刷新频率,比调innodb_io_capacity这类MySQL参数更治本。

















