线上项目偶尔出现错误,这个错误发现是在项目无人操作一段时间后就产生,如果有人操作,那就不会出现。
具体报错信息
***.mysql.jdbc.exceptions.jdbc4.***municationsException: The last packet su***essfully received from the server was 385,290,819 milliseconds ago. The last packet sent su***essfully to the server was 385,290,820 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.
中文意思大概是:
从服务器成功接收到的最后一个数据包是385290819毫秒前。最后一个成功发送到服务器的数据包是385290820毫秒前。比服务器配置的值“wait_timeout”长。在应用程序中使用之前,应考虑过期和/或测试连接有效性,增加服务器配置的客户端超时值,或使用连接器/J连接属性“autoReconnect=true”来避免此问题。
错误原因:
MySQL数据库一般默认的连接等待时间为28800s(即8小时),超过8h,数据库会断开这个连接,但是应用不知道这个连接已经被数据库断开,所以链接池认为该连接是有效的,在下次请求时,连接池会把自己认为有效,但是数据库认为无效的连接分配出去,便会导致如上错误;
查询了mysql数据库的wait_timeout
SHOW GLOBAL VARIABLES LIKE ‘%wait_timeout%’;
发现确实是8小时
注:这里有两个超时需要注意:
interactive_timeout:指的是mysql在关闭一个交互的连接之前所要等待的秒数,
wait_timeout:指的是mysql在关闭一个非交互的连接之前所要等待的秒数
通过mysql客户端连接数据库是交互式连接,通过jdbc连接数据库是非交互式连接
所以我们要关注wait_timeout这个参数的值
再去看项目的配置文件,发现没有一项跟连接超时有关
解决办法
1.C3P0连接池
加上idleConnectionTestPeriod:用来配置测试空闲连接的间隔时间,如果发现超时,会自动去掉。默认0,不进行测试,单位s(秒)
更新后的配置文件,idleConnectionTestPeriod只要设置比数据库28800秒(8小时)小就可以,我这边设置的是3600秒即一小时进行检测。