一、出现的问题
我的web工程在隔夜连接mysql数据库,会出现错误如下(截取了关键字),需要重启服务器才能ok。
Communications link failure;
The last packet successfully received from the server was 35,605,633 millise;
二、我的工程环境
使用了struts2.0+hibernate3.3+spring3;mysql 是5.7。
三、原因分析
通过查询网上资料得出,这是由于mysql 服务器默认wait_timeout为28800s,合计8小时。如果8小时后链接还处于sleep状态,mysql将自动将连接断掉。而web工程中默认的连接池用此连接在进行连接将出现错误。
1、你可通过在mysql 中输入下行代码,查询mysql的参数。
show variables like '%timeout%';
更多知识:wait_timeout 和 interactive_timeout 参数详解请见:
http://blog.csdn.net/z1988316/article/details/7976038
2、你也可在mysql中输入下行代码,查询现在的mysql连接;
show processlist
结果如下:
四、解决措施
目前笔者了解3种解决方法:
1、更改mysql的wait_timeout时间(不推荐)
可用set global wait_timeout=XXX;单位为秒,但是最大貌似只能为24天,同时太大会带来诸多弊端。
2、更改hibernate默认的连接池的配置(不推荐)
将hibernate.cfg.xml添加以下代码:
<!-- 针对mysql wait_timeout 默认只有8小时新增的(hibernate自带连接池)
<property name="connection.autoReconnect">true</property>
<property name="connection.autoReconnectForPools">true</property>
<property name="connection.is-connection-validation-required">true</property>
对mysql wait_timeout 默认只有8小时新增的 end(hibernate自带连接池) -->
3、在hibernate使用C3P0连接池(推荐)
hibernate配置C3P0,比较简单,而且是官方推荐的连接池,比自带的连接池好用。所以建议用此方法。
(1)在C3P0官网下载源码:http://sourceforge.net/projects/c3p0/ ;将其中的c3p0-0.9.1.jar和mchange-commons-java-0.2.11.jar复制到lib下。
(2)更改hibernate.cfg.xml,添加C3P0的配置:
其中最关键的是 <property name="hibernate.c3p0.timeout">7200</property>;
每隔7200,连接池就会将连接刷新激活,这样就不会造成mysql数据库timeout的问题。
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="connection.url">jdbc:mysql://172.22.145.10:3306/rdcms?characterEncoding=utf-8&useSSL=false&autoReconnect=true&useSSL=false
<!--jdbc:mysql://localhost:3306/lyh-->
</property>
<property name="connection.username">root</property>
<property name="connection.password">12345678</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="myeclipse.connection.profile">
mysql_rdcms
</property>
<!-- 针对mysql wait_timeout 默认只有8小时新增的(hibernate自带连接池)
<property name="connection.autoReconnect">true</property>
<property name="connection.autoReconnectForPools">true</property>
<property name="connection.is-connection-validation-required">true</property>
针对mysql wait_timeout 默认只有8小时新增的 end(hibernate自带连接池) -->
<!--C3P0配置 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!--数据库连接池的最大连接数 -->
<property name="hibernate.c3p0.max_size">100</property>
<!--数据库连接池的最小连接数,测试时建议为2,实际可以为10 -->
<property name="hibernate.c3p0.min_size">10</property>
<!-- 数据库连接池中连接对象在多长时间未使用过后,就应该被销毁c3p0,
初始值为7200;可以有效防止mysql默认的await_time的8小时过期时间 -->
<property name="hibernate.c3p0.timeout">7200</property>
<!--缓存statement 对象的数量-->
<property name="hibernate.c3p0.max_statements">300</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="hibernate.c3p0.acquire_increment">3</property>
<!-- 表示连接池检测县城多长时间检测一次池内的所有连接对象是否超时。
连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,
这个线程通过比较连接对象最后一次被使用时间和当前时间的时间差来和timeout做对比,进而确定是否销毁这个连接对象 -->
<property name="hibernate.c3p0.idle_test_period">120</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么
属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试
使用。Default: null-->
<property name="automaticTestTable">Test</property>
<property name="testConnectionOnCheckin" >false</property>
<property name="testConnectionOnCheckout" >true</property>
<!--C3P0配置end -->
<mapping resource="com/cms/model/Test.hbm.xml" />
</session-factory>
</hibernate-configuration>
(4)如何测试:
通过调整 <property name="hibernate.c3p0.timeout">7200</property> 参数,以及<property name="hibernate.c3p0.min_size">10</property>。
你可在mysql 输入 show processlist ;查询存在的连接数以及timeout的时间,知晓你的C3P0是否配置成功,同时也可通过time列知晓连接池是否刷新。
例如,我配置参数为<property name="hibernate.c3p0.timeout">30</property> ;(实际不能这么配置)那么time不能大于30s了。
五、入门文章,希望对大家有所帮助,欢迎大家拍砖,谢谢。
六、另:在常文本型的字段中,字段包过大会导致mysql 错误,lost connect,需手动修改变大
进入mysql server
默认是4M
在mysql 命令行中运行
set global max_allowed_packet = 2*1024*1024*10
然后关闭掉这此mysql server链接,再进入。
show VARIABLES like '%max_allowed_packet%';
查看下max_allowed_packet是否编辑成功