物化视图日志必须创建在基表上而非物化视图上,用于支持快速刷新;需根据物化视图查询结构选择WITH PRIMARY KEY、SEQUENCE、INCLUDING NEW VALUES等参数,并确保日志能力匹配刷新需求。

物化视图日志必须在基表上创建,不是在物化视图上
Oracle 的物化视图日志(MATERIALIZED VIEW LOG)本质是为基表(master table)记录 DML 变更的辅助结构,用于支持快速刷新(FAST REFRESH)。它和物化视图本身是分离的——你不能对物化视图建日志,只能对它所依赖的**源表**建日志。
常见错误是试图在物化视图对象上执行 CREATE MATERIALIZED VIEW LOG,结果报错 ORA-12000: materialized view log does not exist on table 或更直接的 ORA-00942: table or view does not exist(因为物化视图不是基表)。
- 确认目标基表名:比如物化视图基于
sales表,则日志必须建在sales上 - 用户需有该基表的
SELECT权限,且具备CREATE MATERIALIZED VIEW系统权限 - 若基表已有主键,建议显式指定
WITH PRIMARY KEY;否则需用WITH ROWID(但限制更多)
CREATE MATERIALIZED VIEW LOG 语句的关键参数组合
最简可用的日志定义是 CREATE MATERIALIZED VIEW LOG ON sales;,但它默认只记录 ROWID,不支持按列刷新或复杂查询的快速刷新。实际中需根据物化视图的刷新需求选配参数:
-
WITH PRIMARY KEY:推荐首选,要求基表有主键且物化视图查询中包含该主键列 -
WITH SEQUENCE:配合PRIMARY KEY使用,提升多节点并发 DML 下的刷新稳定性 -
INCLUDING NEW VALUES:记录新旧行值,支持FAST REFRESH ON COMMIT场景(如需捕获 UPDATE 前后值) -
WITH (col1, col2):仅记录指定列变更,减小日志体积,但物化视图 SELECT 列必须完全覆盖这些列
例如,若物化视图查询为 SELECT prod_id, SUM(amount) FROM sales GROUP BY prod_id,则日志至少需:CREATE MATERIALIZED VIEW LOG ON sales WITH PRIMARY KEY, SEQUENCE(prod_id, amount) INCLUDING NEW VALUES;
物化视图日志与快速刷新的匹配关系
即使日志建成功,物化视图仍可能无法 FAST REFRESH——Oracle 会检查日志能力是否满足其查询结构。典型不匹配场景:
- 物化视图含
AVG()或COUNT(*),但日志未建SEQUENCE和INCLUDING NEW VALUES - 基表无主键,日志用了
WITH ROWID,但物化视图含JOIN或GROUP BY,导致 Oracle 拒绝快速刷新 - 日志建在分区表上,但未启用
WITH ROWID或未对每个分区单独建日志(分区表需额外注意)
验证方式:创建物化视图后执行 DBMS_MVIEW.EXPLAIN_MVIEW,查 msgtxt 字段是否含 "fast refreshable" 及具体限制原因。
删除或重建日志前务必检查依赖
物化视图日志被多个物化视图共享时,直接 DROP MATERIALIZED VIEW LOG 会失败,并报错 ORA-12002: there is no materialized view log on table(实际是“有依赖未清除”)。真实依赖关系藏在 USER_MVIEW_LOGS 和 USER_MVIEWS 中:
- 查哪些物化视图依赖该日志:
SELECT mview_name FROM user_mviews WHERE master = 'SALES'; - 查日志当前配置:
SELECT * FROM user_mview_logs WHERE log_table = 'MLOG$_SALES'; - 若需重建日志,先
DROP所有依赖的物化视图,或用ALTER MATERIALIZED VIEW ... DISABLE QUERY REWRITE临时解除绑定(不推荐生产环境)
日志表名由 Oracle 自动生成(如 MLOG$_SALES),其结构受参数影响较大——比如加了 SEQUENCE 就会多出 M_ROW$$、SNAPTIME$$、DMLTYPE$$ 等隐藏字段,这些字段不可手动修改,也不应在应用逻辑中引用。


















