必须加INCLUDING NEW VALUES才能捕获LOB变更,否则FAST REFRESH会跳过LOB列更新;排除LOB列后若MV定义仍引用它,将触发ORA-12034错误;LOB存在时ON COMMIT快速刷新不可用,仅支持ON DEMAND。
物化视图日志里加 INCLUDING NEW VALUES 才能捕获 LOB 变更
oracle 默认的物化视图日志(create materialized view log)不记录 lob 列内容变更,哪怕你显式列出了 lob 字段。这是因为 lob 的变更不走常规 dml 路径,而是通过独立的 lob locator 操作触发,日志机制默认忽略。
必须显式加上 INCLUDING NEW VALUES,否则 FAST REFRESH 时会跳过 LOB 列更新,导致物化视图中该列始终为旧值或 NULL —— 这不是 bug,是设计行为。
-
INCLUDING NEW VALUES会让日志表多存一份 LOB 值(或 locator),显著增大日志表体积 - 只对
FOR UPDATE类型的日志生效;WITH PRIMARY KEY单独使用无效 - 如果源表有多个 LOB 列(如
CLOB和BLOB),全部会被一并捕获,无法按列开关
排除 LOB 列后 FAST REFRESH 仍可能失败:ORA-12034
你以为删掉 LOB 列就能让刷新变快?不一定。如果物化视图定义里还引用了被排除的 LOB 列(比如 SELECT id, content FROM t,而 content 是 CLOB),即使日志没记它,Oracle 在构建增量 SQL 时仍会尝试比对 LOB 值 —— 此时直接报 ORA-12034: materialized view log on "T" younger than last refresh 或更隐蔽的 ORA-12008: error in materialized view refresh path。
- 错误常发生在首次快速刷新或日志重建后,和时间戳/SCN 不一致无关,本质是元数据校验失败
- 修复方式只有两个:要么在 MV 定义中彻底去掉 LOB 列(
SELECT id FROM t),要么把 LOB 列加回日志并启用INCLUDING NEW VALUES - 用
DBMS_MVIEW.EXPLAIN_MVIEW查看REFRESH_METHOD字段,若显示FAST但实际报错,大概率是这个原因
LOGGING vs NOLOGGING 对 LOB 日志写入性能影响极大
LOB 数据写入物化视图日志表时,默认走完整 REDO 流程。如果源表本身是 NOLOGGING,但日志表是 LOGGING(Oracle 默认),那每次 LOB 更新都会强制刷盘、锁日志缓冲区,吞吐量断崖下跌。
- 建议将物化视图日志表所在表空间设为
NOLOGGING(需业务可接受丢失部分日志的 RPO 风险) - 建日志时指定
TABLESPACE ts_nolog并确保该表空间为NOLOGGING,比后期 ALTER 更可靠 -
NOLOGGING下,LOB 日志写入延迟可从百毫秒级降到个位数毫秒,但主库宕机时这部分日志不可恢复
LOB 列存在时,FAST REFRESH ON COMMIT 几乎不可用
Oracle 要求 ON COMMIT 快速刷新必须满足“无 LOB、无 LONG、无嵌套表”等硬限制。只要源表含 LOB 列,哪怕日志里没它、MV 定义里也没它,只要该列存在于基表结构中,ON COMMIT 就直接被拒绝,报 ORA-12052: cannot fast refresh materialized view string.string。
- 这不是配置问题,是 Oracle 内核限制,无法绕过
- 替代方案只能是
ON DEMAND+ 定时DBMS_MVIEW.REFRESH,或改用 CDC/OGG 等外部机制同步 LOB - 别信网上“加 hint 或隐含参数能解锁”的说法,19c 仍无效,且可能引发内部错误
LOB 和物化视图日志的耦合点很窄,但每个卡点都硬——要么全链路支持(含日志、MV 定义、刷新方式),要么彻底放弃 FAST 刷新。没有中间态。











