ash可通过分析blocking_session与enq: tx%等待事件组合,识别会话间循环阻塞链,结合v$active_session_history查最近5分钟采样、awr报告确认ora-00060及影响范围,前提是statistics_level=typical/all且权限充足。
怎么从ash里捞出死锁相关的会话链
ash(active session history)本身不直接标记“这是死锁”,但它能还原出死锁发生前几秒内所有活跃会话的等待和持有状态,是定位死锁链条最接近实时的手段。关键不是等死锁报错(ora-00060)之后再查,而是在锁等待升级成死锁前就识别出循环依赖苗头。
执行以下查询,重点看 blocking_session 和 event 字段的组合:
SELECT sample_time,
session_id,
session_serial#,
blocking_session,
blocking_session_serial#,
event,
sql_id,
program,
machine
FROM dba_hist_active_sess_history
WHERE sample_time > SYSDATE - 1/24 -- 查最近1小时
AND (blocking_session IS NOT NULL OR event LIKE 'enq: TX%')
ORDER BY sample_time DESC;
-
event LIKE 'enq: TX%'表示事务级行锁争用,是死锁高发等待事件 - 若某行的
blocking_session指向另一个会话,而那个会话的blocking_session又指回当前会话(或形成 A→B→C→A 环),就是死锁链雏形 - ASH采样间隔默认 1 秒,但历史表(
dba_hist_active_sess_history)可能被压缩,优先用v$active_session_history查最近 5 分钟更准
为什么不能只靠 v$lock 或 v$locked_object 定位死锁链
因为 v$lock 和 v$locked_object 只反映“当前持有哪些锁”,不记录“谁在等谁”。一旦 Oracle 自动回滚了牺牲者(victim),这些视图里的锁信息可能已清空,只留下断点式快照。
典型误判场景:
- 查
v$locked_object发现只有 1 个会话在锁表 → 实际可能是 A 刚释放锁、B 还没拿到,中间有 200ms 空档,ASH 能捕获这个窗口 -
v$session.blocking_session为空 → 不代表没阻塞,只是当时没在采样点上被捕捉到;ASH 多次采样叠加后能看出趋势 - 死锁发生瞬间,
v$lock中两个会话的block=1标志可能同时为 0(Oracle 已清理),但 ASH 里仍保留它们连续几秒都在等对方的记录
ASH + AWR 联合分析死锁的实操要点
单靠 ASH 只能看到“现象”,结合 AWR 报告才能确认“是否真发生了死锁”以及“影响范围”。ORA-00060 错误一定会出现在 AWR 的 Top Events 和 Incident Summary 里。
操作顺序建议:
- 先跑
awr_report_text(用awrrpt.sql脚本),时间范围覆盖疑似死锁时段,搜索报告中是否出现enq: TX - row lock contention或ORA-00060 - 在 AWR 报告的 “SQL ordered by Gets” 或 “SQL ordered by Executions” 里,找出
sql_id对应的语句,再回 ASH 表里过滤该sql_id的全部采样行 - 注意
dba_hist_active_sess_history默认只保留 7 天(由db_controlfile_record_keep_time控制),超时数据进不了 AWR,此时必须依赖 alert.log + trace 文件
容易被忽略的 ASH 使用限制
不是所有环境都能靠 ASH 快速定位死锁链,几个硬性前提得满足:
- 数据库必须启用
STATISTICS_LEVEL = TYPICAL或ALL(BASIC下 ASH 不采集) - 用户需有
SELECT_CATALOG_ROLE或直接授予SELECTondba_hist_active_sess_history - 如果用了 RAC,要查
gv$active_session_history并加inst_id过滤,否则可能漏掉跨实例的等待关系 - ASH 不保存绑定变量值,所以即使看到
sql_id,也得结合v$sql_bind_capture或应用日志才能还原具体哪条 update 影响了哪行
真正卡住的地方往往不在 SQL 写法,而在事务边界没控制好 —— 比如一个业务事务横跨三次 HTTP 请求,中间任何一次失败都可能导致锁残留。ASH 能告诉你“谁在等”,但没法自动推断“为什么还不提交”。











