ORACLE定期清理INACTIVE会话

   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举例说明。

   1: SELECT SID, SERIAL#,MODULE, STATUS
   2: FROM V$SESSION S
   3: WHERE S.USERNAME IS NOT NULL
   4: AND UPPER(S.PROGRAM) IN ('TOAD.EXE', 'W3WP.EXE')
   5: AND S.LAST_CALL_ET >= 60*60*2
   6: AND S.STATUS = 'INACTIVE'
   7: ORDER BY SID DESC;

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

   1: SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
   2: FROM gv$session S
   3: WHERE S.USERNAME IS NOT NULL
   4: AND UPPER(S.PROGRAM) IN ('TOAD.EXE', 'W3WP.EXE')
   5: AND S.LAST_CALL_ET >= 2 * 60*60
   6: AND S.STATUS = 'INACTIVE'
   7: ORDER BY INST_ID DESC

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

   1:  
   2: CREATE OR REPLACE PROCEDURE SYS.DB_KILL_IDLE_CLIENTS AUTHID DEFINER AS
   3:    job_no number;
   4:    num_of_kills number := 0;
   5: BEGIN
   6:  
   7:    FOR REC IN
   8:        (SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
   9:         FROM gv$session S
  10:             WHERE S.USERNAME IS NOT NULL
  11:             AND UPPER(S.PROGRAM) IN ('xxx', 'xxx.EXE')   
  12:                  AND S.LAST_CALL_ET >= 2*60*60                              
  13:             AND S.STATUS= 'INACTIVE'
  14:         ORDER BY INST_ID ASC
  15:             ) LOOP
  16:          ---------------------------------------------------------------------------
  17:          -- kill inactive sessions immediately
  18:          ---------------------------------------------------------------------------
  19:          DBMS_OUTPUT.PUT('LOCAL SID ' || rec.sid || '(' || rec.module || ')');
  20:      execute immediate 'alter system kill session ''' || rec.sid || ', ' ||
  21:                             rec.serial# || '''immediate' ;
  22:      
  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;
  28: /

另外,由于kill session是直接将session
kill掉,有可能出现导致事物回滚的现象,其实我们可以使用disconnect
session完成当前事务并终止session。这种方式比alter system kill session跟安全可靠。

   1: CREATE OR REPLACE PROCEDURE SYS.DB_KILL_IDLE_CLIENTS AUTHID DEFINER AS
   2:    job_no number;
   3:    num_of_kills number := 0;
   4: BEGIN
   5:  
   6:    FOR REC IN
   7:        (SELECT SID, SERIAL#, INST_ID, MODULE,STATUS
   8:         FROM gv$session S
   9:             WHERE S.USERNAME IS NOT NULL
  10:             AND UPPER(S.PROGRAM) IN ('xxxx', 'xxxx')   
  11:                  AND S.LAST_CALL_ET >= 2*60*60                              
  12:             AND S.STATUS<>'KILLED'
  13:         ORDER BY INST_ID ASC
  14:             ) LOOP
  15:          ---------------------------------------------------------------------------
  16:          -- kill inactive sessions immediately
  17:          ---------------------------------------------------------------------------
  18:          DBMS_OUTPUT.PUT('LOCAL SID ' || rec.sid || '(' || rec.module || ')');
  19:          execute immediate 'alter system disconnect session ''' || rec.sid || ', ' ||
  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;
  27: /

然后,我们可以在作业(JOB)或Schedule里面定期调用该存储过程,也可以通过后台作业结合shell脚本实现定期清理空闲会话的功能。例如如下所示。

创建killSession.sh脚本,调用该存储过程SYS.DB_KILL_IDLE_CLIENTS

   1: #!/bin/bash
   2:  
   3:  
   4:  
   5: logfile=/home/oracle/cron/session/log/killSession.log
   6:  
   7: echo " " >> $logfile 2>&1
   8: echo "START ----`date`" >> $logfile 2>&1
   9: sqlplus /nolog <<STATS
  10: connect / as sysdba
  11: exec sys.db_kill_idle_clients;
  12: exit;
  13: STATS
  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

时间: 2024-10-02 11:16:12

ORACLE定期清理INACTIVE会话的相关文章

Oracle删除用户会话的方法

1. 以一个session做以示例, a. 找到你要杀掉的那个session, 并记下paddr select sid, username, paddr, status from v$session where username = '用户名' and status = 'INACTIVE'; b. 找到这个session所对应的spid select * from v$process where addr = '上面查寻的paddr'; c. 杀掉spid所标识的那个进程 如果你的Oracle

oracle追踪SQL会话的方式

oracle中追踪一个sql会话有很多方式,oracle 11g中官方推荐使用 DBMS_MONITOR. 在实际生产环境中,尽量慎重这个操作,尽可能找出具体的会话ID或 pid来追踪. --新建测试表 create tablespace test datafile 'E:\APP\ADMINISTRATOR\ORADATA\ORCL\test01.DBF' size 500m autoextend on next 100m maxsize unlimited extent management

Oracle中获取会话信息的两个函数分享_oracle

1. USERENV(OPTION)  返回当前的会话信息.  OPTION='ISDBA'若当前是DBA角色,则为TRUE,否则FALSE.  OPTION='LANGUAGE'返回数据库的字符集.  OPTION='SESSIONID'为当前会话标识符.  OPTION='ENTRYID'返回可审计的会话标识符.  OPTION='LANG'返回会话语言名称的ISO简记.  OPTION='INSTANCE'返回当前的实例.      OPTION='terminal'返回当前计算机名  S

ORACLE 博客文章目录(2015-05-27更新)

从接触ORACLE到深入学习,已有好几年了,虽然写的博客不多,质量也参差不齐,但是,它却是成长的历程的点点滴滴的一个见证,见证了我在这条路上的寻寻觅觅,朝圣的心路历程,现在将ORACLE方面的博客整理.归纳分类,方便自己和大家查看.翻阅.  ORACLE数据类型 ORACLE基本数据类型总结 ORACLE VARCHAR2最大长度问题 ORACLE数据库汉字占几个字节问题 ORACLE NUMBER类型Scale为0引发的问题   PL/SQL语法学习   PLSQL 调试触发器 PL/SQL重

Oracle中如何彻底的清除会话

kill session 是DBA经常碰到的事情之一.如果kill 掉了不该kill 的session,则具有破坏性,因此尽可能的避免这样的错误发生.同时也应当注意, 如果kill 的session属于Oracle 后台进程,则容易导致数据库实例宕机. 通常情况下,并不需要从操作系统级别杀掉Oracle会话进程,但并非总是如此,下面的描述中给出了在Oracle级别杀掉会话以及操作系统级别杀掉进程. 一.获得需要kill session的信息(使用V$SESSION 和 GV$SESSION视图)

ORACLE快速彻底Kill掉的会话

在ORACLE数据库当中,有时候会使用ALTER SYSTEM KILL SESSION 'sid,serial#'杀掉一个会话进程,但是使用这个SQL语句杀掉会话后,数据库并不会立即释放掉相关的资源,有时候你会发现锁定的资源很长时间 也不会释放,即使会话状态为"KILLED",依然会阻塞其它会话. 下面根据Eygel的"Oracle中Kill session的研究",构造一个案例看看kill session到底做了什么.如下所示 会话1: SQL> conn

【会话】Oracle kill session系列

[会话]Oracle kill session系列   1.1  BLOG文档结构图 Oracle kill session相关问题 - 3 - 1.1 BLOG文档结构图 - 4 - 1.2 前言部分 - 5 - 1.2.1 导读和注意事项 - 5 - 1.2.2 相关参考文章链接 - 6 - 1.2.3 本文简介 - 7 - 1.3 相关知识点扫盲(摘自网络+个人总结) - 7 - 1.3.1 得到当前会话的几个SQL - 7 - 1.3.2 Session 状态说明 - 8 - 1.3.3

Oracle自动性能统计

Oracle自动性能统计   高效诊断性能问题,需要提供完整可用的统计信息,好比医生给病人看病的望闻问切,才能够正确的确诊,然后再开出相应的药方.Oracle数据库为系统.会话以及单独的sql语句生成多种类型的累积统计信息.本文主要描述Oracle性能统计涉及到的相关概念及统计对象,以更好的利用统计信息为性能调整奠定基础. 一.性能统计信息的几个术语 增量值(delta)   性能统计信息依赖于delta值的累计,即增量值.增量值反映了在某个特定时段某个特定事件的趋势,或者说波动的幅度.通过对比

Oracle 彻底 kill session

--*************************** -- Oracle 彻底 kill session --***************************       kill session 是DBA经常碰到的事情之一.如果kill 掉了不该kill 的session,则具有破坏性,因此尽可能的避免这样的错误发生.同时也应当注意, 如果kill 的session属于Oracle 后台进程,则容易导致数据库实例宕机.   通常情况下,并不需要从操作系统级别杀掉Oracle会话进程