使用 APACHE COMMON DBCP +COMMON POOL+MYSQL连接无效的问题

运维 系统运维
1.mysql 会自动关闭长时间不用的connection,一个连接如果处于sleep状态达到mysql的参数wait_timeout指定的时间(默认为8小时),就是自动关闭这个连接 2.common pool中没有指定相应的连接检查参数

Throwable occurred: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 50,123,505 milliseconds ago.  The last packet sent successfully to the server was 50,123,505 milliseconds ago. 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.

这主要是由两个原因引起来的:

1.mysql 会自动关闭长时间不用的connection,一个连接如果处于sleep状态达到mysql的参数wait_timeout指定的时间(默认为8小时),就是自动关闭这个连接
2.common pool中没有指定相应的连接检查参数

解决办法:从common pool的配置参数来解决:

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName">
   <value>${db.driver}</value>
  </property>
  <property name="url">
   <value>${db.url}</value>
  </property>
  <property name="username">
   <value>${db.user}</value>
  </property>
  <property name="password">
   <value>${db.password}</value>
  </property>
  <property name="maxActive">
   <value>100</value>
  </property>
  <property name="maxIdle">
   <value>50</value>
  </property>
  <property name="maxWait">
   <value>10000</value>
  </property>

  <property name="timeBetweenEvictionRunsMillis">
   <value>3600000</value><!--1 hours-->
  </property>
<!--
  <property name="minEvictableIdleTimeMillis">
   <value>20000</value>
  </property>
-->
  
  <property name="testWhileIdle">
   <value>true</value>
  </property>
  <property name="validationQuery">
   <value>select 1 from dual</value>
  </property>
 </bean>
使用上述的三个红色的参数,就可以避免这个问题.这三个参数的意义:

timeBetweenEvictionRunsMillis:启动connection校验定时器,定时器运行时间间隔就是timeBetweenEvictionRunsMillis的值.默认为-1,表示不启动定时器,这里设定为1小时,只要小于mysql的wait_timeout就可以了

testWhileIdle: true,表示检查idle的connection,false为不检查

validationQuery:用于检查connection的sql语句.

这只是一种方法,另外的几种方法:

timeBetweenEvictionRunsMillis+minEvictableIdleTimeMillis:这种方式不检查Connection的有效性,而是检查连接的空闲时间,大于minEvictableIdleTimeMillis就清除.

  <property name="timeBetweenEvictionRunsMillis">
   <value>3600000</value><!--1 hours-->
  </property>

  <property name="minEvictableIdleTimeMillis">
   <value>120000</value><!--connection的空闲时间大于这个值,就直接被关闭,并从连接池中删除-->
  </property>

如果不喜欢用定时器,也可以配置testOnBorrow+validationQuery参数:每次从连接池取参数都会校验连接的有效性.实际上这种方式性能会比定时器差些.
  <property name="testOnBorrow">
   <value>true</value>
  </property>
  <property name="validationQuery">
   <value>select 1 from dual</value>
  </property>

另外,也可以用testOnReturn+validationQuery,不过未必会解决问题:这表示每次使用完连接,归还连接池的时候检查连接的有效性,这有可能导致使用一次无效的连接,***不要用.

上面的几种方法可以合并使用,只是检查的点多了,未必是好事.

【编辑推荐】

  1. 技术解析 容错服务器技术还是双机冗余?
  2. Linux下使用mke2fsk格式化分区的方法
  3. Ubuntu 11.10 利用终端环境备份还原
责任编辑:赵宁宁
相关推荐

2020-12-07 18:19:46

Common Lisp方言编程

2009-09-22 14:57:34

Hibernate d

2011-07-18 08:57:13

MySQLwait_timeouDBCP

2009-07-10 18:02:05

MyEclipseMySQL

2021-03-01 18:37:15

MySQL存储数据

2010-05-17 16:38:08

MySQL 连接池

2021-08-02 09:52:44

NvidiaMozilla数据集

2011-06-01 13:54:10

MySQL

2009-12-29 16:50:13

ADO DataSet

2010-06-12 13:04:03

MySQL连接池

2023-10-07 15:56:49

三链表缓存页flush链表

2011-08-15 14:27:51

CocoaRunLoop

2011-05-17 13:22:50

SQL对象名无效

2010-05-27 18:44:14

MySQL远程连接

2010-06-04 18:24:20

2022-11-20 16:21:33

Linuxping 命令网络连接

2010-06-02 16:36:38

连接MySQL中文乱码

2015-10-16 09:21:13

SparkMySQL数据分析

2022-03-22 15:05:15

MySQL缓冲池

2022-07-08 17:13:32

MySQL数据死锁
点赞
收藏

51CTO技术栈公众号