mybatisplus版本引发的连接泄漏血案

上周几次接到同事电话说线上环境用户登陆失败,我一查线上日志看到很多Connection timeout的错,

因为我们用到了HikariCP连接池,理论上来说不会出现连接泄漏的问题,我就加了HikariCP的leakDetectionThreshold连接泄漏检测配置。

今晚又被提示说登陆不上了,我一看日志,果真如提前预料的那样也是Connection timeout的错,但是这次竟然日志中没有出现Apparent connection leak detected类似的字样,甚是奇怪。

其实在去年年底的时候已经出现过几次,当时我是定位到mybatisplus中ActiveRecord用法(比如updateById等操作)会导致Connection timeout,当时也没去深入源码看是什么问题就草草略过,只是叫同事不要用ActiveRecord的操作(可惜同事还是继续用的乐此不疲),后来又遇到多数据源下Spring事务不生效的问题,是因为不是用同一个dynamicDatasource的Bean导致的,之后也想当然认为ActiveRecord引发的Connection timout是这个问题引起的,当时系统也没多少用户访问,所以问题没暴露的频繁。

这次几回出现这个异常看来是另有隐情, 我想从根本上解决问题,首先就把日志级别调为debug模式,然后我结合着用户日志行为分析(这几次是每到傍晚6点过后就会出现问题),模拟用户界面操作,果然过一会连接数飙升,在HikariCP经过Cleanup后也没移除,既有连接一直处于active状态,说明连接是存在泄漏。接着我发现了为什么leakDetectionThreshold没生效?竟然是因为我没在代码里加上相应配置,只是在配置文件中加上而已(因为我们是用的自定义数据源,所以配置也需要在HikariCP的配置Bean中手动加上)。

果然过了我配置的60s检测时间过后就抛出了一条Apparent connection leak detected的异常,异常定位到我们使用ActiveRecord的updateById那边,这边我也同时想到了 在我们写的类似代码里调用ActiveRecord的时候是不会被Spring管理的,因为我们操作的Entity是自己new出来然后去selectById的,不是经过注入的Service去调用的。 接着我下意识点开updateById的定义,发现了重要线索,里面竟然在update过后没有调用closeSession,我也看了insert方法是有close操作的。所以到这里我想应该是mybatisplus本身的bug,然后我一看我们项目引用的版本竟然是RC版,我瞬间感觉崩溃(当时竟然没去考虑这个版本问题)。为了证明这一点,我去github上的mybatisplus版本release记录中去看,发现他们在3.0.4中才把这个bug修复,加上了finally close的操作,而我们用的只是3.0.1-RC版本。

最后我把pom中mybatisplus版本升到了3.0.4把这个坑给填上了。

参考资料:

  1. 聊聊hikari连接池的leakDetectionThreshold
  2. 去除全局缓存sqlSession,增加Model,通用service层sqlSession释放.修改测试用例异常范围
  3. 使用mybatis plus的activerecorde怎么开启事务呢

欢迎大家关注我的个人公众号:
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JNDI(Java命名和目录接口)数据源连接泄漏是指在使用JNDI数据源连接数据库时,在每次使用完连接后没有正确地关闭连接,导致连接不能被释放,从而占用了数据库的资源。这种情况可能会导致数据库服务器出现性能下降、资源耗尽等问题。 连接泄漏的原因主要有以下几点: 1. 程序没有正确地关闭数据库连接:在使用完连接后,应该显式地关闭连接,释放资源。而如果程序没有正确关闭连接,就会导致连接泄漏。 2. 程序没有处理异常情况:在操作数据库时,可能会出现异常情况,例如网络中断、数据库宕机等。如果程序没有正确地处理这些异常情况,就有可能导致连接没有被正确地关闭。 3. 程序没有使用连接池:连接池是管理数据库连接的一种机制,可以有效地避免连接泄漏。如果程序没有使用连接池,而是直接使用JNDI获取连接,就容易出现连接泄漏的情况。 解决连接泄漏问题的方法主要有以下几点: 1. 确保在使用完连接后及时关闭连接:在程序的逻辑中,应该保证在使用完连接后,无论是否出现异常,都要显式地关闭连接,释放资源。 2. 增加异常处理逻辑:要在程序中增加异常处理的逻辑,包括捕获异常、记录日志、释放资源等操作,确保连接在出现异常时也能被正确地关闭。 3. 使用连接池:使用连接池可以有效地管理连接,确保连接的合理分配和回收。通过配置合适的连接数和超时时间,可以避免连接泄漏的问题。 总之,在使用JNDI数据源连接数据库时,要注意合理管理连接,保证在使用完连接后及时关闭,避免连接泄漏问题的发生。另外,使用连接池也是一种有效的方式来管理连接,提高系统的性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值