### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException

1.问题描述

### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 170,369 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.
2.问题分析
每个数据库连接都会占用一定的数据库服务器内存资源,如果存在大量已完成数据库操作但仍未断开的连接,将会导致数据库服务器内存资源的极大浪费。
在mysql的界面工具Navicat中,点击F6键,输入show variables like "%timeout%";


interactive_timeout:服务器关闭交互式连接前,等待下一次执行数据库操作的秒数。
wait_timeout:服务器关闭非交互式连接前,等待下一次执行数据库操作的秒数。


在应用程序中配置的连接池中部分参数说明:
timeBetweenEvictionRunsMillis:间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:ms
minEvictableIdleTimeMillis:一个连接在连接池中最小生存的时间,单位:ms
validationQuery:用来验证数据库连接是否正常的一个sql语句,如“ select 1 ”
testOnBorrow :从连接池取连接时,验证是否有效,默认为 true 
testOnReturn:连接放回到连接池的时,验证是否有效,默认值为 flase
testWhileIdle:验证空闲连接是否有效, 默认值为 false


如果minEvictableIdleTimeMillis设置的为300000(300秒),而其连接的mysql数据库中interactive_timeout和wait_timeout的值若大于300秒,则一般不会出现问题。但是,如果interactive_timeout和wait_timeout的值若小于300秒,则可能就会出现本文中说的问题。
原因:比如说在连接创建后第270秒时,连接池中的这个连接还在最小生存时间范围之内。而数据库中interactive_timeout和wait_timeout的值比如说为150秒,即在连接建立并完成上一次数据库操作后第150秒后,仍没有下一次数据库操作,就认为这个连接超时,mysql就将这个连接关闭了。而在数据库连接池中的这个连接虽然已经被mysql认为无效并关闭了,但是该连接由于还在最小生存时间范围之内,在连接池中仍然认为这个连接是有效的,并在此时应用程序使用这个连接尝试进行mysql数据库操作,那么就会出现本文中的问题。
3.解决方案
a.MySQL4及其以下版本

在url后面添加autoReconnect=true来完成连接自动恢复
jdbc:mysql://localhost:3306/abc?autoReconnect=true   
b.MySQL5及以后版本

同时设置interactive_timeout和wait_timeout的值,使其为大于minEvictableIdleTimeMillis的一个适当值。这个interactive_timeout和wait_timeout的值也不能设置过大,否则可能会出现数据库连接占用大量数据库服务器内存的问题。


如上图,在不必重启MySQL的情况下,可以在sql命令行中设置并生效。但是MySQL重启后,这些设置将失效并恢复为默认值

也可以修改对应的配置文件windows 中myini、linux 中my.cnf。在[mysqld]下添加两行并重启服务。

interactive_timeout=值     

wait_timeout=值 

 重启MySQL服务

service mysqld stop     

service mysqld start

或者 

service mysqld restart



你可能感兴趣的:(数据库)