优先使用V$SESSION_BLOCKERS定位阻塞源头,它直接暴露阻塞SID和链长;RAC环境须用GV$SESSION_BLOCKERS;结合ASH分析等待链与SQL耗时;杀会话前须查事务、进程归属,优先用DISCONNECT SESSION IMMEDIATE。
查阻塞源头:优先用 V$SESSION_BLOCKERS,不是手写多表关联
oracle 19c 的 v$session_blockers 是专为这事设计的视图,它直接暴露正在阻塞其他会话的 sid 和阻塞链长度,不用再手动 join v$session 和 v$lock。很多 dba 还在用老套路写三层嵌套查询,结果要么漏掉递归阻塞,要么查到一半就卡住。
执行这个即可定位一级阻塞者:
SELECT blocking_session, COUNT(*) AS blocked_count,
MAX(blocking_session_status) AS status,
MAX(program) AS program
FROM v$session_blockers
GROUP BY blocking_session
ORDER BY blocked_count DESC;注意点:
-
blocking_session为 NULL 的行表示“自己就是根阻塞源”,别误当成普通会话放过 - 该视图不包含历史信息,只反映当前快照;若阻塞刚发生又消失,可能查不到
- RAC 环境下必须查
GV$SESSION_BLOCKERS,否则只看到本节点
确认阻塞影响范围:结合 ASH 看等待链和 SQL 实际耗时
V$SESSION_BLOCKERS 告诉你“谁在挡路”,DBA_HIST_ACTIVE_SESS_HISTORY(或实时 V$ACTIVE_SESSION_HISTORY)告诉你“挡了多久、挡在哪条 SQL 上”。尤其当阻塞会话状态是 ACTIVE 但 SQL_ID 为空(比如网络中断后挂起),仅靠 V$SESSION 无法判断它是否还在回滚。
推荐组合查法:
SELECT s.sid, s.serial#, s.username, s.program,
a.sql_id, a.event, a.wait_time, a.time_waited,
ROUND(a.time_waited/60,1) AS mins_blocked
FROM v$session s
JOIN v$active_session_history a ON s.sid = a.session_id
WHERE s.sid IN (
SELECT blocking_session FROM v$session_blockers
)
AND a.sample_time > SYSDATE - 1/24; -- 过去1小时关键信号:
-
event是enq: TX - row lock contention或enq: TM - contention:说明锁对象明确,可顺藤摸瓜查DBA_BLOCKERS -
sql_id为空但event是SQL*Net message from client:大概率是客户端断连未清理,会话卡在 inactive 状态但 PADDR 仍占资源 -
time_waited持续增长:说明阻塞未缓解,不能等 PMON 自动回收
杀会话前必做三件事:检查事务、确认进程归属、选对命令类型
直接 ALTER SYSTEM KILL SESSION 'sid,serial#' 很容易留下 KILLED 状态的僵尸会话——它不再响应新请求,但仍在占用 PGA、锁、undo,且 PMON 可能要等几分钟才清理。更糟的是,如果会话正回滚大事务,IMMEDIATE 会让它强行中断并重做全部 undo,反而拖慢系统。
由 ReMe 驱动的记忆管理系统,支持跨会话记忆持久化、自动应用用户偏好以及智能上下文压缩...
动手前务必验证:
- 查
V$TRANSACTION:确认该会话是否有未提交事务,USED_UREC是否在下降(说明回滚中) - 查
V$PROCESS对应的SPID:避免误杀后台进程(如PMON、DBW0),PROGRAM字段含oracle@+ 主机名的才是用户进程 - 优先用
DISCONNECT SESSION ... IMMEDIATE:它直接终止服务器进程,比KILL SESSION更彻底,且不依赖 PMON 清理
示例命令:
ALTER SYSTEM DISCONNECT SESSION '7938,41571' IMMEDIATE;
杀完还要盯两分钟:防止被杀会话触发连锁阻塞
一个常见疏忽是:杀掉 A 后,B 立即拿到锁开始执行,但 B 的 SQL 又触发了另一个锁争用(比如更新同一张表的另一批行),导致 C 被新阻塞。此时 V$SESSION_BLOCKERS 里 A 消失了,但 B 又成了新源头,监控断档就会漏掉。
建议操作节奏:
- 执行
DISCONNECT SESSION后,立刻轮询V$SESSION_BLOCKERS和V$SESSION_WAIT(间隔 10 秒,持续 2 分钟) - 重点盯
EVENT为enq: TX或library cache lock的活跃会话,它们最容易成为第二波阻塞源 - 如果发现新阻塞源的
PROGRAM是应用中间件(如java@、python@),别急着再杀,先查应用日志是否批量任务异常重试
真正难处理的从来不是单个会话,而是阻塞从数据库层向上蔓延到连接池、API 网关甚至前端重试逻辑——这时候杀得再快也没用,得停业务接口限流。

















