Oracle12c新增max_idle_time参数的学习与感触

发布时间 2023-12-20 22:38:18作者: 济南小老虎

Oracle12c新增max_idle_time参数的学习与感触


TLDR

其实任何软件出了新版本.readme 是很重要的. 
尤其是数据库, 涉及到底层问题的. 

比如这次遇到的Oracle的max_idle_time参数,以及前几天遇到的Mysql的新增的parallel关键字. 
自己之前的积累可能是一盏明灯, 也可能是一堵墙. 

需要不断的学习不断的更新自我,才能够快速的定位和发现问题. 
有时候时间很重要, 比别人快的解决问题才可能不被别人骗. 

背景

最近出现了一个非常奇怪的问题现象
一个环境早上上班时容易出现无法建立连接的提示.
同时数据库的v$session等信息又比较正常, 显示仅有几个连接. 
所以上线会议之前, 同事告诉我没有连接池的问题, 是连不上数据库导致的. 

基于这个判断, 我跟着项目组一起学习和判断问题可能得原因. 

排查过程

最开始以为是网络问题, 因为现场的网络的确存在偶发性异常的情况.
这是一个老问题, 结合背景里面手的没有连接池的问题, 所以很浅显就推断是网络问题导致. 

但是问题接二连三的出现, 客户又排除了网络变更, 就比较诡异了.
就开始询问问题出现的规律: 
发现有规律的在凌晨三点和下午两点多开始出现问题. 

当时没办法, 想到最笨的方式为: 
排查凌晨三点左右以及之前的nginx日志,排查nginx的日志有没有比较特殊的功能访问
但是考虑到如果是api调用直接的话可能就比较难分析了.

此时同时分析道有一个凌晨两点半和早上一点半的动作进行同步数据. 
所以才想是不是此处导致的. 

同事晚上使用测试环境进行复现, 发现的确会出现连接异常增多的情况. 
感觉问题基本上定位到了一半. 

结合下午客户找oracle专家查看数据库时, 发现有 oracle killed的日志.
当时提示的问题原因是 max_idle_time . 询问客户得知,客户因为资源限制,的确修改过数据库的默认值. 

然后猜测怀疑是此处修改 导致与其他异常情况不一致的情况出现. 

佐证

同事晚上就行进行验证:
1. 数据库开启参数 将 max_idle_time 设置成10分钟.
2. 模拟产生大量数据库连接的操作.
3. 开启应用的actuator 进行判断.
4. 打开数据库监控, 查看该应用服务器针对数据库的连接情况. 

结论为:
连接池很快增多,并且保持问题. 
十分钟之后, 应用和数据库的连接开始被kill, 这是max_idle_time的核心目标.
通过netstat 可以看到 CLOSEWAIT的连接开始增多. 
通过数据库的session信息可以看到, 该客户端的数据库连接迅速减少.

所有动作的同事发现actuator的hikari_connections 的参数没有发生变化. 保持在连接的高位. 

所以基本上可以在再现了这个问题. 

后续思考

1. 应用层必须减少建立数据库连接的次数和频率, 并且尽量使用连接池实现连接复用.
2. 应用最好实现批量处理,批量提交, 避免单次提交太多导致应用性能下降.
3. 需要进行连接的finally catch的处理. 避免SQL异常时不进行commit后者是rollback. 
4. 数据库有任何改动必须告知业务方人员, 数据库是很关键的. 任何修改都可能产生比较大的影响.
5. 数据库的内存, CPU, process,session都是资源,重要项目必须保证有充足的资源储备. 来扛过可能得洪峰.
   数据库需要实时进行优化, 不仅仅是CPU和内存等参数,还有句型表的处理. 应该将非核心表移除到其他位置, 避免影响核心业务. 
6. 网络层一定要稳定, 最好有完整的监控, 能够自证清白网络没有问题.  
7. 监控必须全面, 应用,网络, 数据库,必须都的有监控, 并且最好是一体化, 快速查询分析 ,不能偏听偏信. 
8. 对变动要有敏感,对过往的知识储备要有实时更新的思想准备. 遇到问题并不可怕, 能够解决问题才能进步. 

关于Oracle的参数

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

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 也表示没有限制。官方文档关于这个参数的介绍如下:
当会话持有其它会话所需的资源时,该会话被视为阻塞会话. 例如

该会话持有另一个会话所需的锁。
该会话是并行操作,并且其使用者组,PDB或数据库已达到其最大并行服务器限制或已排队的并行操作。
会话的PDB或数据库实例即将达到其SESSIONS或PROCESSES限制。
这个参数与MAX_IDLE_TIME参数的不同之处在于,MAX_IDLE_TIME适用于所有会话(阻塞和非阻塞),而MAX_IDLE_BLOCKING_TIME仅适用于阻塞会话。  
因此,为了使MAX_IDLE_BLOCKING_TIME有效,其限制必须小于MAX_IDLE_TIME限制。

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

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

参数的个人理解

之前与方神沟通时一直发现数据库里面有很多 inactive的会话.
长时间不回收, 导致process和session等数据量较高.

现在想oracle应该在面对了大量的类似问题后, 在oracle12c时决心来解决这个问题.
在资源比较差的环境上面, 的确能够大量减少idle的线程, 避免数据库出现宕机的情况. 
也的确能够增加数据库的稳定性. 

但是直接对连接进行kill不太优雅,尤其是很多应用在启用了连接池,并且设置了min pool
用来解决应用突发请求时,避免大量建立连接时间较长的问题时 
会出现相反的作用, 但是产品不停的进行kill和create 反而导致网络和数据库的压力变大.

结合当年IIS调优时 应用程序池 1740分钟的回收时间, 也就是 129个小时的时间的设置
应该是超过一天, 避免太短太频繁的回收影响业务,太长可能也会导致积压过多的无线资料
感觉超过一天的设置是比较合理和有必要的. 

工作中还是需要不断的学习和积累的,  多学习才有触类旁通的可能. 才有快速领悟的机会. 
希望自己能够一直学习和进步下去. 能够过上理想的生活.