会话、锁与阻塞

业务卡死时,先不要重启实例。大多数情况是会话互相等锁,或者一条 SQL 占着资源。

当前会话

SELECT sid, serial#, username, status, machine, program, sql_id, event, seconds_in_wait
FROM v$session
WHERE username IS NOT NULL
ORDER BY seconds_in_wait DESC;

machineprogram 用来判断是应用池、报表工具还是临时脚本。示例用户写成 APP_USER,不要用真实账号。

阻塞链

SELECT
  s.sid waiter_sid,
  s.username waiter,
  s.blocking_session blocker_sid,
  b.username blocker,
  s.event,
  s.seconds_in_wait
FROM v$session s
LEFT JOIN v$session b ON b.sid = s.blocking_session
WHERE s.blocking_session IS NOT NULL;

先看 blocker 在干什么:未提交事务、超大更新、还是忘了关会话。杀会话是最后一步:

-- 确认后再执行,SID/SERIAL# 换成你查到的
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;

锁类型速记

  • TX:行级事务锁,最常见
  • TM:表级,DDL 或外键场景会碰到
  • UL:用户锁
SELECT sid, type, lmode, request, id1, id2
FROM v$lock
WHERE type IN ('TX','TM');

注意

杀会话前确认没有长事务要保留。RAC 下阻塞可能跨实例,要看 gv$session。应用侧连接泄漏会表现为大量 INACTIVE 却占着锁。

参考:V$SESSION