必须用GV$ACTIVE_SESSION_HISTORY,因其每秒采样、含final_blocking_instance和final_blocking_session字段,可精准定位RAC跨节点级联锁最上游持锁者,而V$SESSION仅限本实例、DBA_HIST_ACTIVE_SESS_HISTORY采样稀疏易漏根因。

直接查 GV$ACTIVE_SESSION_HISTORY,别用 V$SESSION 或 DBA_HIST_ACTIVE_SESS_HISTORY —— RAC 环境下锁源跨节点时,前两者大概率漏掉持锁者。
为什么必须用 GV$ACTIVE_SESSION_HISTORY
单靠 V$SESSION 只能看到当前实例的 blocking_session,但若持锁会话在节点 2,而你在节点 1 查,blocking_session 字段为空或为 0,误判为“无阻塞”。DBA_HIST_ACTIVE_SESS_HISTORY 是 10 秒采样一次、且默认只存当前实例数据,死锁或级联锁常在 1–2 秒内完成,历史表基本抓不到链路起点。
GV$ACTIVE_SESSION_HISTORY 每秒采样、含 blocking_instance 和 final_blocking_instance 字段,能明确告诉你锁源头落在哪个实例上。
- 必须加
inst_id或blocking_instance过滤,否则结果混杂多实例数据,无法定位 - 时间窗口别拉太宽:
SAMPLE_TIME > SYSDATE - 5/1440(最近 5 分钟)足够,再宽噪音剧增 - RAC 下若看到
blocking_instance = 0,说明不是普通会话持锁,可能是 SMON、PMON 或僵死连接
查哪几个字段能一眼看出锁源节点
核心就三个字段:blocking_instance、final_blocking_instance、event。前者指向“直接阻塞者所在节点”,后者指向“最上游持锁者所在节点”——多数情况下二者一致,但级联阻塞(A→B→C)时,final_blocking_instance 才是真源头。
-
event IN ('enq: TX - row lock contention', 'library cache lock'):锁定锁类型,排除 I/O 或网络干扰 -
blocking_session IS NOT NULL:确保是真实阻塞,而非空等待 -
final_blocking_session != 0:排除后台进程或已断连但事务未提交的情况
示例查询:
SELECT inst_id, sample_time, blocking_instance, final_blocking_instance,
blocking_session, final_blocking_session, event, sql_id
FROM gv$active_session_history
WHERE event IN ('enq: TX - row lock contention', 'library cache lock')
AND blocking_session IS NOT NULL
AND final_blocking_session != 0
AND sample_time > SYSDATE - 5/1440;查到节点号后下一步怎么验证
拿到 final_blocking_instance = 2 和 final_blocking_session = 1058 后,立刻切到实例 2 执行实时确认,别只信 ASH 采样快照——它可能刚好错过持锁瞬间。
- 连上实例 2 后查:
SELECT sid, serial#, username, status, sql_id, event, logon_time FROM v$session WHERE sid = 1058 - 重点看
status:若为INACTIVE,说明会话已退出但事务未提交;若为ACTIVE且event是SQL*Net message from client,基本可断定应用端没发commit - 若
sql_id为空,立刻查v$sqlarea或dba_hist_sqltext(注意后者依赖 AWR 快照是否及时)
容易被忽略的跨节点陷阱
RAC 下一个常见盲区是:你查的节点 CPU 正常、会话也少,但响应慢——其实热点全在另一个节点。这时候如果只查本节点的 V$SESSION 或没加 inst_id 的 GV$ASH,等于白忙。
- 执行前先确认当前连接的是哪个实例:
SELECT instance_number, instance_name FROM v$instance - 查
GV$ACTIVE_SESSION_HISTORY时,WHERE条件里必须显式包含blocking_instance或final_blocking_instance,不能只靠ORDER BY inst_id排序后肉眼找 - 如果多个会话显示同一
final_blocking_instance,别急着 kill,先核对它们的p1/p2是否一致——不一致说明锁资源不同,只是碰巧被同一个会话间接影响
真正卡住的从来不是“有没有锁”,而是“锁在哪、谁在持、持了多久、有没有被正确释放”。final_blocking_instance 和 final_blocking_session 这两个字段,就是 Oracle 在内存里给你留的唯一可信锚点。


















