ROWID是物化视图快速刷新的必要行定位锚点,必须与SEQUENCE成对显式声明于日志中,且在多表JOIN场景下每张基表日志均需包含WITH ROWID,否则将静默降级为COMPLETE刷新。

ROWID是物化视图快速刷新的行定位锚点
没有ROWID,Oracle 就无法把日志里的变更记录精确映射到物化视图中对应那行数据。快速刷新不是重跑SQL,而是“打补丁”:INSERT就加一行,UPDATE就改某行特定字段,DELETE就删某行——所有这些操作都依赖ROWID来定位目标行。
WITH ROWID日志必须显式声明且不可省略
建日志时只写WITH PRIMARY KEY或什么都不写,ROWID不会自动出现。即使基表有主键,REFRESH FAST仍可能失败,因为日志里缺M_ROW$$列,导致刷新引擎找不到物理行位置。
-
CREATE MATERIALIZED VIEW LOG ON emp WITH ROWID, SEQUENCE(empno) INCLUDING NEW VALUES;——这是安全起点 - 如果物化视图定义里用了
e.rowid别名(如SELECT e.rowid rid, e.empno FROM emp e),那日志必须含ROWID,否则ORA-12052报错 - 多表JOIN场景下,每张基表的日志都得单独加
WITH ROWID,不能只给主表加
ROWID失效会导致静默降级为COMPLETE刷新
某些操作会让ROWID失去稳定性,比如ALTER TABLE ... MOVE、VACUUM FULL(在兼容模式下)或分区交换后未维护日志。此时日志里的M_ROW$$指向已不存在的物理地址,Oracle 检测到不一致,会跳过FAST路径,直接执行全量刷新,且不报错。
- 查日志是否健康:
SELECT LOG_TABLE, ROWIDS FROM DBA_MVIEW_LOGS WHERE MASTER = 'EMP';,确认ROWIDS = 'YES' - 检查物化视图是否真走增量:
SELECT FAST_REFRESHABLE, LAST_REFRESH_TYPE FROM DBA_MVIEWS WHERE MVIEW_NAME = 'MV_EMP_DEPT';,若LAST_REFRESH_TYPE = 'COMPLETE'但你期望FAST,大概率是ROWID链断了 -
WITH ROWID只支持单表物化视图——含JOIN的MV必须每个基表都有自己的ROWID日志,且查询中显式引用各表rowid别名
ROWID和SEQUENCE必须成对出现才能保证顺序正确
ROWID解决“改哪行”,SEQUENCE$$解决“按什么顺序改”。两者缺一不可:只有ROWID没SEQUENCE,并发DML可能导致UPDATE和DELETE乱序应用;只有SEQUENCE没ROWID,根本不知道该对哪行施加这个序列号的操作。
- 建日志必须同时包含
ROWID和SEQUENCE,例如WITH ROWID, SEQUENCE(empno, ename) -
SEQUENCE括号里列不必全,但至少要覆盖所有被聚合或JOIN用到的列;漏掉关键列(如GROUP BY字段),ORA-12052就会出现 - 日志里
M_ROW$$和SEQUENCE$$是联合索引键,Oracle 刷新时靠它们做ORDER BY SEQUENCE$$+WHERE M_ROW$$ = ?双重过滤
rowid别名与日志声明不匹配,整个快速刷新机制就退化为黑盒——看起来在跑,实际每次都在全量刷。


















