1. 程式人生 > >Oracle清除資料庫中長時間佔用資源的非活動的會話

Oracle清除資料庫中長時間佔用資源的非活動的會話

首先我們瞭解下,會話有那些狀態:

1、active 

此狀態的會話,表示正在執行,處於活動狀態。

2、killed

此狀態的會話,被標註為刪除,表示出現了錯誤,正在回滾,當然,也是佔用系統資源的。還有一點就是,killed的狀態一般會持續較長時間,而且用windows下的工具pl/sql developer來kill掉,是不管用的,要用命令:alter system kill session 'sid,serial#' ;

3、inactive 

            該狀態處於等待操作(即等待需要執行的SQL語句),通常當DML語句已經完成。 但連線沒有釋放,這個可能是程式中沒有釋放,如果是使用中介軟體來連線的話,也可能是中介軟體的配置或者是bug 導致。

4、SNIPED- Session inactive, waiting on the client

其它說明:

  inactive對資料庫本身沒有什麼影響,但是如果程式沒有及時commit,那麼就會造成佔用過多會話。容易是DB 的session 達到極限值。

他們的做法是不處理inactive 狀態的session, 如果達到了session 的最大值, 就增加processes 和 sessions 引數。 如果kill inactive session 可能會到中介軟體有影響。

下面講怎麼清除長時間的會話數:

1、啟動資源計劃

  alter system set resource_limit=true scope=spfile;

2、設定非活動回話十五分鐘斷開,釋放資源

  alter profile default limit idle_time 15;

3.  清楚非活動的程序 (沒10分鐘傳送檢測包)

$ORACLE_HOME/network/admin 新增 SQLNET.EXPIRE_TIME=10;

SELECT SID, SERIAL#,MODULE, STATUS
FROM V$SESSION S
WHERE S.USERNAME ISNOTNULL
ANDUPPER(S.PROGRAM) IN ('TOAD.EXE', 'W3WP.EXE')
AND S.LAST_CALL_ET >= 60*60*2
AND S.STATUS = 'INACTIVE'
ORDERBY SID DESC;
如果是RAC環境,那麼最好使用下面SQL語句,使用全域性檢視GV$SESSION。
SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
FROM gv$session S
WHERE S.USERNAME ISNOTNULL
ANDUPPER(S.PROGRAM) IN ('TOAD.EXE', 'W3WP.EXE')
AND S.LAST_CALL_ET >= 2 * 60*60
AND S.STATUS = 'INACTIVE'
ORDERBY INST_ID DESC
 
 
 
 
    
  
 
    
  
 
    CREATE OR REPLACE PROCEDURE SYS.DB_KILL_IDLE_CLIENTS AUTHID DEFINER AS
  
 
       job_no number;
  
 
       num_of_kills number := 0;
  
 
    BEGIN
  
 
    
  
 
       FOR REC IN
  
 
           (SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
  
 
            FROM gv$session S
  
 
                WHERE S.USERNAME IS NOT NULL
  
 
                AND UPPER(S.PROGRAM) IN ('xxx', 'xxx.EXE')   
  
 
                     AND S.LAST_CALL_ET >= 2*60*60                              
  
 
                AND S.STATUS= 'INACTIVE'
  
 
            ORDER BY INST_ID ASC
  
 
                ) LOOP
  
 
             ---------------------------------------------------------------------------
  
 
             -- kill inactive sessions immediately
  
 
             ---------------------------------------------------------------------------
  
 
             DBMS_OUTPUT.PUT('LOCAL SID ' || rec.sid || '(' || rec.module || ')');
  
 
         execute immediate 'alter system kill session ''' || rec.sid || ', ' ||
  
 
                                rec.serial# || '''immediate' ;
  
 
    
  
 
             DBMS_OUTPUT.PUT_LINE('. killed locally ' || job_no);
  
 
             num_of_kills := num_of_kills + 1;
  
 
       END LOOP;
  
 
       DBMS_OUTPUT.PUT_LINE ('Number of killed xxxx system sessions: ' || num_of_kills);
  
 
    END DB_KILL_IDLE_CLIENTS;
  
 
    /
  
 
 
 

然後,我們可以在作業(JOB)或Schedule裡面定期呼叫該儲存過程,也可以通過後臺作業結合shell指令碼實現定期清理空閒會話的功能。例如如下所示。

建立killSession.sh指令碼,呼叫該儲存過程SYS.DB_KILL_IDLE_CLIENTS

#!/bin/bash   

logfile=/home/oracle/cron/session/log/killSession.log

echo " " >> $logfile 2>&1

echo "START ----`date`" >> $logfile 2>&1

sqlplus /nolog <<STATS

connect / as sysdba

exec sys.db_kill_idle_clients;

exit;

STATS

echo "END ------`date`" >> $logfile 2>&1

最後在系統任務中增加:

在crontab裡面配置後臺作業,每隔15分鐘執行一次,清理哪些滿足條件的空閒會話。

0,15,30,45 * * * * /home/oracle/cron/session/bin/killSession.sh >/dev/null 2>&1