跨库物化视图仅支持complete刷新,fast不可用;因mlog$日志必须建在源库且本地进程无法读取远程日志变更,故语法解析阶段即报ora-12015/ora-12008,与主键、日志是否完备无关。

跨 DB Link 的物化视图无法实现自动 FAST 刷新,唯一可行的自动刷新方式是 COMPLETE + DBMS_SCHEDULER 定时调用,且必须手动建表、显式授权、严格校验链路连通性。
为什么 REFRESH FAST ON DEMAND 会直接报错
Oracle 在语法解析阶段就拒绝跨库 FAST 刷新:只要 AS SELECT 中出现 @dblink,哪怕基表有主键、日志完备、查询极简单,CREATE MATERIALIZED VIEW 就会抛 ORA-12015 或 ORA-12008。根本原因是物化视图日志(MLOG$)必须建在源表所在库,而本地刷新进程无法访问远程库的日志变更记录——这不是权限或配置问题,是机制级限制。
- 别试
REFRESH FAST ON COMMIT:跨库下 COMMIT 触发无效,语句直接失败 -
FORCE模式在这里等价于COMPLETE,不会 fallback 到增量 - 错误示例:
CREATE MATERIALIZED VIEW mv_remote REFRESH FAST ON DEMAND AS SELECT * FROM t@remote_link;—— 这行不通
必须用 ON PREBUILT TABLE + BUILD IMMEDIATE
直接 CREATE MATERIALIZED VIEW ... AS SELECT 会让 Oracle 自动建表,字段顺序、NULL 属性、约束全不可控;更危险的是删 MV 会级联删表。生产环境必须手工建表再绑定:
- 先在目标库建空表:
CREATE TABLE your_table AS SELECT * FROM your_table@your_dblink WHERE 1=0; - 再建 MV 绑定该表:
CREATE MATERIALIZED VIEW your_table ON PREBUILT TABLE REFRESH COMPLETE ON DEMAND BUILD IMMEDIATE WITH PRIMARY KEY AS SELECT * FROM your_table@your_dblink; - 漏掉
BUILD IMMEDIATE会导致 MV 创建后为空,不是“延迟构建”,是真没数据 -
ENABLE QUERY REWRITE要加上,否则优化器不会自动重写查询走 MV,它只是个“手动缓存表”
DBMS_SCHEDULER 作业怎么写才不静默失败
用传统 DBMS_JOB 容易丢错误、难追踪;DBMS_SCHEDULER 是唯一推荐方式,但参数极易出错:
-
job_action必须双引号转义单引号:'BEGIN DBMS_MVIEW.REFRESH(''OWNER.MV_NAME'', ''C''); END;'(内层两个单引号) - 物化视图名必须带 schema:
''DW.SALES_MV'',不能只写''SALES_MV'' - START WITH/NEXT 必须是 DATE 表达式:
NEXT TRUNC(SYSDATE) + 1 + 6/24(每天早6点),不能写成字符串'TRUNC(SYSDATE)+1',否则ORA-12012静默失败 - 作业默认以创建者身份运行;若跨 schema 刷新,需提前授
REFRESH ANY MATERIALIZED VIEW权限
刷新前必须验证的三个硬性条件
哪怕作业跑成功了,数据也不一定刷进去了。以下三点任一不满足,DBMS_MVIEW.REFRESH 就会失败或退化为低效路径:
-
DBLINK必须双向连通:不仅要SELECT 1 FROM DUAL@link成功,还得SELECT COUNT(*) FROM remote_table@link成功;报ORA-02069往往是GLOBAL_NAMES=TRUE但 DBLINK 名与远程全局名不一致 - 远程用户必须显式授权:
GRANT SELECT ON schema.table TO local_user;(不能靠SELECT ANY TABLE) - 本地用户对
DBLINK有执行权:查USER_DB_LINKS确认USERNAME字段非空,或已授CREATE DATABASE LINK权限
远程表结构变更(如加列、改类型)不会触发 MV 失效,查询仍返回旧结构数据——这是最易被忽略的静默故障点,得靠定期比对 DESCRIBE your_table@your_dblink 和本地表结构来发现。











