物化视图交换分区后不走fast刷新,因mlog$_xxx不记录exchange元数据操作,导致增量日志为空;必须满足pct全部硬性条件(同列分区、含聚合、enable query rewrite/pct、row movement启用),并用partition_change_refresh或手工补日志恢复。

交换分区后物化视图为什么突然不走FAST刷新?
因为Oracle的物化视图日志(MLOG$_xxx)不感知分区EXCHANGE操作——它只记录DML(INSERT/UPDATE/DELETE),而EXCHANGE PARTITION本质是元数据切换,不触发日志写入。结果就是:源表物理数据已换,但日志里没留下任何变更记录,DBMS_MVIEW.REFRESH执行FAST时发现“无增量可拉”,直接退化为COMPLETE或报ORA-12034。
必须满足的PCT(Partition Change Tracking)前提条件
PCT不是可选开关,是一组硬性约束组合,缺一不可:
- 基表和物化视图都必须按**相同列**做范围/列表分区(例如都按
sale_dateRANGE分区) - 物化视图定义中必须含聚合(如
SUM、COUNT)或GROUP BY,纯SELECT *不触发PCT - 建MV时显式声明
ENABLE QUERY REWRITE和PCTFREE 0(或类似存储参数),且DDL里带ENABLE ROW MOVEMENT - 源表必须启用
ROW MOVEMENT:ALTER TABLE t ENABLE ROW MOVEMENT,否则MOVE PARTITION会失败,间接破坏日志一致性
交换后如何手动恢复增量能力?
不能等下次自动刷新——PCT水位已断,必须人工干预:
- 先确认PCT是否启用:
BEGIN DBMS_MVIEW.EXPLAIN_MVIEW('MV_SALES'); END;,再查mv_capabilities_table中REFRESH_FAST的possible是否为Y,且msgtxt不含"partition change tracking not supported" - 若PCT未生效,重建MV并强制开启:
CREATE MATERIALIZED VIEW mv_sales ... ENABLE QUERY REWRITE PCT AS SELECT ... - 交换分区后,立刻执行一次
DBMS_MVIEW.PARTITION_CHANGE_REFRESH(注意:仅Oracle 12c+支持),传入MV名和被交换的分区名 - 若版本低于12c,只能手工补日志:在交换前,对目标分区做一次
UPDATE /*+ FULL */ SET last_modified = SYSDATE WHERE ...(需该字段在日志中),确保变更被捕获
最容易被忽略的兼容性陷阱
即使所有配置看起来正确,以下细节仍会导致PCT失效:
-
EXCHANGE时未用INCLUDING INDEXES或WITH VALIDATION,导致索引状态不一致,Oracle拒绝信任分区数据完整性 - 物化视图日志建在非分区键字段上(比如日志含
product_id,但分区键是sale_date),PCT无法映射变更范围 - 交换的分区在源表中
STATUS不是USABLE(例如刚TRUNCATE过但未ANALYZE),DBMS_MVIEW会跳过该分区 -
SNAPTIME$$字段在MLOG$_t中被人工修改过,或因刷新失败残留脏值,必须用DBMS_MVIEW.REFRESH的ATOMIC_REFRESH => FALSE参数绕过校验
真正麻烦的不是交换动作本身,而是交换后那个没人检查的SNAPTIME$$和分区元数据一致性——它们不会报错,只会让FAST悄悄变成COMPLETE。











