ORACLE定期清理INACTIVE会话

Posted lclc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ORACLE定期清理INACTIVE会话相关的知识,希望对你有一定的参考价值。

2014-03-31 22:25 by 潇湘隐者, 21797 阅读, 12 评论, 收藏, 编辑

  ORACLE数据库会话有ACTIVE、INACTIVE、KILLED、 CACHED、SNIPED五种状态。INACTIVE状态的会话表示此会话处于非活动、空闲、等待状态。例如PL/SQL Developer连接到数据库,执行一条SQL语句后,如果不继续执行SQL语句,那么此会话就处于INACTIVE状态。一般情况下,少量的INACTVIE会话对数据库并没有什么影响,如果由于程序设计等某些原因导致数据库出现大量的会话长时间处于INACTIVE状态,那么将会导致大量的系统资源被消耗,造成会话数超过系统session的最大值,出现ORA-00018:maximum number of sessions exceeded错误。

有时候需要清理那些长时间处于INACTIVE状态的会话。人为定期检查、杀掉这类会话肯定不太现实,要定期清理那些长时间处于INACTIVE的会话,只能通过作业来实现;另外需要注意,Kill掉这些会话需要需要谨慎,稍不注意,就有可能误杀了一些正常的会话。那么我们该如何定义这类会话呢?下面是我结合业务规则定义的:

  1: 会话的Status必须为INACTIVE,如果会话状态为ACTIVE、KILLED、CACHED、SNIPED状态,不做考虑。

  2: 会话必须已经长时间处于INACTIVE状态。例如,处于INACTIVE状态超过了两小时的会话进程,才考虑Kill。这个视具体业务或需求决定,有可能超过半小时就可以杀掉会话进程。至于如何计算处于INACTIVE会话状态的时间,这个可以 通过V$SESSION的LAST_CALL_ET字段来判别,需要查询处于INACTIVE状态两小时或以上的会话,就可以通过查询条件S.LAST_CALL_ET >= 60*60*2实现,当然最好写成 S.LAST_CALL_ET >= 7200

  3: 连接到会话的程序。比如,某个特定的应用程序产生的INACTIVE会话才要清理。例如, Toad工具、PL/SQL Developer工具。关于PROGRAM这个需要根据当前项目的具体情况设置,下面仅仅使用TOAD.EXE、W3WP.EXE举例说明。

clip_image002

   2: FROM V$SESSION S
   4: AND UPPER(S.PROGRAM) IN (\'TOAD.EXE\', \'W3WP.EXE\')
   5: AND S.LAST_CALL_ET >= 60*60*2
   7: ORDER BY SID DESC;

如果是RAC环境,那么最好使用下面SQL语句,使用全局视图GV$SESSION。

   2: FROM gv$session S
   4: AND UPPER(S.PROGRAM) IN (\'TOAD.EXE\', \'W3WP.EXE\')
   5: AND S.LAST_CALL_ET >= 2 * 60*60
   7: ORDER BY INST_ID DESC

接下来创建存储过程SYS.DB_KILL_IDLE_CLIENTS. 方便调用该功能执行kill inactive 会话。注意:xxx部分用实际业务的PROGRAM来替代。

   1:  
   3:    job_no number;
   4:    num_of_kills number := 0;
   6:  
   8:        (SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
  10:             WHERE S.USERNAME IS NOT NULL
  12:                  AND S.LAST_CALL_ET >= 2*60*60                              
  14:         ORDER BY INST_ID ASC
  16:          ---------------------------------------------------------------------------
  18:          ---------------------------------------------------------------------------
  19:          DBMS_OUTPUT.PUT(\'LOCAL SID \' || rec.sid || \'(\' || rec.module || \')\');
  21:                             rec.serial# || \'\'\'immediate\' ;
  23:          DBMS_OUTPUT.PUT_LINE(\'. killed locally \' || job_no);
  24:          num_of_kills := num_of_kills + 1;
  25:    END LOOP;
  26:    DBMS_OUTPUT.PUT_LINE (\'Number of killed xxxx system sessions: \' || num_of_kills);
  27: END DB_KILL_IDLE_CLIENTS;
1: CREATE OR REPLACE PROCEDURE SYS.DB_KILL_IDLE_CLIENTS AUTHID DEFINER AS
   2:    job_no number;
   3:    num_of_kills number := 0;
   5:  
   7:        (SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
   9:             WHERE S.USERNAME IS NOT NULL
  11:                  AND S.LAST_CALL_ET >= 2*60*60                              
\'KILLED\'
  14:             ) LOOP
  16:          -- kill inactive sessions immediately
  18:          DBMS_OUTPUT.PUT(\'LOCAL SID \' || rec.sid || \'(\' || rec.module || \')\');
  20:                             rec.serial# || \'\'\'immediate\' ;
  21:  
  22:          DBMS_OUTPUT.PUT_LINE(\'. killed locally \' || job_no);
  23:          num_of_kills := num_of_kills + 1;
  24:    END LOOP;
  25:    DBMS_OUTPUT.PUT_LINE (\'Number of killed system sessions: \' || num_of_kills);
  26: END DB_KILL_IDLE_CLIENTS;
1: #!/bin/bash
   2:  
   3:  
   4:  
   6:  
   7: echo " " >> $logfile 2>&1
   8: echo "START ----`date`" >> $logfile 2>&1
   9: sqlplus /nolog <<STATS
  11: exec sys.db_kill_idle_clients;
  12: exit;
  14:  
  15: echo "END ------`date`" >> $logfile 2>&1

在crontab里面配置后台作业,每隔15分钟运行一次,清理哪些满足条件的空闲会话。

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

以上是关于ORACLE定期清理INACTIVE会话的主要内容,如果未能解决你的问题,请参考以下文章

Oracle inactive session的清理

如何迅速杀掉数据库里inactive的会话

oracle许多inactive会话久久不释放,我该怎么办

Oracle查询session连接数和inactive

plsql会话inactive状态 程序还在执行吗

CentOS7下设置定期清理Oracle归档日志