ERROR [com.alibaba.druid.pool.DruidDataSource] – abandon connection

摘要

#项目结构#
MyBatis+TDDL

问题

https://github.com/FS1360472174/javaweb/issues/58

ERROR [com.alibaba.druid.pool.DruidDataSource] – abandon connection, owner thread: qtp1267032364
-14, connected at : 1515409987672, open stackTrace
at java.lang.Thread.getStackTrace(Thread.java:1556)
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1068)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:994)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:984)
at com.taobao.tddl.atom.jdbc.TDataSourceWrapper.getConnectionByTargetDataSource(TDataSourceWrapper.java:322)
at com.taobao.tddl.atom.jdbc.TDataSourceWrapper.getConnection0(TDataSourceWrapper.java:284)
at com.taobao.tddl.atom.jdbc.TDataSourceWrapper.getConnection(TDataSourceWrapper.java:255)
at com.taobao.tddl.atom.jdbc.TDataSourceWrapper.getConnection(TDataSourceWrapper.java:222)
at com.taobao.tddl.atom.AbstractTAtomDataSource.getConnection(AbstractTAtomDataSource.java:27)
at com.taobao.tddl.group.jdbc.DataSourceWrapper.getConnection(DataSourceWrapper.java:120)
at com.taobao.tddl.group.jdbc.TGroupConnection.createNewConnection(TGroupConnection.java:191)
at com.taobao.tddl.group.jdbc.TGroupConnection$1.tryOnDataSource(TGroupConnection.java:453)
at com.taobao.tddl.group.jdbc.TGroupConnection$1.tryOnDataSource(TGroupConnection.java:443)
at com.taobao.tddl.group.dbselector.AbstractDBSelector.tryOnDataSourceHolderWithIndex(AbstractDBSelector.java:19

at com.taobao.tddl.group.dbselector.AbstractDBSelector.tryExecute(AbstractDBSelector.java:315)
at com.taobao.tddl.group.jdbc.TGroupConnection.prepareCall(TGroupConnection.java:492)
at com.taobao.tddl.group.jdbc.TGroupConnection.prepareCall(TGroupConnection.java:520)
at com.taobao.tddl.group.jdbc.TGroupConnection.prepareCall(TGroupConnection.java:74)
at com.taobao.tddl.matrix.jdbc.TConnection.prepareCall(TConnection.java:515)
at com.taobao.tddl.matrix.jdbc.TConnection.prepareCall(TConnection.java:483)
14980,1-8 99%
at com.taobao.tddl.group.jdbc.TGroupConnection.prepareCall(TGroupConnection.java:74)
at com.taobao.tddl.matrix.jdbc.TConnection.prepareCall(TConnection.java:515)
at com.taobao.tddl.matrix.jdbc.TConnection.prepareCall(TConnection.java:483)

在线上排查其他问题时,看到日志中有这个ERROR,而且很频繁。
根据abandon connection,得知这是一个数据库连接池问题,废弃的连接处理。

解决步骤

  • 首先搜了下druid 官 FAQ
    https://github.com/alibaba/druid/wiki/常见问题
    发现是druid有对连接泄露进行监控处理

    https://github.com/alibaba/druid/wiki/连接泄漏监测
    https://github.com/alibaba/druid/issues/872
    我这边没有配对监控,直接是从日志中看到的,有相应的线程栈信息,可以方便排查。

  • 这个连接泄露不会导致OOM,因为druid会去主动detroy这些未关闭的连接,也就是上面日志中的错误信息

  • 现在知道是有数据库连接未关闭,但是代码中并没有去管理数据库连接池,都是交给了Spring去管理的呢,而且不是每个数据库操作都会有问题,而是特定的数据库操作有问题

  • 开启debug日志

这里接可以看出阿里的开源软件距离工业级还有距离,Spring的可以清楚的看到连接释放与返回,而Druid并没有

  • 因为这个是和特定的SQL有关系,所有看下具体的这个SQL操作

    这个是之前人留下的,这种写法目前在项目组不是很常见了,没有实现代码与SQL语句分离,不是很提倡。
    这边的StatementType为Callable,看起来比奇怪,一般CallableStatement由于数据库存储过程的操作,显然这个语句不是这么调用存储过程。不知道前任为什么这么写,所以首先干掉了这个StatementType.CALLABLE参数。

  • 结果果然出错了,调用的时候 错,一个好笑的错误,没有使用auto generate id,却调用了。

    这个应该是MySQL 5.7 driver的一个bug,前任为了避免这个问题,使用CallableStatement绕过去了

  • 所以先改成xml方式验证下,xml默认是PreparedStatement,然后看下是否还能发生错误

发现没有了,所以问题的原因就是CallableStatement造成的

#探索-druid连接管理#
虽然问题解决了,但是还是不知道druid是如何管理连接的,所以需要深入一点

  • mybatis
    首先项目中用到了Mybatis,Mybatis + jdbc的操作流程如下
    一个数据库操作取连接是在具体的sql执行时才去取的

    可以看到修正的sql操作是有关闭的,但是CallableStatement没有,所以有未关闭的连接

    ERROR [com.alibaba.druid.pool.DruidDataSource] - abandon connection

    #参考#
    http://blog.csdn.net/luanlouis/article/details/40422941

    http://blog.csdn.net/luanlouis/article/details/37671851

    https://www.jianshu.com/p/ec40a82cae28

    http://blog.csdn.net/u013476542/article/details/53256610

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2018年1月24日
下一篇 2018年1月24日

相关推荐