ASH比v$locked_object更适合查并行死锁,因为PX进程在v$locked_object中常不显式出现或oracle_username为空,而ASH每秒采样能捕获PX进程的活动等待、完整阻塞链及时间戳,精准定位死锁现场。
并行查询本身不会直接导致死锁,但并行执行中的多个px进程(如p000、p001等)若参与了有锁竞争的dml操作,就可能卷入常规死锁链——此时ora-00060照常抛出,但根因和阻塞路径更隐蔽。
为什么ASH比v$locked_object更适合查并行死锁
并行查询启动后,主会话(QC)只负责协调,真正加锁、更新、等待的是从属的PX进程(P00x)。这些进程在v$locked_object里通常不显式出现,或oracle_username显示为空/NULL,导致传统锁视图漏掉关键参与者。
而v$active_session_history每秒采样一次,只要PX进程处于“活动等待”状态(比如卡在enq: TX - row lock contention),就会被记录,且带完整session_id、sql_id、blocking_session和event。
- ASH能捕获到QC与PX之间、PX与PX之间、PX与普通会话之间的跨会话阻塞链
- 采样时间戳(
sample_time)可对齐死锁发生时刻,避免靠猜 - 即使死锁已解除(Oracle自动回滚victim),ASH中仍保留事发前数秒的现场快照
用ASH定位并行死锁的三步查询
核心思路:先找高密度TX等待事件,再过滤出含PX进程的会话组,最后还原阻塞关系。
- 第一步:查死锁窗口内TX争用最密集的时段
SELECT TRUNC(sample_time, 'MI') ts, COUNT(*) cnt FROM v$active_session_history WHERE event = 'enq: TX - row lock contention' AND sample_time > SYSDATE - 1/24 GROUP BY TRUNC(sample_time, 'MI') ORDER BY cnt DESC FETCH FIRST 5 ROWS ONLY; - 第二步:在该时段内抓所有相关会话,重点看
program是否含P00或ora_pSELECT session_id, session_serial#, sql_id, program, event, blocking_session, blocking_session_serial#, sql_opname FROM v$active_session_history WHERE sample_time BETWEEN TO_DATE('2026-04-13 21:45:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2026-04-13 21:46:00', 'YYYY-MM-DD HH24:MI:SS') AND event = 'enq: TX - row lock contention' ORDER BY sample_time; - 第三步:确认是否为并行执行,查
sql_id对应计划SELECT * FROM v$sql_plan WHERE sql_id = '<target_sql_id>' AND operation = 'PX COORDINATOR' OR operation LIKE 'PX%';</target_sql_id>
常见误判点和过滤技巧
并行环境下的TX等待容易被误读为“只是并发高”,实际可能是死锁前兆。注意以下信号:
-
blocking_session指向另一个P00x进程,且双方sql_id相同 → 典型PX间资源循环等待 - QC会话(
program为ora@...)的event是px qref latch或DFS lock handle,但PX进程在等TX → 说明QC被PX阻塞,而PX又卡在行锁上 - 同一
sql_id下多个PX进程的current_obj#指向同一个表,且row_wait_obj#一致 → 锁冲突集中在少数热点块 - ASH中连续多条记录显示同一PX进程
blocking_session不变,但seconds_in_wait持续增长 → 不是瞬时争用,而是真实阻塞
别忽略PX进程的事务状态
并行DML开启后,每个PX进程都有独立事务上下文,但v$transaction默认只显示当前登录会话的事务。要查PX进程的事务,必须用其真实sid关联:
SELECT t.start_time, t.used_ublk, t.log_io, s.program, s.sql_id FROM v$transaction t JOIN v$session s ON t.ses_addr = s.saddr WHERE s.sid = <px_sid>;</px_sid>
如果发现多个PX进程的start_time接近、used_ublk持续增长、且都未提交,基本可判定它们正共同修改同一张表的重叠数据范围——这是并行死锁最典型的温床。这种场景下,哪怕SQL本身没写错,分区键设计不合理或并行度设置过高,都会让Oracle把本该分散的锁集中到几个块上。











