直接查SELECT COUNT(*) FROM v$locked_object仅确认是否存在锁,真正判断阻塞需结合v$session中event LIKE 'enq: TX%'且blocking_session IS NOT NULL或自身持锁未提交,并通过v$sql分析SQL行为与事务状态。

查 v$locked_object 有没有活跃锁记录
直接执行 SELECT COUNT(*) FROM v$locked_object,如果返回值大于 0,说明当前有对象被锁定;但别急着下结论——得看这些锁是不是正在阻塞业务。重点不是“有没有锁”,而是“有没有会话卡在 TX 等待上且没进展”。
常见错误是只查到几条 v$locked_object 记录就认定是锁导致性能差,其实可能是短时 DML 正常持有行锁(比如批量 UPDATE 刚开始),还没到阻塞程度。
看 v$session 的 event 和 blocking_session 字段
运行以下查询:
SELECT sid, serial#, username, status, event, blocking_session, sql_id<br>FROM v$session<br>WHERE event LIKE 'enq: TX%' OR blocking_session IS NOT NULL<br>ORDER BY logon_time;
关键判断点:
-
event是enq: TX - row lock contention或类似 TX 类等待,才真正指向锁争用 -
blocking_session非空,且对应会话的status是ACTIVE、sql_id不为空,说明它正执行未提交的 DML - 如果
blocking_session为空,但该会话仍在enq: TX%上等待,大概率是它自己持锁未提交(比如开了事务但忘了 COMMIT)
gv$session,否则可能漏掉其他节点上的阻塞源头。结合 v$sql 看 SQL 实际行为
光看会话 ID 不够,得确认它到底在跑什么。
对疑似阻塞会话的 sql_id 执行:
SELECT sql_text FROM v$sql WHERE sql_id = 'xxx';
重点关注:
- 是否为
UPDATE/DELETE语句,且影响行数远超预期(比如本该改 1 行,实际扫描了全表) - 是否有
FOR UPDATE且后续没跟 COMMIT/ROLLBACK - SQL 是否带绑定变量,但执行计划走了全表扫描——这会让锁持有时间大幅延长
program 名(比如都是 JDBC Thin Client),同一应用里可能混着合法长事务和异常未提交事务。警惕“伪死锁”和误杀风险
ORA-00060 错误日志只写进 alert log,但它反映的是过去发生的死锁,不是当前活跃状态。现在看到的卡顿,未必是刚发生的死锁,更可能是某会话持锁太久(比如凌晨跑的批处理没 commit),把后续所有请求堵住。
容易踩的坑:
- 看到
v$session.blocking_session就 kill,结果发现源头会话其实在执行一个合法的、需 5 分钟的报表导出 - 用
alter system kill session 'sid,serial#'后没加immediate,会话仍处于 “KILLED” 状态卡住,客户端还在等响应 - 在 RAC 上没指定实例号(如
@2),kill 命令发到了错误节点,根本无效
logon_time 很早、status 一直是 ACTIVE、又长期停在 TX 等待上的会话——它们才是拖慢整体性能的根因。



















