排查数据库连接池错误

简介: 最近在使用druid数据源时,碰到一个问题closed connection。在本地及测试环境都运行正常,但是在正式环境,过一段时间就出现closed conneciton问题,关闭的连接。

一、closed connection

最近有个需求,单线程监控kafka数据的变化,再由简单的逻辑查询数据库,封装查询接口,使用open-feign调用接口。具体链路如下图所示:

因kafka的数据变化较快,需要频繁查询数据库,所以使用了druid的数据源。程序在测试环境执行没有任何问题,一旦在生产环境上执行就会出现closed connection错误,经过排查分析原因,发现oralce数据库超过一定的时间会把链接断开,当数据源再去使用连接时就会报closed connect错误。

详细分析配置文件中,发现其中几个配置有问题,详细分析以下几个配置

maxActive
最大连接池数量,允许的最大同时使用中的连接数。这里特地唠叨一下,配置 maxActive 千万不要好大喜多,虽然配置大了看起来业务流量飙升后还能处理更多的请求,但切换到 DB 视角会发现其实连接数的增多在很多场景下反而会减低吞吐量,一个非常典型的例子就秒杀,在更新热点数据时 DB 需要加锁操作,这个时候再让更多的连接操作 DB 就有点像假日往高速上涌入的车辆,只会给 DB 添堵。

keepAlive
参数表示是否对空闲连接保活,布尔类型。可能不少人认为 druid 连接池默认会维持DB连接的心跳,对池子中的连接进行保活,特别配置了 minIdle 这个参数后觉得,有了 minIdle 最少应该会保持这么多空闲连接。其实,keepAlive 这个参数是在 druid 1.0.28 后新增的,并且默认值是 false,即不进行连接保活。

那么需要保活连接,是不是将 keepAlive 配置成 true 就完事了呢?虽然 true 的确是开启了保活机制,但是应该保活多少个,心跳检查的规则是什么,这些都需要正确配置,否则还是可能事与愿违。这里需要了解几个相关的参数:minIdle 最小连接池数量,连接保活的数量,空闲连接超时踢除过程会保留的连接数(前提是当前连接数大于等于 minIdle),其实 keepAlive 也仅维护已存在的连接,而不会去新建连接,即使连接数小于 minIdle;minEvictableIdleTimeMillis 单位毫秒,连接保持空闲而不被驱逐的最小时间,保活心跳只对存活时间超过这个值的连接进行;maxEvictableIdleTimeMillis 单位毫秒,连接保持空闲的最长时间,如果连接执行过任何操作后计时器就会被重置(包括心跳保活动作);timeBetweenEvictionRunsMillis 单位毫秒,Destroy 线程检测连接的间隔时间,会在检测过程中触发心跳。保活检查的详细流程可参见源码com.alibaba.druid.pool.DruidDataSource.DestroyTask,其中心跳检查会根据配置使用 ping 或 validationQuery 配置的检查语句。

maxEvictableIdleTimeMillis 和 minEvictableIdleTimeMillis  

/**

DestroyTask 线程销毁任务每隔 timeBetweenEvictionRunsMillis

(默认一分钟)的时间会执行一次连接池瘦身检测

**/

if (idleMillis >= minEvictableIdleTimeMillis) {

   if (checkTime && i < checkCount) {  // checkCount = poolingCount - minIdle

       evictConnections[evictCount++] = connection;

       continue;

   } else if (idleMillis > maxEvictableIdleTimeMillis) {

       evictConnections[evictCount++] = connection;

       continue;

   }

}

checkTime = true 所以会再判断 i < checkCount 是否成立,而 checkCount = poolingCount - minIdle 也就是超过 minIdle 那部分连接(类似线程池的 maximumPoolSize - corePoolSize )

所以,代码逻辑是 1~minIdle 的连接空闲超过 maxEvictableIdleTimeMillis(默认7小时) 则需要清除掉, minEvictableIdleTimeMillis(默认30分钟) 针对的是超过 minIdle 的那部分连接

maxEvictableIdleTimeMillis 表示的是 minIdle 内连接能空闲的最大时长。

因为程序启动时间在中午11:30分左右,这就是为什么程序是在凌晨1:30分左右报错的原因,因配置文件没有配置maxEvictableIdleTimeMillis此参数,默认7个小时,druid要关闭超过最大空闲时间的连接,关闭连接连接时(oracle客户端已经把连接关闭),所以日志报错closed connection。

二、解决办法

1、因为程序是单线程,所以调整了minActive 和minIdle ,把参数值都调整为1,尽量不保留空闲连接,没有空闲连接,就不会关闭连接,就不会报错。

2、开启keep-alive参数设置为true,查看数据库配置的关闭空闲连接的时间,修改maxEvictableIdleTimeMillis的默认值(单位为ms),小于数据库配置的默认时间。select resource_name,resource_type,limit from dba_profiles where profile='DEFAULT' ;

相关文章
|
SQL 监控 Oracle
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
|
监控 Oracle 安全
Oracle数据库用户频繁被锁问题原因排查及解决
由于应用环境下Oracle用户总是频繁被锁,经常不能执行数据库事务操作,严重影响了系统运行效率。通过问题原因分析及排查,发现了原因,在此记录一下。
4573 0
Oracle数据库用户频繁被锁问题原因排查及解决
|
SQL 监控 Oracle
Oracle 数据库报错:ORA-12592问题排查过程
Oracle 数据库报错:ORA-12592问题排查过程
3994 0
|
3月前
|
SQL 关系型数据库 MySQL
遇到mysql数据库死锁,你会怎么排查?
遇到mysql数据库死锁,你会怎么排查?
244 0
|
19天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
44 0
|
5月前
|
运维 数据管理 数据库
数据管理DMS产品使用合集之遇到报错:数据库账号没有权限执行,该如何排查
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。
56 2
|
5月前
|
SQL 存储 监控
达梦数据库死锁排查与解决
达梦数据库死锁排查与解决
1464 0
|
SQL 监控 关系型数据库
一次数据库CPU飙高问题排查与解决
### 问题发现 最近,经常收到一些数据库的报警,提示我们的数据库的CPU有异常飙高的情况,通过该监控发现,确实间歇性的有一些CPU飙高的情况,经常把CPU打满了。 ![](https://ata2-img.oss-cn-zhangjiakou.aliyuncs.com/neweditor/a1786489-1f44-4c39-bea4-85ca25a45433.png) ### 问题排
686 0
一次数据库CPU飙高问题排查与解决
|
SQL 监控 关系型数据库
线上数据库挂了,你该如何排查?如何防备?
大家好,我是Leo,目前在常州从事Java后端工程师。上篇文章我们介绍了读写分离那些问题,主要从概念,目的,单到多的演变,安全性演变以及六个解决方案为叙述。今天我们聊聊一主多从,如果挂了你会如何快速定位。
线上数据库挂了,你该如何排查?如何防备?
|
SQL 搜索推荐 关系型数据库
php| 一次上线后数据库代理服务报错的排查
选择 `言简意赅` 作为技术 blog 的写作风格, 放弃使用 `故事型` 风格, 这样: - 行文不会太长, 写起来容易, 读起来也轻松. - 围绕技术展开, 不会离题太远
332 0