靠不住。LAST_REFRESH_DATE仅记录最后一次成功刷新完成时间,失败、中断或取消均不更新;STALENESS为STALE/UNUSABLE时即使时间新也无有效数据;需结合DBA_SCHEDULER_JOB_RUN_DETAILS查失败日志,并以STALENESS='FRESH'为准判断是否生效。
查 DBA_MVIEWS 里刷新时间字段到底靠不靠谱?
靠不住。字段 last_refresh_date 只记录「最后一次成功刷新的完成时间」,如果刷新失败、中断或被取消,这个值不会更新,也不会存失败信息——它只管“成功落库”的那一刻。
常见错误现象:LAST_REFRESH_DATE 显示是昨天,但业务查不到新数据,STALENESS 是 STALE 或 UNUSABLE,说明物化视图没真正刷进去。
-
LAST_REFRESH_DATE为空?说明从未成功刷新过(哪怕执行过DBMS_MVIEW.REFRESH) -
STALENESS为NEEDS_COMPILE:依赖对象改了,但没重编译 MV,此时即使时间看起来新,也可能查不到数据 - 快照太老时,Oracle 可能跳过刷新直接报错,但
LAST_REFRESH_DATE不变
刷新失败日志藏在哪?别只盯 DBA_MVIEWS
Oracle 不把失败详情写进 DBA_MVIEWS,得去查刷新任务本身的执行痕迹。最直接的是看 DBA_JOBS 或 DBA_SCHEDULER_JOB_LOG(取决于你用的是旧式 job 还是 scheduler),再结合 DBA_SCHEDULER_JOB_RUN_DETAILS 看错误堆栈。
- 如果用
DBMS_MVIEW.REFRESH手动刷,且没捕获异常,错误就直接抛给调用方,不会落地日志 - 自动刷新(比如通过
DBMS_SCHEDULER)失败后,LOG_DATE和STATUS = 'FAILED'的记录才真正反映问题 - 关键字段要查:
ERROR#(Oracle 错误号)、ADDITIONAL_INFO(含 ORA-xxxx 和触发语句)
示例查最近 10 条失败记录:
SELECT LOG_DATE, JOB_NAME, ERROR#, ADDITIONAL_INFO FROM DBA_SCHEDULER_JOB_RUN_DETAILS WHERE STATUS = 'FAILED' AND JOB_NAME LIKE '%MV_%' ORDER BY LOG_DATE DESC FETCH FIRST 10 ROWS ONLY;
DBMS_MVIEW.EXPLAIN_MVIEW 能提前暴露刷新隐患
很多刷新失败不是运行时才爆,而是建模阶段就埋了雷:比如基表没主键、远程数据库链接不稳定、物化视图日志缺失。用 EXPLAIN_MVIEW 把这些「静态缺陷」打出来,比等失败后再翻日志高效得多。
- 输出结果里
MSGTXT字段含具体限制,如"materialized view log does not exist on table" -
CAPABILITY_NAME = 'REFRESH_FAST_PCT'但实际不支持?说明分区变更跟踪没开,PCT刷新会退化成完全刷新甚至失败 - 对大型 MV,先跑
EXPLAIN_MVIEW再提交刷新任务,能避开 70% 以上的「ORA-12008 + ORA-00600」组合拳
为什么 LAST_REFRESH_DATE 和 V$MVREFRESH 时间对不上?
因为 V$MVREFRESH 记的是「当前正在执行的刷新会话的开始时间」,而 DBA_MVIEWS.LAST_REFRESH_DATE 是「上一次提交事务的 SCN 对应的时间戳」——两者不在一个生命周期里。更麻烦的是,V$MVREFRESH 是内存视图,实例重启就清空,没法追溯历史。
- 想确认某次刷新是否真完成了?不能只比对两个时间,得查
DBA_MVIEWS.STALENESS+STALENESS是否为FRESH - 并行刷新时,
V$MVREFRESH可能显示多个条目,但DBA_MVIEWS只记最终 commit 时间 - 跨库刷新(DB Link)失败时,
LAST_REFRESH_DATE不变,V$MVREFRESH可能早没了,唯一可靠线索只剩调度日志里的ADDITIONAL_INFO
真正要盯的不是「什么时候刷的」,而是「刷完有没有生效」——STALENESS = 'FRESH' 且 STALENESS 不是 UNUSABLE,才是硬指标。








