mysql 数据库连接超过 8 小时失效的解决方案

时间:2022-01-17 06:19:36

使用mysql数据库遇到的问题,后台打印错误信息如下:

org.springframework.dao.RecoverableDataAccessException: PreparedStatementCallback; SQL [ SELECT  lessonNo,lessonStart,lessonEnd,answerCount,studentNumber,allCount,correctRate,averageTime  FROM  studycase_answer_class  WHERE  schoolId =? and classCode=?  and teaEmail=? ]; Communications link failure

The last packet successfully received from the server was 101,594 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 101,594 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:98)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)
at org.s

结合网上查找,原因就是: mysql默认会将 8 个小时内没有操作过的 数据库连接断开。

MySQL服务器所支持的最大连接数是有上限的,因为每个连接的建立都会消耗内存,因此我们希望客户端在连接到MySQL Server处理完相应的操作后,应该断开连接并释放占用的内存。如果你的MySQL Server有大量的闲置连接,他们不仅会白白消耗内存,而且如果连接一直在累加而不断开,最终肯定会达到MySQL Server的连接上限数,这会报'too many connections'的错误。所以mysql在一定时长后默认断开连接并且释放掉sleep的连接线程,已保证mysql server不会出现连接数过满的情况。mysql默认8小时数据库断开的设置参数如下:

1)interactive_timeout:
参数含义:服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。
参数默认值:28800秒(8小时)

(2)wait_timeout:
参数含义:服务器关闭非交互连接之前等待活动的秒数。
在线程启动时,根据全局wait_timeout值或全局interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义)。
参数默认值:28800秒(8小时)

ps:如果在配置文件my.cnf中只设置参数wait_timeout=100,则重启服务器后进入,执行:Mysql> show variables like “%timeout%”;会发现参数设置并未生效,仍然为28800(即默认的8个小时)。查询资料后,要同时设置interactive_timeout和wait_timeout才会生效。

复现此问题很容易:设置端口连接为60s即可,然后等待2分钟后在调同样的接口并会出现。

解决思路:

1.既然连接8小时会断开连接,可以设置更长一些比如24小时?

2.各大数据源(durid,c3p0)有没有解决方案呢?

第一种方案不推荐,第二种方案了解到数据源方面的设置优化是能解决此问题的。下面已c3p0举例:

<property name="idleConnectionTestPeriod" value="60" />
<property name="preferredTestQuery" value="SELECT 1"/>
<property name="testConnectionOnCheckout" value="true"/>
8小时失效的解决方案其实配置idleConnectionTestPeriod就可以解决,c3p0中的解释是:

用来配置测试空闲连接的间隔时间。测试方式还是上面的两种之一,可以用来解决MySQL8小时断开连接的问题。因为它
保证连接池会每隔一定时间对空闲连接进行一次测试,从而保证有效的空闲连接能每隔一定时间访问一次数据库,将于MySQL
8小时无会话的状态打破。为0则不测试。
而preferredTestQuery和testConnectionOnCheckOut主要是为了在每次getConnection的时候都会信息测试,查看连接是否有效。当然还有更多的c3p0调优的参数,具体参考:https://www.cnblogs.com/zmc/p/6188040.html