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

Oracle 8i 實現閒置連線自動斷開與重連機制

     編輯:Oracle 資料庫基礎

問題背景

兩層架構 (Client/Server) 應用中,用戶操作完成後長時間不斷開,佔用有限的資料庫連線 (Process/Session)、PGA 記憶體、鎖資源,導致真實業務無法獲取連線、伺服器負載飆升。三層架構可用連線池 解決,兩層架構需資料庫端主動清理。

核心思路:後台 Job 定時掃描 V$SESSION

  • 識別閒置超過閾值 (如 60 分鐘) 的 Session。
  • 自動 `ALTER SYSTEM KILL SESSION` 釋放資源。
  • 可選:先發送警告訊息給客戶端 (需應用協助)。

關鍵動態視圖欄位

欄位型別含義
SID / SERIAL#NUMBERSession 唯一識別,Kill 所需
USERNAMEVARCHAR2資料庫用戶
STATUSVARCHAR2ACTIVE / INACTIVE / KILLED
LOGON_TIMEDATE登入時間
LAST_CALL_ETNUMBER最後一次 Call 結束後經過秒數 (閒置時間核心指標)
MACHINEVARCHAR2客戶端主機名
PROGRAMVARCHAR2客戶端程式名
PADDRRAW對應背景進程位址 (可關聯 V$PROCESS.SPID 取得 OS PID)

識別閒置 Session 查詢


SELECT s.SID, s.SERIAL#, s.USERNAME, s.STATUS, s.MACHINE, s.PROGRAM,
       s.LOGON_TIME,
       s.LAST_CALL_ET AS IDLE_SECONDS,
       p.SPID AS OS_PID,
       'ALTER SYSTEM KILL SESSION ''' || s.SID || ',' || s.SERIAL# || ''' IMMEDIATE;' AS KILL_CMD
FROM V$SESSION s
JOIN V$PROCESS p ON s.PADDR = p.ADDR
WHERE s.TYPE = 'USER'
  AND s.STATUS = 'INACTIVE'
  AND s.LAST_CALL_ET > 3600  -- 閒置超過 1 小時 (秒)
  AND s.USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN')  -- 排除系統帳號
  AND s.MACHINE NOT IN ('batch-server','etl-server')       -- 排除長跑批次機器
ORDER BY s.LAST_CALL_ET DESC;

自動清理預存程序


CREATE OR REPLACE PROCEDURE pr_kill_idle_sessions (p_idle_minutes IN NUMBER DEFAULT 60) AS
  v_kill_cmd VARCHAR2(200);
  v_cnt      PLS_INTEGER := 0;
BEGIN
  FOR r IN (
    SELECT SID, SERIAL#
    FROM V$SESSION
    WHERE TYPE = 'USER'
      AND STATUS = 'INACTIVE'
      AND LAST_CALL_ET > p_idle_minutes * 60
      AND USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN')
      AND MACHINE NOT IN ('batch-server','etl-server')
  ) LOOP
    v_kill_cmd := 'ALTER SYSTEM KILL SESSION ''' || r.SID || ',' || r.SERIAL# || ''' IMMEDIATE';
    BEGIN
      EXECUTE IMMEDIATE v_kill_cmd;
      v_cnt := v_cnt + 1;
      DBMS_OUTPUT.PUT_LINE('Killed: ' || v_kill_cmd);
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Failed to kill ' || r.SID || ': ' || SQLERRM);
    END;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('Total killed: ' || v_cnt);
END;
/
  • 需以 **SYS** 建立並授權執行 (`GRANT EXECUTE ON pr_kill_idle_sessions TO sys`)。
  • `IMMEDIATE` 關鍵字讓 Session 立即中斷進行中的 Call 並釋放鎖,不等待交易結束。
  • 排除清單 (系統帳號、批次伺服器) 防止誤殺關鍵作業。

建立定時 Job (DBMS_JOB)


CONNECT sys/password AS SYSDBA
VARIABLE jobno NUMBER;
BEGIN
  DBMS_JOB.SUBMIT(
    job       => :jobno,
    what      => 'BEGIN pr_kill_idle_sessions(60); END;',
    next_date => SYSDATE,
    interval  => 'SYSDATE + 30/1440'  -- 每 30 分鐘執行一次
  );
  COMMIT;
END;
/
PRINT jobno;
  • 確認 `JOB_QUEUE_PROCESSES > 0` (init.ora),否則 Job 不會啟動。
  • 查詢 `DBA_JOBS` 驗證 Job 狀態、`NEXT_DATE`、`FAILURES`。

OS 層面輔助清理 (極端情況)

若 Session 被標記 `KILLED` 但長時間未消失 (等待資源/rollback),可在 OS 層面殺掉對應 Process:


# 從上述查詢取得 OS_PID (SPID)
kill -9 

警告:OS Kill 為最後手段,可能導致資料檔損壞、Instance Crash,僅在 `ALTER SYSTEM KILL SESSION` 無效且確認該 Session 無關鍵交易時使用。

替代方案:SQL*Net / 監聽器層面

  • `SQLNET.ORA` 設定 `SQLNET.EXPIRE_TIME = 30` (分鐘) — 伺服器定期發送探測封包,偵測客戶端網路中斷並自動清理 Session。
  • 監聽器 `LISTENER.ORA` 設定 `INBOUND_CONNECT_TIMEOUT` 限制連線建立階段等待。

總結

透過 `V$SESSION.LAST_CALL_ET` 識別閒置 Session、`DBMS_JOB` 定時執行 `ALTER SYSTEM KILL SESSION IMMEDIATE`、配合 `SQLNET.EXPIRE_TIME` 網路層探測,可在 Oracle 8i/9i 兩層架構環境有效回收閒置連線資源。現代版本 (11g+) 推薦使用 **Resource Manager** (`IDLE_TIME` 指令) 或 **Database Resident Connection Pooling (DRCP)** 統一管理,無需自訂 Job。

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