跨库物化视图仅支持COMPLETE刷新,FAST不可用;必须使用ON PREBUILT TABLE安全建模,并通过DBMS_SCHEDULER调度,且需确保DBLINK双向权限与真实查询路径连通。

跨库物化视图只能用 COMPLETE 刷新,FAST 不可用
Oracle 官方不支持跨 DB_LINK 的 FAST 刷新。哪怕源表有主键、日志建得再规范,只要物化视图定义里用了 @dblink,创建时加 REFRESH FAST 就会直接报 ORA-12015 或 ORA-12008。根本原因是:物化视图日志(MLOG$)必须建在基表所在库,而本地 MV 进程无法实时读取远程库的日志变更。
常见误操作是照搬同库 FAST 写法,比如:
CREATE MATERIALIZED VIEW mv_remote REFRESH FAST ON DEMAND AS SELECT * FROM t@remote_link;
这语句在语法检查阶段就失败。唯一能走通的跨库刷新方式是 COMPLETE —— 每次都重跑整个 SELECT 查询,性能取决于远程查询响应时间、网络带宽和结果集大小。
- 别指望“自动增量”,跨库场景下所有变更都靠全量拉取
- 如果源表加了列或改了类型,物化视图不会自动失效,查询仍返回旧结构数据,可能出错或丢字段
-
FORCE刷新模式在这里等价于COMPLETE,因为 FAST 路径根本走不通
DBLINK 配置必须双向可用且权限精准
DBLINK 不只是“能连上 DUAL”就算通。物化视图刷新时,Oracle 会以目标库当前用户身份,通过 DBLINK 去远程库执行 SELECT。所以两个环节缺一不可:
- 目标库用户对 DBLINK 有执行权(
CREATE DATABASE LINK权限或 PUBLIC 链路被授予) - 远程库对应用户必须显式授权:
GRANT SELECT ON schema.table TO local_user(不能只靠SELECT ANY TABLE,最小权限原则)
测试不能只跑 SELECT 1 FROM DUAL@link,必须验证真实查询路径:
SELECT COUNT(*) FROM your_table@your_dblink;
若报 ORA-02069,大概率是 GLOBAL_NAMES=TRUE 但 DBLINK 名与远程数据库全局名不一致;若报 ORA-02041,说明分布式事务未初始化,需检查 tnsnames.ora 是否同步到目标实例,且监听正常。
ON PREBUILT TABLE 是生产环境安全底线
直接用 CREATE MATERIALIZED VIEW ... AS SELECT 让 Oracle 自动建表,会导致表结构不可控:字段顺序、NULL 属性、索引、约束全由 Oracle 决定。更危险的是,删 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 AS SELECT * FROM your_table@your_dblink
这样后续可独立维护表结构(如加索引、分区),MV 只负责刷新逻辑,解耦清晰。注意:即使跨库,ON PREBUILT TABLE 也必须显式指定,否则 Oracle 默认新建表。
DBMS_SCHEDULER 替代 JOB_QUEUE_PROCESSES 是调度首选
用 START WITH ... NEXT 语法创建定时刷新,底层依赖 JOB_QUEUE_PROCESSES 参数,该机制在 12c+ 已逐步淘汰,且难以监控、调试和告警。
推荐显式用 DBMS_SCHEDULER 创建作业:
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'refresh_mv_job',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN DBMS_MVIEW.REFRESH(''SCOTT.MV_REMOTE'', ''C''); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0',
enabled => TRUE
);
END;好处是:
- 作业状态可查:
SELECT * FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME = 'REFRESH_MV_JOB' - 失败自动记录日志,支持邮件通知、重试策略
- 避免
JOB_QUEUE_PROCESSES资源争用导致刷新延迟或跳过
最关键的是:跨库刷新耗时波动大,DBMS_SCHEDULER 支持设置 max_runs 和 stop_on_window_close,防止因单次卡住拖垮整个调度队列。
跨库物化视图最易被忽略的点,不是语法或权限,而是“全量刷新的副作用”:每次刷新都会触发远程库一次完整扫描,如果源表没合适索引、WHERE 条件没下推、或网络抖动,就会拖慢源库或超时失败。真正可控的做法,是在源库建好带过滤条件的视图,再让物化视图查这个视图,而不是裸查基表。


















