查v$active_session_history必须加时间窗和等待状态过滤,仅查最近5分钟且session_state='waiting'、event匹配'enq: tx%'或'library cache lock'等关键等待事件。
查 v$active_session_history 要加时间窗和等待状态过滤
直接 select * from v$active_session_history 会扫全内存缓冲区(默认约1小时),慢、卡、结果混杂。生产环境必须缩窄范围:只查最近5分钟,且只取真正“卡着”的会话。
关键条件就两个:sample_time > SYSDATE - 5/1440(5分钟) + event LIKE 'enq: TX%' 或 event = 'library cache lock'。别漏掉 session_state = 'WAITING',否则会混入 CPU 运行中或空闲会话,干扰判断。
-
enq: TX - row lock contention表示行锁争用,大概率是业务 SQL 未提交或 FOR UPDATE 没释放 -
enq: TM - contention是表级锁,常见于 DDL 执行中(如 ALTER TABLE) -
library cache lock多半是硬解析风暴,不是数据锁,排查方向完全不同
blocking_session 字段不能单独依赖
blocking_session 在 ASH 里只是采样瞬间快照,持锁时间短于1秒、或刚好在两次采样之间提交/回滚,它就为空。你看到大量 enq: TX% 等待但 blocking_session IS NULL,不等于没阻塞——更可能是漏采,或根本是 library cache lock 伪装成 TX 等待。
真正可信的组合是:event = 'enq: TX - row lock contention' + session_state = 'WAITING' + wait_class = 'Concurrency'。三者同时成立,才能确认是真实行锁等待。
- 优先用
final_blocking_session(Oracle 12c+),它能穿透 A→B→C 级联链,比blocking_session更稳 - 若发现
final_blocking_session非空,立刻去v$session查该 SID 当前状态——v$session是实时的,v$active_session_history是快照,两者不能 JOIN,只能人工串 - RAC 环境下必须看
blocking_inst_id,跨节点阻塞不会出现在本地v$session里
递归查阻塞链必须物化中间结果
ASH 视图本身不支持直接递归 CTE(ORA-32043 报错),也不能用 CONNECT BY 直接连 v$active_session_history。想展开 A→B→C→D 链,得先物化数据再算。
做法分两步:先用 WITH 子句把目标窗口数据捞进临时集,再用递归 CTE 构建层级。重点校验三个一致性:时间(同一 sample_time 或相邻秒级)、实例号(inst_id = blocking_inst_id)、序列号(session_serial# = blocking_session_serial#)。
- 别用
sample_id = PRIOR sample_id - 1强制“前后秒”关联——采样可能跳过,造成伪链 - 阻塞关系不是持续存在的,同一对会话在不同采样点反复出现/消失,不能简单去重后当稳定链路
- 物化时加
WHERE blocking_session IS NOT NULL,否则递归起点不明确,结果爆炸
死锁互指必须在同一 sample_time 下验证
死锁不是靠单条记录识别,而是靠“同一秒内两个会话互相指对方为 blocking_session”。如果 A 的 blocking_session = B.sid,B 的 blocking_session = A.sid,且 sample_time 完全相同,event 都是 enq: TX - row lock contention,基本就是死锁实锤。
进一步交叉验证看 p1 和 p2:若 A.p1 = B.p2 且 B.p1 = A.p2,说明 TX 锁互持。注意 enq: TX - allocate ITL entry 是 ITL 不足,不是死锁,别混淆。
- 时间窗必须极窄:
sample_time BETWEEN SYSDATE - 1/1440 AND SYSDATE(最近1分钟),死锁持续通常不到1秒 - 别只查等待方,要同时查
blocking_session IS NOT NULL和session_state = 'WAITING'的会话,否则漏掉刚释放锁但被采到的持有者 - 查出互指对后,立刻切到
v$session确认双方当前状态,再查v$sql看 SQL 是否一致、事务是否未提交
实际执行时最容易忽略的是:ASH 只反映“谁在等”,不反映“谁在持”。真要定位锁源头,最终还得回到 v$locked_object 和 v$session 关联查——ASH 是线索,不是终点。











