记录解决wait_time连接超时问题

com.mysql.jdbc.CommunicationsException: The last packet successfully received from the server was14400 seconds ago.The last packet sent successfully to the server was 14400seconds ago, which 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_time与interactive_timeout)wait_time(mysql服务关闭非交互式连接等待的时间秒数)interactive_timeout(服务器关闭交互式连接等待的时间秒数)MySQL连接时,服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。connections如果空闲超过8小时,Mysql将其断开,而DBCP连接池并不知道该connection已经失效,如果这时有Client请求connection,DBCP将该失效的Connection提供给Client,将会造成异常。

什么是 交互式连接与非交互式连接呢?、

1、交互式连接顾名思义就是直接沟通,就像你在cmd或者xshell打开命令窗口连接mysql进行增删改查的界面,这个连接就是交互式,直接通过tcp连接。

2、非交互式就是通过中间媒介,比如hibernate或者jdbc与mysql服务建立连接,这就叫做非交互式连接。

 那么这个等待时间是多少呢?

通过命令查询:show variables like '%timeout%';  

mysql> show variables like '%timeout%';
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| connect_timeout             | 10       |
| delayed_insert_timeout      | 300      |
| have_statement_timeout      | YES      |
| innodb_flush_log_at_timeout | 1        |
| innodb_lock_wait_timeout    | 50       |
| innodb_rollback_on_timeout  | OFF      |
| interactive_timeout         | 14400    |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 60       |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 60       |
| wait_timeout                | 14400    |
+-----------------------------+----------+
13 rows in set (0.00 sec)

可以看到 wait_time与interactive_timeout  都是14400s 通过计算 这是半小时,其实mysql默认的是28800s(8小时)

可以做一个测试

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://10.19.159.31:3399/hansight?serverTimezone=UTC"></property>
		<property name="user" value="hansight"></property>
		<property name="password" value="HanS!gh5#NT"></property>
		<!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->
		<property name="initialPoolSize"  value="2"></property>
		<!-- 连接池中保留的最小连接数,默认为:3-->
		<property name="minPoolSize"  value="2"></property>
		<!--连接池中保留的最大连接数。默认值: 15 -->
		<property name="maxPoolSize"  value="15"></property>

	</bean>

这时候启动系统等待半个小时后 再次进入系统发现报出上面的错误

解决办法:

1、增加配置等待时间数  但是治标不治本;

 

set interactive_timeout=2147483;
Query OK, 0 rows affected (0.00 sec)

mysql> set wait_timeout=2147483;
Query OK, 0 rows affected (0.00 sec)

2、修改C3P0配置文件,让空闲连接不要等待那么长时间,最好小于wait-time时间就关闭掉

<!--最大空闲时间,3600秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
		<property name="maxIdleTime"  value="5600"></property>

 3、修改配置文件,一段时间就自动检测一次空闲连接,连接一次数据库

 

<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。测试的表必须在初始数据源的时候就存在。Default: null-->
		<property name="preferredTestQuery"  value="select 1"></property>
		<!--每10000秒检查所有连接池中的 空闲连接。Default: 0 -->
		<property name="idleConnectionTestPeriod"  value="10000"></property>
		<!-- 获取连接时测试有效性,每次都验证连接是否可用 -->
		<property name="testConnectionOnCheckout" value="true"></property>//默认是fasle