直接查v$session的blocking_session和event字段可快速定位阻塞者:单实例执行select sid,serial#,username,blocking_session,event,seconds_in_wait from v$session where blocking_session is not null and status='active';rac环境须加blocking_instance条件,event为enq:tx-row lock contention即行锁冲突。

直接查 v$session 中的 blocking_session 和 event 字段,比等日志或猜 SQL 更快定位真实阻塞者
查 v$session 看谁在等、等谁、等什么锁
物化视图刷新挂起,第一反应不是翻 trace,而是立刻查实时会话链。重点不是“有没有锁”,而是“谁在等、等谁、等什么”:
- 单实例执行:
SELECT sid, serial#, username, blocking_session, event, seconds_in_wait FROM v$session WHERE blocking_session IS NOT NULL AND status = 'ACTIVE' - RAC 环境必须加
AND blocking_instance = <your_inst_id></your_inst_id>,否则跨节点阻塞会被漏掉 - 若
event是enq: TX - row lock contention,基本可断定是行级冲突;若是library cache lock,说明问题出在解析层(比如基表刚被 DDL 修改) - 别信
blocking_session为空的会话——它可能是根阻塞者,但状态已变INACTIVE或连接断开,需结合last_call_et判断是否长时间未活动
交叉验证 v$locked_object 和 dba_objects 锁了什么对象
仅看会话不够,得确认锁落在哪张表上。物化视图刷新卡住,90% 锁的是基表或日志表,不是 MV 本身:
- 运行:
SELECT ao.object_name, lo.locked_mode FROM v$locked_object lo, dba_objects ao WHERE lo.object_id = ao.object_id AND lo.session_id IN (SELECT session_id FROM v$session WHERE blocking_session IS NOT NULL) - 重点关注
object_name是否为MLOG$_*表、基表名、或物化视图名;locked_mode = 6表示排他锁(X lock),大概率就是它 - 如果看到多个
MLOG$_*被锁,说明刷新正读日志表,而业务写入正更新同一行——这是 FAST 刷新典型的死锁前兆 - 别忽略
dba_objects.status:若日志表状态是INVALID,Oracle 可能静默跳过日志读取,退化为 COMPLETE 刷新并全程锁基表
用 DBMS_MVIEW.EXPLAIN_MVIEW 验证是否已退化为 COMPLETE 刷新
很多“挂起”其实是假象:你以为它在 FAST 刷新,其实 Oracle 已悄悄切到 COMPLETE 模式,正在全量扫基表,还锁着整张表不放:
- 立即执行:
EXEC DBMS_MVIEW.EXPLAIN_MVIEW('MV_NAME'),然后查MV_CAPABILITIES_TABLE - 关键字段:
CAPABILITY_NAME = 'REFRESH_FAST'对应的POSSIBLE值为'N',或MSGTXT含"REFRESH FAST IS NOT POSSIBLE" - 常见退化原因:
CAN_USE_LOG = 'NO'(日志失效)、基表主键被删、日志缺失 JOIN 列、或物化视图定义含非确定性函数(如SYS_GUID()) - 如果已退化,改
ATOMIC_REFRESH => FALSE没用——先修复日志或重建 MV,否则你只是在给一个更慢的锁表操作加速
为什么不能只靠 alert log 或 ORA-12008 报错定位
ORA-12008 是占位符错误,alert log 只记“刷新失败”,不记“为什么失败”。等你看到这个错误,事务可能早已回滚,线索只剩内存快照:
-
ORA-12008出现后,真实错误(如ORA-00001、ORA-01652)只存在于当前会话的 10046 trace 文件中,且默认不开启 - alert log 里只会写一行
Errors in file .../trace/xxx_ora_xxx.trc,但不会告诉你该 trace 文件对应哪个会话、是否已被覆盖 - trace 文件路径在
USER_DUMP_DEST下,文件名含进程号,当天生成的才有效;过夜后可能被自动清理 - 真正有用的线索在
Deadlock graph(死锁时)或紧挨刷新语句后的第一个ORA-(非死锁时)——但前提是你要知道去哪找、什么时候找
最常被忽略的点是:刷新挂起未必是锁的问题,也可能是 MV 状态为 UNUSABLE 或 NEEDS_COMPILE,此时连锁都不会加,只是直接报错退出。查 user_mviews 的 staleness、compile_state、last_refresh_date 这三个字段,比查锁更快确认是否根本没走到刷新逻辑。











