欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

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

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

基本问题解决

项目环境:

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

错误描述:

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

报错日志:

[plain] view plaincopyprint?使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL

  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?使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL

  1. wait_timeout=31536000
  2. interactive_timeout=31536000

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

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

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

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


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

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

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

[java] view plaincopyprint?使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案_MySQL

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