Oracle原生物化视图无法实现真正秒级增量同步,FAST刷新实际延迟为100ms~2s;必须创建含INCLUDING NEW VALUES的日志,否则增量逻辑崩溃;ON COMMIT仅支持同库,跨库需应用层主动触发;监控需校验SNAPTIME$$水位与MLOG$_t记录一致性。

Oracle原生物化视图无法实现真正秒级增量同步——FAST刷新的最小可控延迟是“事务提交后立即触发”,但实际耗时取决于日志写入、网络往返、目标库负载和刷新执行路径,通常在100ms~2s之间波动;所谓“秒级”只是业务可接受的感知延迟,不是技术保障的SLA。
必须显式创建带 INCLUDING NEW VALUES 的物化视图日志
这是FAST刷新能捕获UPDATE/DELETE变更的硬性前提。漏掉它,日志只记录ROWID和主键,旧值丢失,导致增量逻辑崩溃:
-
CREATE MATERIALIZED VIEW LOG ON t WITH PRIMARY KEY, ROWID, SEQUENCE(col1,col2) INCLUDING NEW VALUES;—— 必须包含INCLUDING NEW VALUES,否则DBMS_MVIEW.REFRESH('mv','F')会静默退化为COMPLETE - 如果基表被
TRUNCATE过,MLOG$_t被清空但SNAPTIME$$不重置,下次FAST刷新直接报ORA-12034;此时需人工重置:UPDATE MLOG$_t SET SNAPTIME$$ = SYSDATE WHERE SNAPTIME$$ = TO_DATE('4000-01-01', 'YYYY-MM-DD'); - 验证日志是否启用时间戳模式:查
SELECT * FROM USER_MVIEW_LOGS WHERE MASTER = 'T',若LOG_TRIGGER列为NO且ROWIDS为YES,说明走的是ROWID日志路径,不依赖SCN,才能支持时间戳水位推进
REFRESH FAST ON COMMIT 是唯一接近秒级的刷新方式
ON DEMAND + 定时JOB(如每秒跑一次)看似能压低延迟,但Oracle不支持亚秒级调度,且频繁调用 DBMS_MVIEW.REFRESH 会引发日志锁争用和PGA内存抖动,实际更慢:
-
CREATE MATERIALIZED VIEW mv REFRESH FAST ON COMMIT AS SELECT * FROM t@dblink;—— 提交即触发刷新,延迟由网络RTT + 目标库执行时间决定,实测中位数约300ms - 不能混用
ON COMMIT和远程DB Link:Oracle要求ON COMMIT模式下基表必须与MV同库,跨库只能用ON DEMAND,此时“秒级”需靠应用层主动触发,例如在源端DML后立刻调用DBMS_MVIEW.REFRESH - 多个MV共享同一张基表日志时,任一MV定义里漏了日志中声明的列(比如日志含
INCLUDING NEW VALUES,而MV查询只选了旧值),会导致所有关联MV的FAST失效,DBA_MVIEWS.FAST_REFRESHABLE显示为NO
验证是否真走增量,而不是静默降级为全量
Oracle对FAST条件检查极严格,不满足就降级,且不报错——你看到刷新成功,不代表是增量:
- 刷新后立刻执行:
SELECT COUNT(*) FROM MLOG$_t WHERE SNAPTIME$$ > (SELECT LAST_REFRESH_DATE FROM DBA_MVIEWS WHERE MVIEW_NAME = 'MV');,结果非零才说明有delta被消费 - 查
DBA_MVIEWS中的FAST_REFRESHABLE字段,值为YES才代表当前定义满足FAST语义;若为NO,常见原因是SQL含SYSDATE、分析函数、外连接或未包含全部主键列 - 不要依赖
REFRESH FORCE:它先试FAST,失败就切COMPLETE,掩盖问题;生产环境应固定用REFRESH FAST并捕获异常,便于及时发现配置漂移
真正卡住“秒级”上限的,从来不是语法或权限,而是SNAPTIME$$水位线与MLOG$_t变更记录之间的耦合关系——它既不是全局时钟,也不自动修复断裂。一次网络超时、一次手动 ALTER MATERIALIZED VIEW ... REBUILD、甚至一次未清理的测试事务,都可能让水位悬空,后续所有FAST请求都会失败。这点必须写进监控脚本,不能只靠DBA巡检。


















