<p>查ASH必须加SAMPLE_TIME和session_state双过滤,实操需满足SAMPLE_TIME > SYSDATE - 5/1440且session_state = 'WAITING',再叠加event LIKE 'enq: TX%'等条件;漏任一条件结果不可信,RAC下须用final_blocking_session+final_blocking_instance定位真实源头,还原阻塞链应按sample_id递减追踪而非CONNECT BY。</p>

查ASH必须加SAMPLE_TIME和session_state双过滤
不加时间窗的ASH查询会扫全内存buffer(默认约1小时),轻则卡住,重则因权限不足报错;只筛blocking_session IS NOT NULL但不校验是否真在等,容易把已提交或断开的僵尸会话当根因。实操必须同时满足:SAMPLE_TIME > SYSDATE - 5/1440(最近5分钟)且session_state = 'WAITING',再叠加event LIKE 'enq: TX%'或event = 'library cache lock'。漏掉任一条件,结果就不可信——比如你看到blocking_session = 456,但它其实在8分钟前就回滚了,当前只是残留快照。
RAC环境下必须用final_blocking_session定位源头
blocking_session在RAC下可能只指向本节点的中间阻塞者,真正持锁的会话在另一个实例上。final_blocking_session和final_blocking_instance才是Oracle 12c+推荐字段,它跳过A→B→C级联链,直指源头。常见错误是查到A→B→C链就kill B,结果C还在等A持有的锁。正确做法:
- 优先筛选的行必须连带查
final_blocking_instance,并用SELECT instance_number FROM v$instance确认该实例号是否有效 - 若
final_blocking_session为0或空,说明它是根阻塞源——大概率就是那个没提交的批处理会话
还原阻塞链不能靠CONNECT BY,得用SAMPLE_ID递减追踪
ASH是滚动内存表,每秒一条记录,SAMPLE_ID严格递增。用CONNECT BY PRIOR blocking_session = session_id会强行把不同时刻的会话拼在一起,比如把上午9:45的会话A和下午3:20的会话B错误关联。真实阻塞路径得聚焦同一会话在连续时刻的行为:
- 先按
sample_time DESC排序,取最近几秒的样本 - 对每个
session_id,检查其SAMPLE_ID是否连续下降、event是否稳定为enq: TX - row lock contention - 若某会话在连续3个
SAMPLE_ID中都显示blocking_session IS NULL且sql_id固定,基本可锁定为源头
死锁识别要同时抓等待方和持有方,靠p1/p2交叉匹配
死锁本质是两个及以上会话形成循环等待:A等B持有的行,B又等A持有的行。ASH不会直接标出“这是死锁”,但你能从采样数据里人工拼出这个环。做法是把同一秒内、同一sample_time下满足以下条件的行拎出来:
- 会话A的
blocking_session = B.sid,且B的blocking_session = A.sid - A和B的
event都是enq: TX - row lock contention - 检查
p1(undo segment#)和p2(slot#):若A.p1 = B.p2且B.p1 = A.p2,基本可确认TX锁互持
最易被忽略的是:必须用sample_time BETWEEN SYSDATE - 1/1440 AND SYSDATE(最近1分钟)过滤,死锁持续时间极短,范围太大会淹没信号;且要同时查blocking_session IS NOT NULL OR session_state = 'WAITING',否则漏掉已释放但刚被采样的持有者。


















