oracle 19c物化视图无真正实时刷新,仅支持低延迟fast on demand增量刷新;on commit受限多且性能差;必须显式指定refresh fast on demand并验证fastrefreshable='yes',否则静默降级为complete。

Oracle 19c 没有真正意义上的“实时刷新”物化视图——所谓实时,实际是低延迟增量刷新(FAST ON DEMAND)+ 合理调度的组合效果。ON COMMIT 模式虽能“事务级触发”,但不支持跨库、性能开销大、且无法用于含 JOIN/子查询等常见场景。真要接近实时,得靠 FAST 刷新 + 定时 job + 严格前置条件。
REFRESH FAST ON DEMAND 是唯一可行路径
Oracle 19c 的 REFRESH FAST 本质是读取物化视图日志(MLOG$_ 表)做行级增量计算,延迟取决于你刷多频繁、日志是否完备、SQL 是否合规。它不是“自动监听变更”,而是“按需拉取已记录的变更”。所以必须显式写成:REFRESH FAST ON DEMAND,只写 REFRESH FAST 会报错。
-
ON COMMIT看似实时,但仅限单库、无远程对象、无子查询、无外连接;一旦基表有 DML,commit 延迟可能从毫秒级升到秒级甚至更长 -
REFRESH FORCE会静默退化为 COMPLETE,尤其在日志缺失或 SQL 不合规时,你根本看不出它没走 FAST - 必须配合
DBMS_MVIEW.EXPLAIN_MVIEW验证:fastrefreshable = 'YES'才算真正可 FAST,否则只是“语法通过、运行降级”
子查询和外连接会让 FAST 直接失效
只要物化视图定义里出现 EXISTS、IN、NOT EXISTS、LEFT JOIN、RIGHT JOIN,Oracle 内核就拒绝 FAST 路径——这不是权限或配置问题,是语法硬拦截。调用 DBMS_MVIEW.EXPLAIN_MVIEW 会明确返回 fastrefreshable = 'FALSE'。
- 替代方案只有手动拆解:
LEFT JOIN→UNION ALL(INNER JOIN 部分 + NOT EXISTS 部分),且两部分都得满足 FAST 条件(主键、日志、列覆盖) -
IN (SELECT ...)若子查询只查单列主键,可转为INNER JOIN;若含聚合(如MAX()),FAST 不可能成立,只能接受 COMPLETE 或换 CDC 方案 - 别信“加索引就能救”,外连接和子查询的语义不确定性,不是索引能解决的
NEXT 子句不会自动触发刷新,job 必须活
NEXT TRUNC(SYSDATE) + 1/24(每小时一次)这类写法本身不干活,它只注册一个时间点;真正执行靠 Oracle 的 job 引擎。如果 job_queue_processes 是 0,或者数据库在 RESTRICTED SESSION 模式下,job 根本不跑。
- 检查 job 是否注册:
SELECT what, next_date, broken, failures FROM dba_jobs WHERE what LIKE '%DBMS_MVIEW.REFRESH%'; -
failures > 0说明最近几次刷新都失败了,但错误被静默吞掉——得手动运行EXEC DBMS_MVIEW.REFRESH('mv_name', 'F');看具体报错 -
START WITH和NEXT必须是 DATE 表达式,写成'SYSDATE + 1'(字符串)会直接导致ORA-12012
远程同步(DB Link)下 FAST 刷新极易退化
用 @dblink 查远程表时,FAST 刷新依赖三件事全部到位:DB Link 可连、源库有日志、MV 定义匹配。漏任一环,就会静默变成 COMPLETE,耗时暴涨。
- DB Link 必须是
PUBLIC,因为刷新由 Oracle 内部调度用户(非你当前 session)触发;CREATE DATABASE LINK不带PUBLIC就等于没建 - 源库日志必须建在远程库上,语句如:
CREATE MATERIALIZED VIEW LOG ON emp@remote WITH PRIMARY KEY—— 本地建无效 - 测试不能只查
SELECT * FROM dual@mylink,要查真实表:SELECT COUNT(*) FROM scott.emp@mylink,否则权限问题会掩盖在连通性后面
复杂点在于:FAST 刷新的“实时性”完全取决于你能否把所有链路(网络、权限、日志、SQL 结构、job 资源)都卡在临界点上。任何一个环节松动,延迟就从秒级跳到分钟级,且毫无预警。











