在Oracle中,如何定时清理INACTIVE状态的会话(配置会话的空闲时间)

0    163    4

Tags:

👉 本文共约2755个字,系统预计阅读时间或需11分钟。

简介

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 >= 60602实现,当然最好写成 S.LAST_CALL_ET >= 7200

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

一般情况下,少量的INACTVIE会话对数据库并没有什么影响,但是,如果由于程序设计等某些原因导致数据库出现大量的会话长时间处于INACTIVE状态,那么将会导致大量的系统资源被消耗,造成会话数超过系统SESSION的最大值,出现ORA-00018:maximum number of sessions exceeded错误。此时就需要清理那些长时间处于INACTIVE状态的会话。人为定期检查、杀掉这类会话肯定不太现实,要定期清理那些长时间处于INACTIVE的会话,可以使用如下几种办法:

Oracle 12之下版本

方法1

设置用户profile的IDLE_TIME参数,需要设置resource_limit为true,然后再设置IDLE_TIME参数,单位为分钟:

该方法需要在sqlnet.ora文件里加上sqlnet.expire_time=5,单位为分钟数。

查询:

方法2

直接KILL掉INACTIVE的会话。V$SESSION视图中的LAST_CALL_ET字段表示用户最后一条语句执行完毕后到sysdate的时间,单位为秒。每次用户执行一个新的语句后,该字段复位为0,重新开始记数。可以通过该字段来获得一个连接用户最后一次操作数据库后的空闲时间。推荐使用这种方法来释放INACTIVE状态的会话。具体代码如下所示:

12.2新参数MAX_IDLE_TIME和MAX_IDLE_BLOCKER_TIME

Oracle 12.2 引入了新参数MAX_IDLE_TIME。它可以指定会话空闲的最大分钟数。如果会话空闲的时间超过了这个阈值的话,这个会话将会被自动终止。其实在Oracle 10g& 11g时代,我还写过脚本定期清理INACTIVE会话,当时写的文章名为ORACLE定期清理INACTIVE会话”。从Oracle 12.2开始,就完全没有必要这样做了,设置一个简单的参数即可解决这个问题,见微知著,一叶知秋。以后数据库运维的趋势确实是越来越简单化,自动化。

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

MAX_IDLE_TIME这个参数的时间单位是分钟,注意不是秒。可以在PDB级别或CDB级别修改。但是不能在会话级别修改(ALTER SESSION),另外,对于RAC实例,不同节点的值可以设置成不一样。如果参数MAX_IDLE_TIME的值为0,表示不限制会话的空闲时间。当会话的空闲时间超过阈值时,会话被终止后,你会在客户端收到ORA-03113错误。注意,有时候我们也会通过RESOURCE_LIMIT限制会话最大的空闲时间,通过在PROFILE里面设置IDLE_TIME的值来实现,如果是通过这种方式来终止会话的话,收到的错误为“ORA-02396: exceeded maximum idle time, please connect again”。注意两者的区别。

另外,我们来看另外一个参数MAX_IDLE_BLOCKER_TIME ,这个参数最开始宣称是ORACLE 21c引入的新特性,但是实际上ORACLE 19c已经有这个参数了。它定义了阻塞会话的最大会话空闲时间,以分钟为单位。默认值 0 也表示没有限制。官方文档[2]关于这个参数的介绍如下:

当会话持有其它会话所需的资源时,该会话被视为阻塞会话. 例如

  1. 该会话持有另一个会话所需的锁。
  2. 该会话是并行操作,并且其使用者组,PDB或数据库已达到其最大并行服务器限制或已排队的并行操作。
  3. 会话的PDB或数据库实例即将达到其SESSIONS或PROCESSES限制。

这个参数与MAX_IDLE_TIME参数的不同之处在于,MAX_IDLE_TIME适用于所有会话(阻塞和非阻塞),而MAX_IDLE_BLOCKING_TIME仅适用于阻塞会话。 因此,为了使MAX_IDLE_BLOCKING_TIME有效,其限制必须小于MAX_IDLE_TIME限制。

注意事项:

此参数对并行查询进程和 SYS 用户会话都没有影响。所以你不要用sys用户去测试,否则你会发现它不生效。

This parameter does not have an effect on parallel query processes, nor on SYS user sessions.

此参数从Oracle 19c开始就已经提供了。不是从Oracle 21c开始。

This parameter is available starting with Oracle Database 19c.

有了这个参数,你又不用写脚本去kill阻塞会话了。你看,新增的一个功能/特性就能节省你很多工作量。但是这个功能也还有一些不足的地方:DBA不清楚Kill了哪些会话,阻塞会话最后执行过什么SQL也无从得知,如果是自己写的脚本,往往可以记录这些信息,方便事后我们回溯、分析问题。如果Oracle在终止会话的同时,将这些信息写入trace文件或数据字典,那就相当完美了。

如何查询超过10小时无响应的会话?

GV$SESSION视图的LAST_CALL_ET字段表示客户端无相应的时间,可以根据该字段来查询,具体SQL语句如下所示:

在Oracle中,如何定时清理INACTIVE状态的会话(配置会话的空闲时间)

参考

https://mp.weixin.qq.com/s/4EI3UhFJMmJbOPWFLf-hnA

https://www.cnblogs.com/kerrycode/p/3636992.html

https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/MAX_IDLE_BLOCKER_TIME.html#GUID-DF3D3C12-1ED1-4146-B76C-2EF0F92C8211

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部