mysql连接池8小时失效问题

发布时间:2023年12月28日

一、现象

Cause: com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 29,437 milliseconds ago. The last packet sent successfully to the server was 29,438 milliseconds ago. is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem.

二、原因分析

出现上面问题之前,程序和数据库之间的读写都是正常的,重启服务之后,也能够暂时的解决问题,但是还是会隔断时间出现这种问题。

三、总结

其实是因为web程序使用数据库连接池对数据库的连接进行了复用,每次程序发出的读写请求,都会在数据库连接池中选择一个连接,这个连接是数据库连接池默认的固定的连接之一,当完成读写之后,会将该连接放回到连接池中去,而不是释放!!!所以当在经过28800秒(8小时)之后的一次新的读写请求恰巧选择到了这个连接去和数据库进行交互时,就发生了这种CommunicationsException异常,其实此时选择到的这条连接已经是一条脏连接了!!!

那么可能有人会问为什么是8小时,而不是5小时6小时呢?

因为这个时间是由mysql数据库控制的,如下图,其中interactive_timeout和wait_timeout,代表的就是控制mysql连接交互式和非交互式的最大存活时间,默认值为28800秒,最小值为1秒
请添加图片描述

三、解决办法

网上有人说是要调大这个属性值,这种办法并不可靠!还是有几率会出现这种问题,鉴于这种情况,其实我们所使用的连接池已经帮助我们考虑到了这种情况的发生。

  1. 举例:使用阿里巴巴的Druid连接池处理办法:
    在引用德鲁伊连接池的位置加入下面参数,以xml举例:
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
属性解释
validationQuery配合下面三个参数使用,表示特定时间发送测试语句
testWhileIdle表示当连接空闲时,发送测试语句
testOnBorrow表示当连接引用时,发送测试语句
testOnReturn表示当连接返回时,发送测试语句

数据库连接池通过配置的这些参数进行检查,如果确定为脏连接时就会放弃这条连接

  1. 举例:使用JDBC连接池处理办法:
<property name="poolPingEnabled" value="true"/>
<property name="poolPingQuery" value="select * from user"/>
属性解释
poolPingQuery配合下面参数使用,表示特定时间发送测试语句
poolPingEnabled表示每次引用连接进行操作时,发送一条测试语句

其他的连接池应该都有特定的方法,请自行查阅

文章来源:https://blog.csdn.net/weixin_45404884/article/details/135226033
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。