当前位置:Gxlcms > mysql > 使用c3p0与DBCP连接池,造成的MySql8小时问题解决方案_MySQL

使用c3p0与DBCP连接池,造成的MySql8小时问题解决方案_MySQL

时间:2021-07-01 10:21:17 帮助过:7人阅读

本文提供了对c3p0与DBCP连接池连接MySql数据库时, 8小时内无请求自动断开连接的解决方案。首先介绍一下我在项目(c3p0连接池)中遇到的问题,后面还提供了使用DBCP连接池的解决方案。

基本问题解决

项目环境:

Java Web项目框架为Spring MVC+JPA,使用c3p0连接池,发布环境为Tomcat 7

错误描述:

项目运行一段时间(大概几个小时)之后访问时会出现第一次访问报错,再次访问正常的现象,且多次出现此问题。

报错日志:

[plain] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed:
  2. at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:428)
  3. at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
  4. at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
  5. at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
  6. at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
  7. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  8. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
  9. at com.appcarcare.cube.service.UserService$$EnhancerByCGLIB$$a4429cba.getUserDao()
  10. at com.appcarcare.cube.servlet.DataCenterServlet$SqlTimer.connectSql(DataCenterServlet.java:76)
  11. at com.appcarcare.cube.servlet.DataCenterServlet$SqlTimer.run(DataCenterServlet.java:70)
  12. at java.util.TimerThread.mainLoop(Timer.java:555)
  13. at java.util.TimerThread.run(Timer.java:505)
  14. Caused by: javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed:
  15. at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
  16. at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
  17. at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1397)
  18. at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:62)
  19. at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:71)
  20. at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:60)
  21. at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:378)
  22. ... 11 more
  23. Caused by: org.hibernate.TransactionException: JDBC begin transaction failed:
  24. at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:76)
  25. at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
  26. at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426)
  27. at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:59)
  28. ... 14 more
  29. Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
  30. The last packet successfully received from the server was 1,836,166 milliseconds ago. The last packet sent successfully to the server was 29,134 milliseconds ago.
  31. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  32. at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
  33. at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
  34. at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
  35. at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
  36. at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117)
  37. at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3567)
  38. at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3456)
  39. at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3997)
  40. at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2468)
  41. at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2629)
  42. at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2713)
  43. at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5060)
  44. at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:881)
  45. at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:72)
  46. ... 17 more
  47. Caused by: java.net.SocketException: Software caused connection abort: recv failed
  48. at java.net.SocketInputStream.socketRead0(Native Method)
  49. at java.net.SocketInputStream.read(SocketInputStream.java:150)
  50. at java.net.SocketInputStream.read(SocketInputStream.java:121)
  51. at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
  52. at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
  53. at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
  54. at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3014)
  55. at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3467)
  56. ... 25 more


原因分析:

MySQL服务器默认的“wait_timeout”是28800秒即8小时,意味着如果一个连接的空闲时间超过8个小时,MySQL将自动断开该连接,而连接池却认为该连接还是有效的(因为并未校验连接的有效性),当应用申请使用该连接时,就会导致上面的报错。

解决方案(解决这个问题的办法有三种,推荐第二种):

1. 增加 MySQL 的 wait_timeout 属性的值

修改mysql安装目录下的配置文件 my.ini文件(如果没有此文件,复制“my-default.ini”文件,生成“复件 my-default.ini”文件。将“复件 my-default.ini”文件重命名成“my.ini” ),在文件中设置:

[plain] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. wait_timeout=31536000
  2. interactive_timeout=31536000

这两个参数的默认值是8小时(60*60*8=28800)。

注意: 1.wait_timeout的最大值只允许2147483 (24天左右)

2.修改配置文件为网上大部分文章所提供的方式,也可以使用mysql命令对这两个属性进行修改



2. 减少连接池内连接的生存周期

减少连接池内连接的生存周期,使之小于上一项中所设置的wait_timeout 的值

修改 c3p0 的配置文件,在 Spring 的配置文件中设置:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  2. "maxIdleTime"value="1800"/>

3. 定期使用连接池内的连接

定期使用连接池内的连接,使得它们不会因为闲置超时而被 MySQL 断开。

修改 c3p0 的配置文件,在 Spring 的配置文件中设置:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  2. "preferredTestQuery" value="SELECT 1"/>
  3. "idleConnectionTestPeriod" value="18000"/>
  4. "testConnectionOnCheckout" value="true"/>

知识扩展

C3P0

C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。 c3p0配置文件

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. <default-config>
  2.   
  3.   <property name="acquireIncrement">3property>
  4.   
  5.   <property name="acquireRetryAttempts">30property>
  6.   
  7.   <property name="acquireRetryDelay">1000property>
  8.   
  9.   <property name="autoCommitOnClose">falseproperty>
  10.   
  11.   <property name="idleConnectionTestPeriod">60property>
  12.   
  13.   <property name="initialPoolSize">3property>
  14.   
  15.   <property name="maxIdleTime">60property>
  16.   
  17.   <property name="maxPoolSize">15property>
  18.   
  19.   <property name="maxStatementsPerConnection">property>
  20.   
  21.   <property name="overrideDefaultPassword">passwordproperty>
  22.   
  23.   <property name="password">property>
  24.   
  25.   <property name="propertyCycle">300property>
  26.   
  27.   <property name="testConnectionOnCheckin">trueproperty>
  28.   
  29.   <property name="user">rootproperty>
  30.   在Hibernate(spring管理)中的配置:
  31.   <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
  32.   <property name="driverClass"><value>oracle.jdbc.driver.OracleDrivervalue>property>
  33.   <property name="jdbcUrl"><value>jdbc:oracle:thin:@localhost:1521:Testvalue>property>
  34.   <property name="user"><value>Kayvalue>property>
  35.   <property name="password"><value>rootvalue>property>
  36.   
  37.   <property name="minPoolSize" value="10" />
  38.   
  39.   <property name="maxPoolSize" value="100" />
  40.   
  41.   <property name="maxIdleTime" value="1800" />
  42.   
  43.   <property name="acquireIncrement" value="3" />
  44.   <property name="maxStatements" value="1000" />
  45.   <property name="initialPoolSize" value="10" />
  46.   
  47.   <property name="idleConnectionTestPeriod" value="60" />
  48.   
  49.   <property name="acquireRetryAttempts" value="30" />
  50.   <property name="breakAfterAcquireFailure" value="true" />
  51.   <property name="testConnectionOnCheckout" value="false" />
  52.   bean>
  53.   ###########################
  54.   ### C3P0 Connection Pool###
  55.   ###########################
  56.   #hibernate.c3p0.max_size 2
  57.   #hibernate.c3p0.min_size 2
  58.   #hibernate.c3p0.timeout 5000
  59.   #hibernate.c3p0.max_statements 100
  60.   #hibernate.c3p0.idle_test_period 3000
  61.   #hibernate.c3p0.acquire_increment 2
  62.   #hibernate.c3p0.validate false
  63.   在hibernate.cfg.xml文件里面加入如下的配置:
  64.   
  65.   <property name="hibernate.c3p0.max_size">20property>
  66.   
  67.   <property name="hibernate.c3p0.min_size">5property>
  68.   
  69.   <property name="hibernate.c3p0.timeout">120property>
  70.   
  71.   <property name="hibernate.c3p0.max_statements">100property>
  72.   
  73.   <property name="hibernate.c3p0.idle_test_period">120property>
  74.   
  75.   <property name="hibernate.c3p0.acquire_increment">2property>
  76.   
  77.   <property name="hibernate.c3p0.validate">trueproperty>