背景
公司一个项目使用了druid连接池,mysql数据库,生产环境日志偶尔会打印一个错误如下:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure。
查了下,错误挺常见,出现这个错误的原因:
1.网络错误,导致数据库无法连接。
2.数据库连接闲置时间太长,导致数据库关闭了连接,而连接池还持有这个连接的引用,所以导致使用这个连接的时候出现了异常。
针对第二个问题,具体分析一下。
在我们的程序中,对数据库发起创建连接的请求,连接由数据库创建,而我们持有的是连接的引用;当使用连接池时,连接池会初始化一批连接,但是当我们的程序空闲时间太长时,数据库会主动根据设置的超时时间(mysql默认连接超时时间为8小时)断开连接,但是这个操作连接池并不知道,所以这个时候就需要连接池有一个心跳机制去检测连接池中的连接是否有效,在druid中,可以通过设置testWhileIdle=true(默认为true)来开启。
ps:使用druid的时候推荐使用1.1.5版本及以上,因为1.1.5版本修复了一个重大的bug:testWhileIdle在某些情况下会失效。
在mysql中查看超时时间的命令为: show global variables like '%timeout%'
修改mysql超时时间语句为: set global wait_timeout=10000
解决办法:
1.改大mysql连接超时时间。
a、修改配置
如果在window中设置为21天,改mysql5的安装文件夹中的my.ini
如果在linux中/etc/my.cnf,添加一行:wait_timeout = 1814400,重启mysql,添加效果如下:
b、直接用sql命令行修改(重启有还原为28800,不推荐)
mysql> set global wait_timeout=1814400;
mysql> show global variables like 'wait_timeout';
2.如果使用了druid连接池,可以配置连接池的testOnBorrow=true,这样在每次从连接池中取出且准备使用之前先测试下当前使用是否能用,如果不能用,系统就会自动删除掉。 但是这样会大大的降低程序的性能。