出现上面问题之前,程序和数据库之间的读写都是正常的,重启服务之后,也能够暂时的解决问题,但是还是会隔断时间出现这种问题。
其实是因为web程序使用数据库连接池对数据库的连接进行了复用,每次程序发出的读写请求,都会在数据库连接池中选择一个连接,这个连接是数据库连接池默认的固定的连接之一,当完成读写之后,会将该连接放回到连接池中去,而不是释放!!!所以当在经过28800秒(8小时)之后的一次新的读写请求恰巧选择到了这个连接去和数据库进行交互时,就发生了这种CommunicationsException异常,其实此时选择到的这条连接已经是一条脏连接了!!!
那么可能有人会问为什么是8小时,而不是5小时6小时呢?
因为这个时间是由mysql数据库控制的,如下图,其中interactive_timeout和wait_timeout,代表的就是控制mysql连接交互式和非交互式的最大存活时间,默认值为28800秒,最小值为1秒
网上有人说是要调大这个属性值,这种办法并不可靠!还是有几率会出现这种问题,鉴于这种情况,其实我们所使用的连接池已经帮助我们考虑到了这种情况的发生。
<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 | 表示当连接返回时,发送测试语句 |
数据库连接池通过配置的这些参数进行检查,如果确定为脏连接时就会放弃这条连接
<property name="poolPingEnabled" value="true"/>
<property name="poolPingQuery" value="select * from user"/>
属性 | 解释 |
---|---|
poolPingQuery | 配合下面参数使用,表示特定时间发送测试语句 |
poolPingEnabled | 表示每次引用连接进行操作时,发送一条测试语句 |
其他的连接池应该都有特定的方法,请自行查阅