网站地图    收藏   

主页 > 后端 > mysql数据库 >

Mysql链接池超时断开解决方法探讨 - mysql数据库栏

来源:自学PHP网    时间:2015-04-16 10:50 作者: 阅读:

[导读] 引言:昨天晚上做了个激活服务,然后测试没问题,今天早上重新测了下,发现报异常,链接不上数据库 先说一下发生这个Exception的大致原因:MySQL的配置中,有一个叫做wait_timeout的参数,这个...

引言:昨天晚上做了个激活服务,然后测试没问题,今天早上重新测了下,发现报异常,链接不上数据库.
先说一下发生这个Exception的大致原因:
MySQL的配置中,有一个叫做“wait_timeout"的参数,这个参数大致的意思是这样:当一个客户端连接到MySQL数据库后,如果客户端不自己断开,也不做任何操作,MySQL数据库会将这个连接保留"wait_timeout"这么长时间(单位是s,默认是28800s,也就是8小时),超过这个时间之后,MySQL数据库为了节省资源,就会在数据库端断开这个连接;当然,在此过程中,如果客户端在这个连接上有任意的操作,MySQL数据库都会重新开始计算这个时间。


这么看来,发生上面Exception的原因就是因为我的服务器和MySQL数据库的连接超过了”wait_timeout"时间,MySQL服务器端将其断开了,但是我的程序再次使用这个连接时没有做任何判断,所以就挂了。
那这个问题怎么解决呢?
查了下网上的资料,其中详细点的如下:


第一个问题:我们的服务器曾经在设计的过程中考虑过这个事情,所以服务器的主线程有一个定时的check机制,每隔半小时会发送一个"select 1"到数据库来保证连接是活动的,为什么这个check机制不起作用了呢?
第二个问题:从上面的Exception中可以得到这么一个信息:
[java] view plaincopy
The last packet sent successfully to the server was 43200 milliseconds ago, which is longer than the server configured value of 'wait_timeout'. 这个信息说的很明白,最后一个成功发到Server的包是43200毫秒之前。但是43200毫秒才43.2秒,也就是说我们的服务器43.2秒之前才和MySQL服务器通过信,怎么会发生超过”wait_timeout“的问题呢?而且MySQL数据库的配置也确实是28800秒(8小时),这又是神马情况呢?[html] view plaincopy
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property>
<property name="hibernate.show_sql">true</property>
<!-- 以下就全是mapping了,省略 -->
</session-factory>
程序中更新的过程大致是这样: [java] view plaincopy
session = org.hibernate.SessionFactory.openSession();
transaction = session.beginTransaction();
session.update(something);
transaction.commit();
session.close(); 在这里,所有关于数据库Connection的连接和关闭都在Hibernate中,因此,不去挖掘Hibernate的源码是不可能了。[html] view plaincopy
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property>
<property name="hibernate.show_sql">true</property>
<!-- c3p0在我们使用的Hibernate版本中自带,不用下载,直接使用 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<!-- 下面这句很重要,后面有解释 -->
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<!-- 以下就全是mapping了,省略 -->
</session-factory>

 

上面配置中最重要的就是hibernate.c3p0.testConnectionOnCheckout这个属性,它保证了我们前面说的每次取出连接时会检查该连接是否被关闭了。不过这个属性会对性能有一些损耗,引用我参考的博客上得话:程序能用是第一,之后才是它的性能(又不是不能容忍)。

当然,c3p0自带类似于select 1这样的check机制,但是就像我说的,除非你将check机制的间隔时间把握的非常好,否则,问题是没有解决的。

好了,至此,困扰我的问题解决完了。希望上面的这些整理可以为我以后碰到类似的问题留个思路,也可以为正在被此问题困扰的人提供一丝帮助。


最后补充点东西:

1,一些c3p0的属性方法总结:

datasource.c3p0.acquireIncrement=10当连接池中的连接用完时,C3P0一次性创建新连接的数目;

datasource.c3p0.minPoolSize=50连接池中保留的最小连接数。默认为15

datasource.c3p0.maxPoolSize=400连接池中保留的最大连接数。默认为15;

datasource.c3p0.initialPoolSize=50初始化时创建的连接数,应在minPoolSize与maxPoolSize之间取值。默认为3;

datasource.c3p0.maxIdleTime=1800最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0;

datasource.c3p0.acquireRetryAttempts=100定义在从数据库获取新连接失败后重复尝试获取的次数,默认为30;

datasource.c3p0.acquireRetryDelay=20两次连接中间隔时间,单位毫秒,默认为1000;

datasource.c3p0.debugUnreturnedConnectionStackTraces=true

datasource.c3p0.maxStatements=0JDBC的标准参数,用以控制数据源内加载的PreparedStatement数量。但由于预缓存的Statement属 于单个Connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素,如果maxStatements与 maxStatementsPerConnection均为0,则缓存被关闭。默认为0;

datasource.c3p0.idleConnectionTestPeriod=1800隔多少秒检查所有连接池中的空闲连接,默认为0表示不检查;

datasource.c3p0.breakAfterAcquireFailure=true获取连接失败将会引起所有等待获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调 用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认为 false;

datasource.c3p0.testConnectionOnCheckout=false因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都 将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable

datasource.c3p0.autoCommitOnClose=true连接关闭时默认将所有未提交的操作回滚。默认为false;

datasource.c3p0.maxStatementsPerConnection=100连接池内单个连接所拥有的最大缓存Statement数。默认为0;

2,本问题中,再多加入<property name="hibernate.c3p0.maxIdleTime">1800</property>这一行,原因在上面属性中有.

3,记得添加两个jar包:我添加的版本是c3p0-0.9.2.1.jar和mchange-commons-java-0.2.3.4.jar

若后面有新的问题 随时补充.

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论