不能直接在存储过程中杀掉会话,只能生成或执行ALTER SYSTEM KILL SESSION语句,真正终止由PMON异步完成且受事务状态和等待事件限制。
不能直接在存储过程中“杀掉”会话,只能生成或执行 alter system kill session 语句 —— 真正的终止动作由数据库后台进程(pmon)异步完成,且受事务状态、等待事件等限制。
查哪些会话算“长时间运行”?别只看 LAST_CALL_ET
很多人误以为 LAST_CALL_ET 大于某值(比如 7200 秒)就代表会话“卡住”,其实它只表示“上次调用后空闲时间”,对 ACTIVE 会话无效。真正要抓的是:
-
STATUS = 'ACTIVE'且SQL_EXEC_START早于当前时间很久(如 > 1 小时),说明 SQL 正在跑但进度异常 -
EVENT是'SQL*Net message from dblink'或'enq: TX - row lock contention'这类典型阻塞/远程等待事件 -
STATE = 'WAITING'且BLOCKING_SESSION_STATUS = 'VALID',说明它正在阻塞别人 - 结合
V$SESSION_LONGOPS查TIME_REMAINING是否长期不更新(比如卡在 99% 不动)
ALTER SYSTEM KILL SESSION 执行后会立刻释放锁吗?
不会。执行该命令后,会话状态变成 KILLED,但资源(锁、事务回滚段、PGA)仍被占用,直到 PMON 完成清理 —— 这可能耗时数分钟甚至更久,尤其当有大事务未提交时。
- 如果会话正在回滚(
V$TRANSACTION.USED_UREC在递减),强行杀 OS 进程可能导致数据不一致 - 加
IMMEDIATE只是让命令立即返回,不改变清理逻辑:ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE - 真正更快释放资源的方式是用
ALTER SYSTEM DISCONNECT SESSION '123,456' POST_TRANSACTION,它会强制结束服务器进程,但要求事务先提交/回滚完毕
写自动清理存储过程要注意什么?
别只拼 ALTER SYSTEM KILL SESSION 字符串然后 EXECUTE IMMEDIATE —— 这样缺乏上下文判断,容易误杀关键会话。
- 必须排除 DBA 用户、
BACKGROUND类型会话、以及PROGRAM为'oracle@... (PMON)'等系统进程 - 建议先查
V$SESSION的CLIENT_IDENTIFIER或MACHINE,只清理特定应用来源(如'APP_ORDER_SERVICE') - 记录日志时,至少保存
SID、SERIAL#、USERNAME、SQL_ID、EVENT和LOGON_TIME,否则事后无法复盘 - RAC 环境下必须用
GV$SESSION,且KILL SESSION要显式指定@inst_id,否则只在当前实例生效
为什么有时 KILL SESSION 像没反应?
最常见原因是会话卡在远程操作(比如 DBLink 查询)、网络中断或等待外部系统响应 —— 它根本收不到数据库发来的“终止信号”。此时 STATUS 可能仍是 ACTIVE 或 INACTIVE,但 EVENT 显示 'SQL*Net message from client' 或 'SQL*Net more data from dblink'。
- 这种会话无法被常规方式终止,必须去远端数据库查对应会话,或检查网络链路是否中断
- 若远端无响应,本地唯一办法是重启 DBLink 连接池,或改用超时控制(如
CREATE DATABASE LINK ... CONNECT TO ... IDENTIFIED BY ... USING 'tns_alias' TIMEOUT 30) - 别指望
DISCONNECT SESSION IMMEDIATE能解决这类问题 —— 它只杀本地服务器进程,DBLink 的远端连接仍存在
真正难处理的从来不是“怎么杀”,而是“该不该杀”和“杀完之后谁来兜底”。一个未提交的事务被强制中断,可能留下中间态数据;一个依赖 DBLink 的报表过程被杀,下游系统可能永远收不到结果。动手前,先确认它是不是真的“该死”。


















