split分区后物化视图不会自动感知变更,fast刷新静默退化为complete;必须手动重建物化视图日志、验证pct已启用(pct_enabled='yes')、调用refresh时显式指定pct=>true,三者缺一不可。

Split分区后物化视图不会自动感知变更,FAST刷新会静默退化为COMPLETE,除非你手动重建物化视图日志并验证PCT路径是否启用。
Split操作本身不触发PCT刷新
Oracle的PCT(Partition Change Tracking)只响应特定DDL:SPLIT、EXCHANGE、TRUNCATE、DROP分区。但PCT生效有前提——基表必须已启用PCT,且物化视图定义中显式声明PCT ON。没加这句,哪怕执行了ALTER TABLE sales SPLIT PARTITION p_202409 AT (DATE'2024-09-16') INTO (PARTITION p_202409a, PARTITION p_202409b),REFRESH FAST仍走日志路径,而Split不写入物化视图日志(MLOG$_SALES),导致增量丢失。
验证是否启用PCT:SELECT PCT_ENABLED FROM DBA_MVIEWS WHERE MVIEW_NAME = 'YOUR_MV_NAME',返回YES才可能走PCT。
Split后必须重建物化视图日志
Split会改变分区结构,但原有物化视图日志(MLOG$_xxx)仍是建在旧分区布局上,字段元数据可能错位,甚至状态变为INVALID。此时REFRESH FAST大概率报ORA-12054或静默降级。
- 先查日志状态:
SELECT status FROM dba_objects WHERE object_name = 'MLOG$_SALES',若为INVALID,必须重建 - 重建命令不能只删再建,要带完整参数:
CREATE MATERIALIZED VIEW LOG ON sales WITH PRIMARY KEY, ROWID, SEQUENCE(sale_date, cust_id) INCLUDING NEW VALUES——注意sale_date是分区键,必须显式列入SEQUENCE - 重建后立刻验证:
SELECT column_name FROM user_tab_columns WHERE table_name = 'MLOG$_SALES' AND column_name = 'SALE_DATE',确保分区键列真实存在
REFRESH FAST调用时需指定PCT参数
即使启用了PCT且日志重建成功,调用刷新时不显式指定PCT,Oracle默认仍走日志路径。这是最容易漏的一步。
正确调用方式:DBMS_MVIEW.REFRESH('your_mv_name', METHOD => 'F', PCT => TRUE)
错误调用方式:DBMS_MVIEW.REFRESH('your_mv_name', 'F')——这个没传PCT => TRUE,就等于没开PCT。
验证本次刷新是否走了PCT:查V$MVREFRESH或刷完后看DBA_MVIEW_ANALYSIS里的LAST_REFRESH_TYPE,值为PCT才算成功;若为FAST,说明还是靠日志,得回头检查日志字段或PCT开关。
外键关联场景下Split更易失败
如果物化视图里JOIN了父表(如product),而Split的是子表(如sales_detail),REFRESH FAST ON COMMIT会因外键校验失败报ORA-12008/ORA-02291——因为Split产生的新分区数据在MV中不可见,但约束检查仍要求所有prod_id在MV内存在。
临时解法:ALTER MATERIALIZED VIEW your_mv_name REFRESH FAST ON DEMAND,改用手动刷新,并确保先刷父表MV,再刷子表MV。
根本解法:把父表关键列(如product.prod_id)显式加入物化视图SELECT列表,并确保其也在物化视图日志中(即父表也要建带SEQUENCE(prod_id)的日志)。
最常被忽略的是:Split后不重建日志、不检查MLOG$_xxx是否含分区键列、调用REFRESH时漏掉PCT => TRUE——这三个点任一缺失,都会让增量同步失效,且无明显报错。











