必须结合v$session的blocking_session/final_blocking_session与ASH的时间窗口采样才能准确定位持锁者、等待者及SQL;单独查任一视图易误判。
直接看和就能定位到谁在 hold 锁、谁在等、sql 是哪条——但必须限定时间窗口,否则数据太杂,容易误判。
查当前正在等 TX 锁的会话(
实时快照)
这个视图反映的是“此刻”正在等待的会话,适合快速响应。关键不是只看
,而是要连带看阻塞链:
和
字段必须一起查,12c+ 推荐优先看后者,它指向最终持有锁的会话(可能跨实例)
的低 16 位是锁模式(
),常见值 6=exclusive,4=share;但实际排查中更依赖
和
别漏掉
:如果值很大(比如 > 300),说明这个会话可能事务没提交,已空闲挂起很久
执行前先
,否则
和
显示不全
用 ASH 抓故障窗口内的锁争用热点(
)
AWR 报告里的
只告诉你“哪张表被锁得多”,但无法还原“谁、什么时候、为什么锁”。ASH 才是定位源头的核心:
必须指定精确时间范围(比如
),Oracle 19c 默认每秒采样一次,5 分钟就是 300 条记录,足够定位
重点查:
、
(关联
看具体表)、
、
四列组合
如果发现多个
都在等同一个
,那它大概率就是事务未提交的“罪魁”;如果多个
互等(A 等 B、B 等 C、C 等 A),可能是死锁,但
本身不触发 Oracle 自动死锁检测,得靠应用层或 DBA 主动 kill
注意
是前提,
或
的行直接过滤掉
确认 holder 会话到底在干什么(
+
)
找到
后,不能只看它当前执行的 SQL —— 它很可能早已执行完 DML,只是没 commit:
oracle知识库
oracle知识库下载
下载
查
:用
关联
,看
和
,如果
是 20 分钟前,
,基本坐实“长事务未提交”
查
:用 holder 的
查历史执行,重点看是否含
或
,且
很小但
很大 —— 典型慢 SQL 持有锁太久
别信
当前值:它可能显示为
(事务空闲中),此时得回溯
去查
19c 中可结合
生成文本版 ASH 报告,用
快速筛出所有相关样本行
容易被忽略的三个细节
很多排查卡在最后一步,不是因为不会查,而是忽略了这些隐性条件:
的 P2/P3 参数在 19c 中含义变了:P2 不再是
,而是 transaction ID 的高位/低位,直接解析无意义;想定位具体行,得用
结合
的
+
反查
位图索引更新引发的 TX 锁,
指向的是索引而非表,容易误判成“锁了错误的表”
唯一键冲突(如重复插入)产生的 TX 锁,等待会话的
往往和 holder 的不同,且 holder 可能已 rollback,此时
为空,只能靠 ASH 中
+
+
三者交叉比对
v$sessionashv$sessionevent = 'enq: TX - row lock contention'blocking_sessionfinal_blocking_sessionp1to_char(bitand(p1, 65535))sql_idblocking_sessionlast_call_etset linesize 200sql_idprogramdba_hist_active_sess_historySegments by Row Lock Waitssample_time between timestamp'2026-04-29 09:45:00' and timestamp'2026-04-29 09:50:00'sql_idcurrent_obj#dba_objects.object_idblocking_sessioneventsql_idblocking_sessionsql_idenq: TXsession_state = 'WAITING'ON CPUINACTIVEv$sqlv$transactionblocking_sessionv$transactionses_addrv$session.saddrstart_timeused_ublkstart_timeused_ublk > 0v$sqlsql_idUPDATEDELETEexecutionselapsed_timev$session.sql_idNULLv$transaction.start_scndba_hist_sqlstatdbms_workload_repository.ash_report_textgrep 'enq: TX'enq: TXrowiddbms_rowid.rowid_createv$locked_objectobject_idsession_idcurrent_obj#sql_idv$session.blocking_sessioneventsql_idsample_time