EXCHANGE PARTITION后物化视图STALENESS变为UNUSABLE是因元数据断裂而非刷新失败,Oracle隐式提交并切断结构映射;需先COMPILE再REFRESH,且分区键列定义必须严格一致。

EXCHANGE PARTITION后物化视图STALENESS变为UNUSABLE
不是刷新失败,而是元数据直接断裂。Oracle在EXCHANGE PARTITION执行时隐式提交,同时切断物化视图与基表的结构映射关系——哪怕只是把一个空分区换进来,DBA_MVIEWS.STALENESS也会立刻变成'UNUSABLE'。此时调用DBMS_MVIEW.REFRESH会静默忽略参数,强制退化为COMPLETE或直接报错ORA-12008。
物化视图日志不捕获EXCHANGE操作
EXCHANGE PARTITION本身不触发DML,也不写入物化视图日志(MLOG$_xxx)。即使日志建了INCLUDING NEW VALUES,它只捕获INSERT/UPDATE/DELETE,对DDL级的数据迁移完全无感。结果就是:基表分区已换,但日志里没记录任何变更,FAST刷新找不到差异行,后续刷新要么卡住,要么全量重刷。
- 验证方式:
SELECT COUNT(*) FROM MLOG$_base_table,若基表刚完成EXCHANGE但日志行数仍为0,说明捕获失效 - 日志状态检查:
SELECT status FROM dba_objects WHERE object_name = 'MLOG$_base_table',返回'INVALID'必须重建 - 重建语句必须显式包含
WITH ROWID, PRIMARY KEY, SEQUENCE,不能省略
交换后必须先COMPILE再REFRESH
跳过ALTER MATERIALIZED VIEW mv_name COMPILE直接刷新,等于对一个编译失败的对象发指令,所有刷新逻辑都会被绕过。这是最常被跳过的一步。
-
COMPILE不修复数据,只重校验元数据一致性;它让物化视图重新“认出”基表当前结构 - 执行后查
SELECT STALENESS, STALENESS_REASON FROM DBA_MVIEWS WHERE MVIEW_NAME = 'MV_NAME',确认是否回到'STALE'而非'UNUSABLE' - 只有变成
'STALE'之后,REFRESH FAST才可能真正生效
分区键列在EXCHANGE前后必须严格一致
如果交换进来的分区,其物理列定义与原表不一致(比如新增NOT NULL列、修改数据类型、删掉主键约束),即使COMPILE成功,后续FAST刷新仍会因ORA-12054失败。Oracle要求物化视图能稳定映射每一行到具体分区,列结构偏移即意味着映射失效。
- 交换前检查:
SELECT column_name, data_type, nullable FROM dba_tab_columns WHERE table_name IN ('BASE_TABLE', 'EXCHANGE_TABLE') ORDER BY column_id - 特别注意
ROWID列是否存在——EXCHANGE后的表若未启用ROW MOVEMENT,且原日志依赖ROWID,则必须重建日志并加WITH ROWID - 避免用
EXCHANGE WITH TABLE替换含虚拟列或隐藏列的表,这些列不会自动同步,极易导致UNUSABLE
EXCHANGE PARTITION后是否“可用”,不取决于数据是否一致,而取决于Oracle能否继续安全推导增量路径。这个判断发生在编译阶段,而不是刷新时。很多DBA卡在刷新失败,却忘了先看COMPILE是否通过。


















