Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection
。
可以用show global variables LIKE'wait_timeout';查看mysql的等待时间。
这就是问题的所在,在连接池中的connections如果空闲超过8小时,Mysql将其断开,而C3P0并不知道该connection已经失效,如果这时有Client请求connection,连接池将该失效的Connection提供给Client,将会造成上面的异常。
-
增加 wait_timeout 的时间。
-
减少 Connection pools 中 connection 的 lifetime。
-
测试 Connection pools 中 connection 的有效性。
最好的办法是同时综合使用上述3种方法,下面就 DBCP、C3P0 和 simple jdbc dataSource 分别做一说明,假设 wait_timeout 为默认的8小时
配置Mysql的wait_timeout
对于 MySQL5 之前的版本,如 Mysql4.x,只需要修改连接池配置中的 URL,添加一个参数:
autoReconnect=true
(如jdbc:mysql://hostaddress:3306/schemaname?autoReconnect=true),如果是 MySQL5 及以后的版本,则需要修改
my.cnf
(或者
my.ini
) 文件,在
[mysqld]
后面添加上:
wait_timeout = 28800
interactive-timeout = 28800
#验证使用的SQL语句
validationQuery SELECT 1
#池中的连接空闲30(1800000ms)分钟后被回收
minEvictableIdleTimeMillis 1800000
#每30(30000ms)秒运行一次空闲连接回收器
timeBetweenEvictionRunsMillis 30000
#借出连接时不要测试,否则很影响性能
testOnBorrow false
testWhileIdle true
#程序中的连接不使用后是否被连接池回收
#DBCP 2.0.1 (该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)
#removeAbandoned=true
removeAbandonedOnMaintenance=true
removeAbandonedOnBorrow=true
#数据库连接过多长时间不用将被视为被遗弃而收回连接池中(单位秒)。(为配合测试程序默认为30秒,一定要小于maxWait)
removeAbandonedTimeout=30
//获取connnection时测试是否有效
testConnectionOnCheckin = true
//自动测试的table名称
automaticTestTable=C3P0TestTable
//set to something much less than wait_timeout, prevents connections from going stale
idleConnectionTestPeriod = 18000
//set to something slightly less than wait_timeout, preventing 'stale' connections from being handed out
maxIdleTime = 25000
//if you can take the performance 'hit', set to "true"
testConnectionOnCheckout = true
simple jdbc dataSource
Pool.PingQuery = select 1
Pool.PingEnabled = true
Pool.PingConnectionsOlderThan = 0
//对于空闲的连接一个小时检查一次
Pool.PingConnectionsNotUsedFor = 3600000
Mysql异常:MySQLNonTransientConnectionException: No operations allowed after statement closed
MySQLNonTransientConnectionException: No operations allowed after statement closed 之所以会出现这个异常,是因为MySQL在5以后针对超长时间DB连接做了一个处理,那就是如果一个DB连接在无任何操作情况下过了8个小时后,Mysql会自动把这个连接关闭。所以使用连接池的时候虽然连接对象还在但是链接数据