dbms_sync_refresh_admin.create_refresh_group是创建物化视图同步刷新组的唯一入口,必须先执行此函数建立刷新组,否则调用refresh会报ora-23424;需dba或execute_catalog_role权限,refresh_group_name大小写敏感且不可含特殊字符,data guard环境须主备库均执行。
dbms_sync_refresh_admin.create_refresh_group 是核心入口
物化视图同步刷新不是靠单个 mv 自己搞定的,必须先建刷新组,dbms_sync_refresh_admin.create_refresh_group 就是唯一能创建它的函数。不走这步,后续所有同步操作都会报 ora-23424: refresh group does not exist。
常见错误是直接调用 DBMS_SYNC_REFRESH.REFRESH,结果发现根本没环境可刷——因为 Oracle 同步刷新强依赖刷新组元数据,它会记录成员 MV、协调节点、冲突处理策略等信息。
- 必须用具备
EXECUTE_CATALOG_ROLE或DBA权限的用户执行,普通SELECT_CATALOG_ROLE不够 - 参数
refresh_group_name不能含小写或特殊字符,Oracle 内部对它大小写敏感且不校验,出错时只报模糊的ORA-00904 - 如果目标库启用了 Data Guard,必须在主库和所有备库都提前运行一次
CREATE_REFRESH_GROUP(哪怕只是空组),否则备库上REFRESH会卡住不动
DBMS_SYNC_REFRESH_ADMIN.ADD_TO_REFRESH_GROUP 绑定物化视图
建好组只是搭了架子,真正干活的是组里的物化视图。用 DBMS_SYNC_REFRESH_ADMIN.ADD_TO_REFRESH_GROUP 把 MV 加进去,但这里有个关键约束:所有加入的 MV 必须基于同一套主表(master site),且主表必须已启用同步刷新支持(即存在 MLOG$_xxx 日志表并配置了 FOR UPDATE)。
典型翻车场景是把跨数据库链路(DB Link)指向不同源库的 MV 加进同一个组——Oracle 不报错,但刷新时会静默跳过部分 MV,日志里只留一句 skipping mv due to master mismatch,很难定位。
- 加之前先查
USER_MVIEWS确认MASTER_LINK字段值一致 - 如果 MV 基于复杂视图(含 UNION、子查询),必须确保该视图已标记为可快速刷新:
DBMS_MVIEW.EXPLAIN_MVIEW返回capable_of_fast_refresh = 'Y' -
refresh_method参数只能传'FAST',传'COMPLETE'会被忽略,同步刷新不支持全量模式
DBMS_SYNC_REFRESH.REFRESH 触发实际同步动作
真正执行刷新的是 DBMS_SYNC_REFRESH.REFRESH,但它不接受单个 MV 名,只认刷新组名。调用前务必确认组内所有 MV 的状态都是 BUILDING 或 VALID(查 USER_MVIEWS.STALENESS),否则会报 ORA-12008: error in materialized view refresh path 并中断整个组。
这个函数默认阻塞执行,且超时时间硬编码为 300 秒,没法改。如果你的 MV 涉及百万级变更数据,很可能超时失败,错误信息却是误导性的 ORA-01013: user requested cancel of current operation。
- 生产环境务必用
job_queue_processes > 0配合后台作业方式调用,避免会话挂起 - 不要在应用事务里嵌套调用,它会自动开启独立事务并提交,跟外层事务无关
- 刷新失败后,不会自动回滚已成功刷新的 MV,组内其他 MV 状态可能变成
NEEDS_COMPILE,得手动ALTER MATERIALIZED VIEW ... COMPILE
ORA-23413 和 ORA-12006 是最常被忽略的前置条件错误
ORA-23413: table "xxx" does not have a materialized view log 表示主表缺日志表,但很多人只盯着表名,忘了同步刷新要求日志表必须带 ROWID 和 SEQUENCE 子句,光建个基础日志没用。
ORA-12006: a materialized view with the same name already exists 则常出现在重试场景:你以为删了 MV 就清干净了,其实 DBMS_SYNC_REFRESH_ADMIN.DROP_REFRESH_GROUP 不会自动清理关联的 MV 元数据,残留记录还在 USER_REFRESH_CHILDREN 里。
- 建日志表必须显式写全:
CREATE MATERIALIZED VIEW LOG ON t WITH ROWID, SEQUENCE (c1,c2) INCLUDING NEW VALUES - 删组前先手动清空组内 MV:
EXEC DBMS_SYNC_REFRESH_ADMIN.REMOVE_FROM_REFRESH_GROUP(...),再删组 - 每次部署前跑一遍
SELECT * FROM USER_REFRESH_CHILDREN WHERE REFRESH_GROUP_NAME = 'xxx',确认无残留
同步刷新的麻烦点不在语法,而在它把多个隐式依赖串成一条刚性链条:主表日志 → 刷新组定义 → MV 成员一致性 → 协调节点状态。断一环,全链失效,而且错误提示往往藏在下游环节里。










