AWR无法直接追溯锁表历史会话对,需先用V$ACTIVE_SESSION_HISTORY定位黄金窗口,再通过DBA_HIST_ACTIVE_SESS_HISTORY归因;因采样间隔10秒、保留1小时且blocking_session字段不稳定,必须实时捕获。

AWR 本身不记录“谁锁了谁”的实时阻塞链,查不到锁表的历史会话对;它只能告诉你“某段时间内,数据库在 enq: TX - row lock contention 或 enq: TM - contention 上花了多少时间”,但无法还原出具体是哪两个会话互相持有/等待。真要挖锁表历史,必须分两步:先用 V$ACTIVE_SESSION_HISTORY 锁定黄金窗口,再用 DBA_HIST_ACTIVE_SESS_HISTORY 做归因。
为什么直接查 DBA_HIST_ACTIVE_SESS_HISTORY 常常失败
死锁或长事务锁表往往持续不到 1 秒,而 DBA_HIST_ACTIVE_SESS_HISTORY 是每 10 秒批量刷入一次的快照,且默认只保留 1 小时。这意味着:
-
blocking_session字段在 19c 以前版本不稳定,部分采样行为NULL或0,导致互指关系断裂 - Oracle 自动回滚牺牲者(victim)后,后续采样中
blocking_session被清空,历史表只剩“单边等待”快照 - 若问题发生在 2 小时前,该表已无数据;若发生在 5 分钟前但没及时查
V$ASH,大概率错过关键样本
必须先用 V$ACTIVE_SESSION_HISTORY 定位“黄金 5 分钟”
死锁或锁表现象发生后,立刻执行以下查询(别等 AWR 报告生成):
SELECT sample_time, session_id, blocking_session, blocking_session_serial#, event, sql_id, current_obj#
FROM v$active_session_history
WHERE sample_time > SYSDATE - 5/1440
AND (event LIKE 'enq: TX%' OR event LIKE 'enq: TM%')
AND (blocking_session IS NOT NULL
OR session_id IN (
SELECT blocking_session
FROM v$active_session_history
WHERE sample_time > SYSDATE - 5/1440
AND blocking_session IS NOT NULL
))
ORDER BY sample_time DESC;关键判断点:
- 看到两个会话 A 和 B 在**同一
sample_time下互相指向对方的blocking_session**,就是死锁链实锤 -
event = 'enq: TX - row lock contention'才是真行锁死锁;enq: TX - allocate ITL entry是 ITL 不足,不是锁表 - 记下这对会话的
session_id、blocking_session_serial#和精确到秒的sample_time——这是后续查历史表的唯一可靠锚点
用 DBA_HIST_ACTIVE_SESS_HISTORY 做归因,不是定位
拿到精确时间锚点后,才去历史表里扩大时间范围查上下文:
SELECT sample_time, session_id, blocking_session, blocking_session_serial#, event, sql_id, current_obj#
FROM dba_hist_active_sess_history
WHERE sample_time BETWEEN TO_DATE('2026-10-26 14:22:35', 'YYYY-MM-DD HH24:MI:SS')
AND TO_DATE('2026-10-26 14:22:45', 'YYYY-MM-DD HH24:MI:SS')
AND (event LIKE 'enq: TX%' OR event LIKE 'enq: TM%')
ORDER BY sample_time;这个阶段的目标不是找“谁卡住了谁”,而是:
- 确认该阻塞是否在多个连续采样点中持续存在(排除瞬时抖动)
- 关联
sql_id查DBA_HIST_SQLSTAT,看对应 SQL 的elapsed_time_max是否远超平均值 - 结合
current_obj#查DBA_OBJECTS,确认被锁的是哪张表,再检查外键索引是否缺失(尤其对enq: TM - contention)
最易被忽略的一点:AWR 报告里的 “Top 5 Timed Events” 只反映聚合等待,它不会告诉你 blocking_session 是谁;而 V$ACTIVE_SESSION_HISTORY 内存视图一旦被新采样覆盖就永远丢失——所以“立刻查”不是建议,是硬性操作前提。


















