首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 被鎖定進程強制終極方案:從 SQL Kill 到 OS 層面 Loop Kill 完整流程

     編輯:Oracle 資料庫基礎

前言

生產環境常遇到 ALTER SYSTEM KILL SESSION 標記為 "KILLED" 但進程長時間不釋放鎖、不退出的殭屍進程。本文提供四步驟標準處理流程:識別鎖定對象 → SQL 層面 Kill → 驗證殘留 → OS 層面強制終止 (Linux kill -9 / Windows orakill),並附自動化腳本與風險控管建議。

步驟 1:識別被鎖定對象與持有 Session

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 l.object_id = o.object_id
JOIN v$session s ON l.session_id = s.sid;

輸出範例:

OBJECT_NAME    MACHINE          SID  SERIAL#
-------------- ---------------- ---- -------
ORDERS         APP-SERVER-01    42   21993
ORDER_ITEMS    APP-SERVER-01    42   21993

步驟 2:SQL 層面標記 Kill

ALTER SYSTEM KILL SESSION '42,21993';

狀態變為 KILLED,但進程可能因回滾大事務、等待 I/O、持有鎖等原因延遲退出。

批次產生 Kill 指令

SELECT 'ALTER SYSTEM KILL SESSION ''' || s.sid || ',' || s.serial# || ''';'
FROM v$locked_object l
JOIN dba_objects o ON l.object_id = o.object_id
JOIN v$session s ON l.session_id = s.sid;

步驟 3:獲取 OS 進程/執行緒 ID (SPID)

若過段時間 (建議 5-10 分鐘) 進程仍存活,查詢對應 OS 執行緒:

SELECT p.spid, s.osuser, s.program
FROM v$session s
JOIN v$process p ON s.paddr = p.addr
WHERE s.sid = 42;  -- 步驟 1 取得的 SID

輸出:SPID=12345, OSUSER=oracle, PROGRAM=oracle@db01 (TNS V1-V3)

步驟 4:OS 層面強制終止

Linux/Unix:root 執行 kill -9

# kill -9 12345

風險:kill -9 不允許進程清理 (釋放共享記憶體段、關閉檔案描述符、通知 PMON),可能導致:
- 共享記憶體段殘留 (需 ipcrm 清理)
- PMON 需額外時間清理進程資源
- 極端情況下資料庫不穩定需重啟

Windows:orakill 工具終止執行緒

C:\> orakill ORCL 12345
  • ORCL:Oracle 實例名 (SID)
  • 12345:步驟 3 取得的 SPID (Windows 執行緒 ID)
  • orakill.exe 位於 %ORACLE_HOME%\bin\

優勢:orakill 通知 Oracle 內部結構清理,比純粹 TerminateThread 安全。

自動化存儲過程 (謹慎使用)

CREATE OR REPLACE PROCEDURE force_kill_locked_sessions AS
  v_spid VARCHAR2(20);
  v_cmd  VARCHAR2(500);
BEGIN
  FOR r IN (
    SELECT s.sid, s.serial#, p.spid
    FROM v$locked_object l
    JOIN dba_objects o ON l.object_id = o.object_id
    JOIN v$session s ON l.session_id = s.sid
    JOIN v$process p ON s.paddr = p.addr
  ) LOOP
    -- 1. SQL Kill
    EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || r.sid || ',' || r.serial# || '''';
    
    -- 2. 等待 30 秒
    DBMS_LOCK.SLEEP(30);
    
    -- 3. 檢查是否仍存在
    BEGIN
      SELECT 1 INTO v_spid FROM v$session WHERE sid = r.sid;
      -- 仍存在 → OS Kill
      IF SYS_CONTEXT('USERENV', 'SERVER_HOST') LIKE '%Windows%' THEN
        v_cmd := 'orakill ' || SYS_CONTEXT('USERENV', 'INSTANCE_NAME') || ' ' || r.spid;
      ELSE
        v_cmd := 'kill -9 ' || r.spid;
      END IF;
      -- 需外部程式執行 (DBMS_SCHEDULER 外部作業或 Java Stored Procedure)
      -- 此處略過實際執行,僅記錄
      INSERT INTO kill_audit (sid, serial, spid, action, cmd, ts)
      VALUES (r.sid, r.serial#, r.spid, 'OS_KILL', v_cmd, SYSTIMESTAMP);
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        NULL; -- 已正常退出
    END;
  END LOOP;
  COMMIT;
END;

風險控管與最佳實務

風險緩解措施
誤殺正常進程雙人複核 SID/SPID、記錄審計日誌、限制執行權限
資料庫不穩定優先等待 PMON 清理、僅在業務受阻不可接受時執行 OS Kill
共享記憶體殘留事後檢查 ipcs -m、必要時 ipcrm
資料不一致殺掉進程等同強制回滾,確認應用有重試/冪等機制

預防勝於治療:減少殭屍進程產生

  1. 適當設定 SQLNET.EXPIRE_TIME:檢測死連線,預設 10 分鐘
  2. 應用層連線池配置:啟用驗證查詢、空閒超時回收
  3. 長時間交易監控:V$TRANSACTION + V$SESSION_LONGOPS 告警
  4. 資源管理計畫:DBMS_RESOURCE_MANAGER 限制會話 CPU/IO/執行時間
  5. 定期巡檢:腳本掃描 STATUS='KILLED' 超過閾值的 Session

結語

「Kill Session 不死」是 Oracle DBA 必經的修煉。標準流程:SQL Kill → 耐心等待回滾 → 確認 SPID → OS 層面精準打擊 (Linux kill -9 / Windows orakill)。核心原則:能等則等,必殺則精,事後必查。建立自動化巡檢與審計機制,將人工介入降至最低,才是成熟運維的標誌。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved