能实现,但必须满足三个硬性前提:源表有主键(或明确可选的唯一约束)、dblink可达且权限完整、快照日志已创建并启用rowid/primary key模式;缺一不可,否则refresh fast会静默退化为complete或直接报错。
能实现,但必须满足三个硬性前提:源表有主键(或明确可选的唯一约束)、dblink 可达且权限完整、快照日志已创建并启用 rowid/primary key 模式。缺一不可,否则 refresh fast 会静默退化为 complete 或直接报错。
为什么 refresh fast 总是变 complete?
Oracle 不会主动告诉你“fast 刷新不可用”,它只会在执行时 fallback —— 这是最容易被忽略的坑。根本原因通常是:
- 源表没建
materialized view log,或者建了但没带with primary key(主键缺失)或with rowid(ROWID 同步场景) - DBLINK 查询语句里用了函数、
distinct、group by、子查询或非等值连接 —— 这些都会让 fast 刷新失效 - 目标物化视图定义中漏了
on prebuilt table(已有表结构时),或表字段顺序/类型与远程查询结果不一致 - 源库和目标库时区差异导致
sysdate类时间计算偏移,next刷新时间被误判为过去
create materialized view log 必须带 primary key 吗?
不是“必须”,而是“推荐优先”。主键同步最稳定,ROWID 同步虽可用,但有严重限制:
-
with rowid要求源表不能发生move、shrink、partition exchange等物理重组操作,否则日志失效 - ROWID 同步无法捕获
delete操作(除非加including new values,但 Oracle 12c 默认不支持该子句) - 主键同步下,
dba_mview_logs中log_table字段显示真实日志表名;ROWID 模式下该字段为空,排查更困难
如何验证 fast 刷新是否真正在工作?
别只看 dbms_mview.refresh 是否成功,要查底层日志和状态:
- 执行刷新后立刻查:
select * from user_mview_logs where master = 'YOUR_TABLE_NAME'—— 确认log_table存在且有记录 - 查刷新历史:
select * from user_mview_refresh_times where name = 'YOUR_MV_NAME' order by refresh_date desc——method列必须是F(Fast)而非C(Complete) - 手动触发一次 fast 刷新:
exec dbms_mview.refresh('MV_NAME', 'F'),如果报ORA-12004: REFRESH FAST cannot be used,说明定义不满足 fast 条件 - 检查基表 DML 是否真正触发日志写入:在源库对表做
insert/update后,查select count(*) from mlog$_your_table(日志表名由 Oracle 自动生成)是否增长
异地容灾场景下,网络抖动比性能更致命——refresh fast on demand 配合定时 job 是稳妥选择,但务必把 interval 设为 ≥5 分钟,太密会堆积未提交的日志,最终撑爆 SYSTEM 表空间。











