The last packet successfully received from the server was 605,043 milliseconds ago. The last packet sent successfully to the server was 605,044 milliseconds ago.
解释:
Mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,
通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接。而应用连接池却认为该连接还是有效的(因为并未校验连接的有效性),当应用申请使用该连接时,就会导致上面的报错。
通过mysql > show variables like '%timeout%',看到超时时间是8小时
参数说明:
initialSize: 初始化连接个数
maxActive: 最大连接池数量
minIdle: 最小连接池数量
validationQuery: 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrow: false 申请连接时不执行validationQuery检测
testOnReturn: false 归还连接时不执行validationQuery检测
testWhileIdle: true 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测
:timeBetweenEvictionRunsMillis 有两个含义:
1.testWhileIdle的判断依据,详细看testWhileIdle属性的说明 对应以下第一种方式
2.Destroy线程会检测连接的间隔时间 对应以下第二种方式
minEvictableIdleTimeMillis: Destroy worker执行时判断连接空闲时间是否大于 minEvictableIdleTimeMillis, 如果大于判断线程池中空闲连接数是否大于minIdle, 如果大于回收此连接
maxEvictableIdleTimeMillis: Destroy worker执行时判断连接空闲时间是否大于 maxEvictableIdleTimeMillis, 如果大于回收此连接(忽略minIdle).
如何解决:testWhileIdle
testWhileIdle:如果为true(默认true),当应用向连接池申请连接,并且testOnBorrow为false时,连接池将会判断连接是否处于空闲状态,如果是,则验证这条连接是否可用。
testWhileIdle什么时候会起作用?
-
获取连接时;
-
testOnBorrow==false;
-
testWhileIdle==true;
使用代码在DruidDataSource的getConnectionDirect方法
注意:此时判断连接空闲的依据是空闲时间大于timeBetweenEvictionRunsMillis(默认1分钟),并不是使用minEvictableIdleTimeMillis跟maxEvictableIdleTimeMillis,也就是说如果连接空闲时间超过一分钟就测试一下连接的有效性,但并不是直接剔除;而如果空闲时间超过了minEvictableIdleTimeMillis则会直接剔除。
总结:
1: 通过配置testOnBorrow=true每次在连接取出时判断, 效率较差
2: 通过配置testWhileIdle=true每次在连接取出时且取出的连接空闲时间超过timeBetweenEvictionRunsMillis时判断,效率较高. 但要注意timeBetweenEvictionRunsMillis的时间一定不能超过8个小时(mysql 自动释放连接时间)
3: 通过配置 timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis定时任务扫空闲线程,超过minEvictableIdleTimeMillis空闲时间的被回收. 缺点:只能回收超出minIdle配置的连接. 另外如果minIdle和maxActive的话, 此方法无效, 相当于没有配置
4: 通过配置timeBetweenEvictionRunsMillis和maxEvictableIdleTimeMillis 作为第3种方案的后补方案,但注意timeBetweenEvictionRunsMillis+maxEvictableIdleTimeMillis一定不能>8小时