语言
<< 返回文章列表

【从根源出发,化风险为可控】应用到数据库的连接数管控

2017年12月22日
巩飞
2082

简介

作为dba,大家的核心工作就是保障数据库的安全稳定高效运行,但是很多时候挑战并不是来自于我们能够把握的范畴之内,风险可能来自于数据库外部,比如今天要和大家交流的数据库连接数量管控。先来看个case。

 

案例分享

一个周末的早上,接到某运营商客户消息,某数据库出现问题,已经影响到了业务,请尽快排查。立即上线,vpn 远程检查,几分钟很快定位出故障原因,并建议了临时解决方案,先消除影响,同时建议客户与应用厂商协作,从根源上消除问题。虽然故障原因很简单,但是从这次小故障,反映出一个非常重要但是很多人并没有认真考虑过的问题,这里和大家交流探讨下,欢迎大家分享自己的心得和经验。

 

首先补充下环境情况,10g的两节点集群:

image.png

   

接到消息时只是说数据库有问题,影响业务,具体什么问题需要排查,所以快速检查(仅以节点1为例,其它节点不再赘述),先看看数据库后台进程是否存在:


 image.png

从os看后台进程正常,进入数据库中看看:

image.png

 

实例的状态也正常,会不会是因某个sql引发拥堵造成问题(这个在运营商这种高负荷高压力且持续优化已经较少存在硬伤的环境里是比较常见的问题来源),继续检查:

 image.png

结果如下:

image.png


可以看到,除了一些后台job,并没有拥堵的sql和会话。好吧,那就赶紧去看看alert日志,在日志中发现如下错误: 

image.png

 

很明显啊,报错是因为系统资源不够,当前没有消耗资源的大sql,为啥会资源不够,先去topas观察下资源使用情况:

image.png

 

一看吓一跳,物理内存耗尽,并且swap使用了30%多,同时从数据库里和os中检查连接资源消耗情况:

image.png


检查参数设置

image.png

 

可以看到两个节点均连了2000来个连接,没有达到数据库的限制,但是达到了os对oracle用户的资源限制。同时库里绝大多数连接资源都是被CTSW用户消耗了,合理吗?


跟客户沟通排查后确认,这个用户是掌上营业厅模块的用户,不应该有这么多连接,因为其它原因中间件连接池暴涨,最终导致问题出现。现在问题根源真相大白,先紧急配合客户创建了个profile,对这个用户的连接数进行了限制(最多1000),杀掉多余的非活动会话。同时建议客户与应用厂商协作,从根源上消除问题。

image.png

问题虽然解决了,但是开篇提到的问题才是我们想进行探讨的核心,即从应用到数据库的连接数该如何设计,运维实践中如何管控?


这一条线上需要考虑的环节不少,应用对连接数的需求->应用服务器os配置->连接池配置->数据库服务器os配置->oracle参数配置->oracle资源管理配置->持续的数据库连接数变化监控报警,加之很多数据库是被多个应用或者多个模块共用,又导致了这个问题的复杂化。

 

我个人的看法是:

  1. 在系统建设初期,就应该进行系统负荷定量分析,全方面的分析系统各个方面的负荷,并针对性的设计解决方案,在其中包含对数据库连接数管控的考虑。

  2. 在系统运维期,每一个数据库用户的增加,均和应用等沟通清楚对连接数等资源需求,再结合硬件状况/配置现状等,制定调整方案,比较全面的将从应用到数据库整条线上所有环节设置配套修改。

  3. 在系统运维期,应该建立一种手段或者机制,能够持续的管控数据库连接数变化趋势,并能进行相应的统计汇总分析,必要时报警。

 

第1、2条建议里,需要大家结合自己单位部门岗位分工,因地制宜的推动落实,第3条属于比较纯粹的技术性功能,可以稍作展开。

 

数据库连接数限制,可以通过上面讲的profile实现,那么监控呢?不外乎自己动手开发或者利用第三方软件。

  • 自己开发,无论是java类的开发语言,还是存储过程开发,思路均是,一份job周期性的对v$session视图进行抽取,将信息适当处理后另外存储起来,一份job周期性的对另外存储的信息进行统计/分析,根据结果与报警要求比对,针对隐患性的趋势调用报警接口报警。

  • 利用第三方软件,针对数据库的监控软件非常多,如oem、spotlight等等,基本都含有活动连接、总连接数的监控,但是含有连接数变化趋势以及连接数按应用服务器/用户等不同纬度下钻分析/预警/报警功能的却很少,目前我知道有zone、ignite、zabbix。其中zone具有完整的功能模块,可以直接使用,ignite和zabbix均有接口支持自定义监控项目,可以通过此二次开发实现。

 

思考:你的单位是如何解决和应对这个问题的呢?


经典问答分享

问题1:我这边有套库,几乎都是大量的短链接造成系统压力,我是不是也可以用profile文件进行限制, 最高每秒37个连接

profile只能限制用户当前连接的总数,如果连接断开就不算了。所以不行。但是针对你这种情况,每秒37个已经很高了,最佳的方法是协调进行应用改造,由短连接改为长连接。

如果是长连接,请记得用连接池,会对连接复用,以及有释放回收机制,同时有各种配置参数(比如初始连接数、上限连接数等等)来保障资源安全。


问题2:suse有没有类似查看资源的命令?

suse也有,而且很多,常规的iostat,vmstat,top等等,比较推荐的是nmon


问题3:dba_Profiles --这个视图的的limit值有的是default,有的unlimited,这个怎么控制?

dba_pfofiles里可以看到所有profile的详细配置,针对每个profile,又有很多个设置项目,这个字典里每一行就是某个profile的某个项目的配置信息,如果要改,可以用alert命令。


问题4:同一个sql 测试环境执行计划和生产不一样 可以把测试执行计划整生产不

如果你确定测试环境的执行计划是最佳的,当然可以将其搬到生产环境,比如用sql profile来做。但是,建议从根源分析为什么生产的计划还不如测试环境,是索引等基础结构有差异,还是统计信息等等造成,然后处理之。


问题5:你的解决方案里有个“杀掉非活动会话” 这个是设定一个crontab弄个脚本定时杀吧!不然废连接一会儿又上来了

不是crontab的定时脚本,因为,确定清楚问题后就已经先配置好profile,然后再杀,超过的就连不上来了。


问题6:能针对IP限制连接数吗?

profile没有这个现成的功能,但是可以自己实现,数据库级触发器+存储过程。


问题7:个人感觉这个案例应该追踪下当时的系统内存分布。2000个会话不算多

内存分布和使用看了,用awk脚本从os里看了,也从v$session的内存使用字段看了,信息一致,是各个会话比较均匀的正常消耗了。另外,就算swap用了30%,但是还有70%的空余,就算慢,也还是可以连的,不会连不上。根源不是内存不够用连接建立不了,是达到了ulimit限制。