執行 ALTER SYSTEM KILL SESSION 'sid,serial#' 後,會話狀態變為 KILLED,但鎖定資源長時間不釋放。常見原因:
COL OBJECT_NAME FOR A30
COL MACHINE FOR A20
SELECT o.OBJECT_NAME, s.MACHINE, s.SID, s.SERIAL#
FROM V$LOCKED_OBJECT l
JOIN DBA_OBJECTS o ON o.OBJECT_ID = l.OBJECT_ID
JOIN V$SESSION s ON s.SID = l.SESSION_ID;
ALTER SYSTEM KILL SESSION 'sid,serial#';
批量產生指令(人工核對後執行):
SELECT 'ALTER SYSTEM KILL SESSION ''' || s.SID || ',' || s.SERIAL# || ''';'
FROM V$LOCKED_OBJECT l
JOIN V$SESSION s ON s.SID = l.SESSION_ID;
SELECT p.SPID, s.OSUSER, s.PROGRAM
FROM V$SESSION s
JOIN V$PROCESS p ON p.ADDR = s.PADDR
WHERE s.SID = :target_sid;
| 平台 | 命令 | 權限 |
|---|---|---|
| Linux/Unix | kill -9 <SPID> | root 或 oracle 用戶 |
| Windows | orakill <ORACLE_SID> <SPID> | Administrator / ORA_DBA 群組 |
範例:orakill ORCL 12345
⚠️ **Windows 注意**:SPID 是**執行緒 ID**,不是 Task Manager 的 PID,必須用上述查詢取得。
CREATE OR REPLACE PROCEDURE kill_zombie_sessions(p_max_wait_sec IN NUMBER DEFAULT 300) AS
v_spid VARCHAR2(24);
BEGIN
FOR r IN (
SELECT s.SID, s.SERIAL#, p.SPID
FROM V$SESSION s
JOIN V$PROCESS p ON p.ADDR = s.PADDR
WHERE s.STATUS = 'KILLED'
AND s.LAST_CALL_ET > p_max_wait_sec
) LOOP
-- 記錄審計
INSERT INTO kill_audit_log (sid, serial, spid, kill_time) VALUES (r.SID, r.SERIAL#, r.SPID, SYSDATE);
-- 嘗試優雅殺(雖狀態已 KILLED,再執行一次可觸發 PMON 加速)
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || r.SID || ',' || r.SERIAL# || ''' IMMEDIATE';
-- 等待 10 秒
DBMS_LOCK.SLEEP(10);
-- 若仍存在,OS 強殺(需建立外部程式或 Scheduler Job 呼叫 OS 命令)
-- 此處略過 OS 層面實作,建議由外部監控腳本處理
END LOOP;
COMMIT;
END;
/
-- 建立 Scheduler Job 每 5 分鐘執行一次
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'AUTO_KILL_ZOMBIE_SESSIONS',
job_type => 'STORED_PROCEDURE',
job_action => 'KILL_ZOMBIE_SESSIONS',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=5',
enabled => TRUE
);
END;
/
⚠️ 風險警告:自動殺會話屬高風險操作,**嚴禁無人值守直接 OS kill**。建議:
STATUS='KILLED' 且 LAST_CALL_ET > 300 且**非關鍵背景進程**(排除 PMON、SMON、DBWn、LGWR、CKPT、ARCH、RECO 等)。SQLNET.ORA 加入 SQLNET.EXPIRE_TIME = 10,啟用死連接檢測,讓 Server 端主動清理斷開的 Client 會話。BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'DAYTIME_PLAN',
group_or_subplan => 'OLTP_GROUP',
comment => 'Kill idle sessions after 30 min',
max_idle_time => 1800, -- 秒
max_idle_blocker_time => 600 -- 阻塞他人時更短
);
END;
/
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'DAYTIME_PLAN';
validateConnection、idleTimeout、maxLifetime,避免連接池洩漏產生殭屍會話。清除殭屍鎖定會話的標準動作:**定位 → 優雅 KILL → 等待 PMON → OS 強殺 (orakill/kill -9)**。但**頻繁出現殭屍會話本身就是架構缺陷的症狀**。請優先落實 SQLNET.EXPIRE_TIME、Resource Manager 閒置清理、連接池驗證機制,從源頭杜絕「KILLED 卻不死」的會話。