具体报错信息:Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
The last packet successfully received from the server was 52,075,567 milliseconds ago.
The last packet sent successfully to the server was 52,075,568 milliseconds ago.
is longer than the server configured value of ‘wait_timeout’.
You should consider either expiring and/or testing connection validity before use in your application,
increasing the server configured values for client timeouts,
or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem.
原因分析:
MySQL连接时,服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。connections如果空闲超过8小时,Mysql将其断开,而DBCP连接池并不知道该connection已经失效,如果这时有Client请求connection,DBCP将该失效的Connection提供给Client,将会造成异常。
1,首先进入mysql,查看 wait_timeout、interactive_timeout这个值是否为默认的8小时(即 28800)
[root@server110 ~]# mysql -u root -p
Enter password:
输密码进入
执行如下命令
show variables like ‘%timeout%’;
其中wait_timeout就是负责超时控制的变量,其时间为长度为28800s,就是8个小时,那么就是说MySQL的服务会在操作间隔8小时后断开,需要再次重连。也有用户在URL中使用jdbc.url=jdbc:mysql://localhost:3306/nd?autoReconnect=true来使得连接自动恢复,当然了,这是可以的,不过是MySQL4及其以下版本适用。MySQL5中已经无效了
解决方式一:修改msyql 配置 ,不推荐
解决方式二:保证应用在MySQL的’wait_timeout’时间内,至少访问一次数据库,配置文件增加心跳检测部分
sys.db.initialSize=10
sys.db.maxIdle=50
sys.db.minIdle=5
sys.db.maxActive=50
sys.db.logAbandoned=true
sys.db.removeAbandoned=true
sys.db.removeAbandonedTimeout=120
sys.db.maxWait=60000
sys.db.type=mysql
dialect=MYSQL
sys.db.class=com.mysql.jdbc.Driver
sys.db.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
sys.db.username=root
sys.db.password=123456
<!-- 数据源定义 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${sys.db.class}"/>
<property name="url" value="${sys.db.url}"/>
<property name="username" value="${sys.db.username}"/>
<property name="password" value="${sys.db.password}"/>
<property name="initialSize" value="${sys.db.initialSize}"/><!-- 初始化连接 -->
<property name="maxIdle" value="${sys.db.maxIdle}"/><!-- 最大空闲连接 -->
<property name="minIdle" value="${sys.db.minIdle}"/><!-- 最小空闲连接 -->
<property name="maxActive" value="${sys.db.maxActive}"/><!-- 最大连接数量 -->
<property name="logAbandoned" value="${sys.db.logAbandoned}"/><!-- 是否在自动回收超时连接的时候打印连接的超时错误 -->
<property name="removeAbandoned" value="${sys.db.removeAbandoned}"/><!-- 是否自动回收超时连接 -->
<property name="removeAbandonedTimeout" value="${sys.db.removeAbandonedTimeout}"/><!-- 超时时间(以秒数为单位) -->
<property name="maxWait" value="${sys.db.maxWait}"/><!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
<!-- sql 心跳检测 -->
<property name= "testWhileIdle" ><value>true</value></property><!-- 起了一个 异步Evict的TimerTask定时线程进行控制 定时对线程池中的链接进行validateObject校验,对无效的链接进行关闭后,会调用ensureMinIdle,适当建立链接保证最小的minIdle连接数 -->
<property name= "testOnBorrow" ><value>false</value></property><!-- 在进行borrowObject进行处理时,对拿到的connection进行validateObject校验 -->
<property name= "testOnReturn" ><value>false</value></property><!-- 进行returnObject对返回的connection进行validateObject校验 -->
<property name= "validationQuery" ><value>select 1</value></property><!-- 代表检查的sql -->
<property name= "validationQueryTimeout" ><value>1</value></property><!-- 代表在执行检查时,通过statement设置,statement.setQueryTimeout(validationQueryTimeout) -->
<property name= "timeBetweenEvictionRunsMillis" ><value>28700</value></property><!-- 设置的Evict线程的时间,多久检查一次,建议小于mysql默认时间默认的8小时(即 28800秒),单位ms,大于0才会开启evict检查线程 -->
<property name= "numTestsPerEvictionRun" ><value>${sys.db.maxActive}</value></property><!-- 代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接. -->
<property name= "minEvictableIdleTimeMillis"><value>18000000</value></property><!-- -->
</bean>