跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Oracle 19c中Enq: TX - row lock contention如何排查_利用ASH定位行级锁源头

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

相关文章