应通过V$SESSION和V$LOCK识别阻塞链,重点关注STATE='WAITING'且EVENT含'enq:%'的会话,结合BLOCKING_SESSION、SQL_ID、执行计划及对象信息定位根因,并设置连续超时阈值告警。
查 V$SESSION 和 V$LOCK 识别阻塞链
oracle 的锁等待本质是会话(session)在等待其他会话持有的锁资源,关键视图是 v$session(查当前会话状态)和 v$lock(查锁类型与持有/等待关系)。不能只看 status = 'inactive' 就认为没事——真正要盯的是 state = 'waiting' 且 event 包含 'enq: tx - row lock contention' 或 'enq: tm - dml lock' 这类锁事件。
实操建议:
- 用
SELECT SID, SERIAL#, USERNAME, EVENT, STATE, BLOCKING_SESSION, SQL_ID FROM V$SESSION WHERE STATE = 'WAITING' AND EVENT LIKE 'enq:%'快速捞出所有锁等待会话 -
BLOCKING_SESSION非空时,说明该会话被另一个会话阻塞;再连查一次V$SESSION获取阻塞方的SQL_ID和执行时间 - 避免直接查
V$LOCK做 join——它不带会话上下文,容易漏掉隐式锁(如未提交事务导致的行锁)
用 JDBC 定时轮询 + 超时阈值触发告警
Java 程序不能依赖 Oracle 自带的告警机制(如 OEM),得自己建轻量级轮询。重点不是“查到锁就告警”,而是“查到锁且持续超时才告警”——否则批量作业启动瞬间的短暂等待会引发误报。
实操建议:
- 用
ScheduledExecutorService每 10–30 秒执行一次查询(太密加重 DB 负担,太疏错过关键窗口) - 对每个等待会话维护本地缓存(如
ConcurrentHashMap<String, Long>,key 为SID,SERIAL#),记录首次检测到等待的时间戳 - 只有当等待时长 > 预设阈值(例如 60 秒)才触发告警逻辑;阈值需结合业务容忍度调优,OLTP 系统建议 ≤ 30 秒,报表类可放宽至 120 秒
- 注意
Connection必须设置setNetworkTimeout(),防止 DB 假死导致线程卡住
提取阻塞 SQL 和执行计划辅助定位根因
光知道“谁在等”不够,得知道“等什么 SQL”以及“为什么慢”。Oracle 中被阻塞的会话可能已拿到 SQL_ID,但若 SQL_ID 为空(常见于 PL/SQL 块或绑定变量未解析完),就得回溯到 PREV_SQL_ID 或查 V$OPEN_CURSOR。
立即学习“Java免费学习笔记(深入)”;
实操建议:
- 对命中阈值的会话,立即执行:
SELECT SQL_TEXT FROM V$SQL WHERE SQL_ID = ?,并补充查V$SQL_PLAN获取执行计划(重点关注ACCESS_PREDICATES是否缺失索引) - 如果
SQL_ID为空,尝试SELECT SQL_TEXT FROM V$SQLAREA WHERE HASH_VALUE = (SELECT PREV_HASH_VALUE FROM V$SESSION WHERE SID = ?) - 避免在告警路径中执行耗时操作(如全表扫描
V$SQL),提前建好基于SQL_ID的索引视图或物化视图(DBA 配合)
告警内容必须包含可操作的上下文字段
运维同学收到告警邮件/钉钉消息后,第一反应不是“哦,有锁”,而是“我该 kill 哪个会话?谁写的这个 SQL?影响哪些表?”——所以告警体不能只有“发现锁等待”,必须结构化输出关键现场信息。
实操建议:
- 每条告警至少包含:
BLOCKING_SID、BLOCKING_SERIAL#、BLOCKED_SID、BLOCKED_SERIAL#、BLOCKING_SQL_ID、BLOCKED_SQL_ID、OBJECT_NAME(从V$LOCKED_OBJECT关联查)、等待秒数 - 提供一键 kill 命令模板:
ALTER SYSTEM KILL SESSION '<sid>,<serial#>' IMMEDIATE;,但加粗提示“需确认业务影响后再执行” - 如果应用使用连接池(如 HikariCP),额外标注该会话所属的
application_name(通过V$SESSION.PROGRAM或自定义MODULE字段识别),方便快速定位服务实例
真实环境里最易忽略的是锁等待的“瞬态性”:一个会话可能在两次轮询之间完成提交,告警还没发出去就消失了;也可能因网络抖动导致 JDBC 查询超时,误判为锁等待。所以阈值判定必须带“连续 N 次命中”条件,而不是单次结果。

















