如何快速诊断Oracle 19c物化视图刷新慢及检查刷新作业状态?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1105个文字,预计阅读时间需要5分钟。
相关专题
查物化视图刷新是否卡在 longops 里
物化视图刷新慢,第一反应不是看执行计划,而是确认它到底“卡没卡住”。oracle 把长时间运行的操作(比如刷新)记在 v$session_longops 里,只要还没超时、没报错,就可能挂在这儿不动。
执行这个查询能快速定位:
SELECT sid, serial#, opname, target, sofar, totalwork, ROUND(sofar/NULLIF(totalwork,0)*100,2) pct_done, elapsed_seconds, sql_id FROM v$session_longops WHERE opname LIKE '%refresh%' AND totalwork > 0 AND sofar < totalwork;
常见现象:
-
opname是Refresh materialized view,但pct_done长时间不动 → 刷新被阻塞或基表锁住 -
sql_id为空 → 刷新还没真正生成 SQL,卡在元数据检查或日志读取阶段 -
elapsed_seconds超过预期(比如已跑 20 分钟,而历史平均才 2 分钟)→ 需进一步查该sql_id的真实执行计划
用 DBMS_MVIEW.EXPLAIN_MVIEW 先验判断能否快刷
别等 DBMS_MVIEW.REFRESH 跑完才发现是 complete 刷新。很多“慢”本质是本该走 fast 却被迫退化成 full,而 DBMS_MVIEW.EXPLAIN_MVIEW 能在执行前暴露根因。
执行后查 MVIEW_EXCEPTIONS 或直接看输出:
EXEC DBMS_MVIEW.EXPLAIN_MVIEW('MV_SALES_SUMMARY');
关键字段 MSGTXT 里出现这些提示,基本就定位了瓶颈:
-
"REFRESH FAST IS NOT POSSIBLE"→ 缺物化视图日志,或基表没主键,或日志没开ROWIDS -
"NO LOG ON BASE TABLE"→ 基表压根没建日志,CREATE MATERIALIZED VIEW LOG ON ...漏了 -
"POTENTIAL FAST REFRESH"但实际没走 → 日志里没未消费变更(LAST_PURGE_DATE没更新),或 DML 后没提交
注意:EXPLAIN_MVIEW 不检查网络或权限,只验证定义层面可行性。如果它说“可快刷”,但刷新仍慢,问题一定出在日志数据积压、索引缺失或锁等待上。
检查刷新作业是否被其他 job 或 session 阻塞
物化视图定时刷新常通过 DBMS_JOB 或 DBMS_SCHEDULER 触发,一旦底层作业卡住,后续刷新全排队。尤其当多个 MV 属于同一刷新组时,一个卡住,整组停摆。
先看当前有没有正在跑的刷新作业:
SELECT job_name, state, last_start_date, running_instance FROM dba_scheduler_jobs WHERE job_name LIKE '%MV%' OR job_action LIKE '%REFRESH%';
再查是否有会话在等锁:
SELECT blocking_session, sid, serial#, event, sql_id FROM v$session WHERE event LIKE 'enq:%' OR event LIKE 'library cache%';
特别注意:
- 如果
blocking_session对应的是另一个DBMS_MVIEW.REFRESH会话 → 刷新组串行执行中,需确认是否真需要强一致性 - 如果
event是enq: TX - row lock contention→ 基表正被业务 DML 修改,刷新在等事务提交 - 定时任务用
DBMS_REFRESH.REFRESH时默认ATOMIC_REFRESH => TRUE,整个组锁表,改成单个 MV 刷新 +ATOMIC_REFRESH => FALSE可绕过
确认刷新是否真的在跑,还是“静默跳过”
调用 DBMS_MVIEW.REFRESH 返回成功,不代表数据更新了。尤其是 method => 'F' 模式下,若日志为空、无变更、或权限失效,它就什么也不做,还返回 SUCCESS。
验证三件事:
- 查
USER_MVIEWS.LAST_REFRESH_DATE是否更新:如果时间没变,说明根本没刷 - 查
USER_MVIEW_LOGS.LAST_PURGE_DATE:如果这个时间远早于现在,说明日志没被消费,可能上次刷新失败后没重试 - 手动触发一次
method => 'C':如果C模式能刷出新数据,那F模式的问题 100% 出在日志或变更捕获环节,不是性能问题,是逻辑断链
最容易被忽略的是:跨库物化视图依赖 DB Link,而 link 失效时 EXPLAIN_MVIEW 不报错,REFRESH 却静默失败——必须查 DBA_MVIEWS.BUILT_STATUS 和 DBA_MVIEW_LOGS 的状态字段是否为 VALID。
本文共计1105个文字,预计阅读时间需要5分钟。
相关专题
查物化视图刷新是否卡在 longops 里
物化视图刷新慢,第一反应不是看执行计划,而是确认它到底“卡没卡住”。oracle 把长时间运行的操作(比如刷新)记在 v$session_longops 里,只要还没超时、没报错,就可能挂在这儿不动。
执行这个查询能快速定位:
SELECT sid, serial#, opname, target, sofar, totalwork, ROUND(sofar/NULLIF(totalwork,0)*100,2) pct_done, elapsed_seconds, sql_id FROM v$session_longops WHERE opname LIKE '%refresh%' AND totalwork > 0 AND sofar < totalwork;
常见现象:
-
opname是Refresh materialized view,但pct_done长时间不动 → 刷新被阻塞或基表锁住 -
sql_id为空 → 刷新还没真正生成 SQL,卡在元数据检查或日志读取阶段 -
elapsed_seconds超过预期(比如已跑 20 分钟,而历史平均才 2 分钟)→ 需进一步查该sql_id的真实执行计划
用 DBMS_MVIEW.EXPLAIN_MVIEW 先验判断能否快刷
别等 DBMS_MVIEW.REFRESH 跑完才发现是 complete 刷新。很多“慢”本质是本该走 fast 却被迫退化成 full,而 DBMS_MVIEW.EXPLAIN_MVIEW 能在执行前暴露根因。
执行后查 MVIEW_EXCEPTIONS 或直接看输出:
EXEC DBMS_MVIEW.EXPLAIN_MVIEW('MV_SALES_SUMMARY');
关键字段 MSGTXT 里出现这些提示,基本就定位了瓶颈:
-
"REFRESH FAST IS NOT POSSIBLE"→ 缺物化视图日志,或基表没主键,或日志没开ROWIDS -
"NO LOG ON BASE TABLE"→ 基表压根没建日志,CREATE MATERIALIZED VIEW LOG ON ...漏了 -
"POTENTIAL FAST REFRESH"但实际没走 → 日志里没未消费变更(LAST_PURGE_DATE没更新),或 DML 后没提交
注意:EXPLAIN_MVIEW 不检查网络或权限,只验证定义层面可行性。如果它说“可快刷”,但刷新仍慢,问题一定出在日志数据积压、索引缺失或锁等待上。
检查刷新作业是否被其他 job 或 session 阻塞
物化视图定时刷新常通过 DBMS_JOB 或 DBMS_SCHEDULER 触发,一旦底层作业卡住,后续刷新全排队。尤其当多个 MV 属于同一刷新组时,一个卡住,整组停摆。
先看当前有没有正在跑的刷新作业:
SELECT job_name, state, last_start_date, running_instance FROM dba_scheduler_jobs WHERE job_name LIKE '%MV%' OR job_action LIKE '%REFRESH%';
再查是否有会话在等锁:
SELECT blocking_session, sid, serial#, event, sql_id FROM v$session WHERE event LIKE 'enq:%' OR event LIKE 'library cache%';
特别注意:
- 如果
blocking_session对应的是另一个DBMS_MVIEW.REFRESH会话 → 刷新组串行执行中,需确认是否真需要强一致性 - 如果
event是enq: TX - row lock contention→ 基表正被业务 DML 修改,刷新在等事务提交 - 定时任务用
DBMS_REFRESH.REFRESH时默认ATOMIC_REFRESH => TRUE,整个组锁表,改成单个 MV 刷新 +ATOMIC_REFRESH => FALSE可绕过
确认刷新是否真的在跑,还是“静默跳过”
调用 DBMS_MVIEW.REFRESH 返回成功,不代表数据更新了。尤其是 method => 'F' 模式下,若日志为空、无变更、或权限失效,它就什么也不做,还返回 SUCCESS。
验证三件事:
- 查
USER_MVIEWS.LAST_REFRESH_DATE是否更新:如果时间没变,说明根本没刷 - 查
USER_MVIEW_LOGS.LAST_PURGE_DATE:如果这个时间远早于现在,说明日志没被消费,可能上次刷新失败后没重试 - 手动触发一次
method => 'C':如果C模式能刷出新数据,那F模式的问题 100% 出在日志或变更捕获环节,不是性能问题,是逻辑断链
最容易被忽略的是:跨库物化视图依赖 DB Link,而 link 失效时 EXPLAIN_MVIEW 不报错,REFRESH 却静默失败——必须查 DBA_MVIEWS.BUILT_STATUS 和 DBA_MVIEW_LOGS 的状态字段是否为 VALID。

