﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-super-随笔分类-spring</title><link>http://www.blogjava.net/super/category/46346.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 15 Sep 2010 10:06:36 GMT</lastBuildDate><pubDate>Wed, 15 Sep 2010 10:06:36 GMT</pubDate><ttl>60</ttl><item><title>使用 apache common dbcp +common pool+mysql连接无效的问题</title><link>http://www.blogjava.net/super/archive/2010/09/15/332102.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Wed, 15 Sep 2010 09:57:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2010/09/15/332102.html</guid><wfw:comment>http://www.blogjava.net/super/comments/332102.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2010/09/15/332102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/332102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/332102.html</trackback:ping><description><![CDATA[<br />
<br />
<br />
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.&nbsp; 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.<br />
<br />
<br />
这主要是由两个原因引起来的:<br />
1.mysql 会自动关闭长时间不用的connection,一个连接如果处于sleep状态达到mysql的参数wait_timeout指定的时间(默认为8小时),就是自动关闭这个连接<br />
2.common pool中没有指定相应的连接检查参数<br />
<br />
<br />
解决办法:从common pool的配置参数来解决:<br />
<br />
<p>&nbsp;&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;<br />
&nbsp;&nbsp;&lt;property name="driverClassName"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.driver}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="url"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.url}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="username"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.user}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="password"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.password}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxActive"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;100&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxIdle"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;50&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxWait"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;10000&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</p>
<p><br />
<span style="color: red">&nbsp;&nbsp;&lt;property name="timeBetweenEvictionRunsMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;3600000&lt;/value&gt;&lt;!--1 hours--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</span><br />
&lt;!--<br />
&nbsp;&nbsp;&lt;property name="minEvictableIdleTimeMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;20000&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
--&gt;<br />
&nbsp;&nbsp;<br />
<span style="color: red">&nbsp;&nbsp;&lt;property name="testWhileIdle"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="validationQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;select 1 from dual&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</span><br />
&nbsp;&lt;/bean&gt;<br />
</p>
使用上述的三个红色的参数,就可以避免这个问题.这三个参数的意义:<br />
<br />
timeBetweenEvictionRunsMillis:启动connection校验定时器,定时器运行时间间隔就是timeBetweenEvictionRunsMillis的值.默认为-1,表示不启动定时器,这里设定为1小时,只要小于mysql的wait_timeout就可以了<br />
<br />
testWhileIdle: true,表示检查idle的connection,false为不检查<br />
<br />
validationQuery:用于检查connection的sql语句.<br />
<br />
<br />
这只是一种方法,另外的几种方法:<br />
<br />
timeBetweenEvictionRunsMillis+minEvictableIdleTimeMillis:这种方式不检查Connection的有效性,而是检查连接的空闲时间,大于minEvictableIdleTimeMillis就清除.<br />
<br />
&nbsp;&nbsp;&lt;property name="timeBetweenEvictionRunsMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;3600000&lt;/value&gt;&lt;!--1 hours--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
&nbsp;&nbsp;&lt;property name="minEvictableIdleTimeMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;120000&lt;/value&gt;&lt;!--connection的空闲时间大于这个值,就直接被关闭,并从连接池中删除--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
<br />
如果不喜欢用定时器,也可以配置testOnBorrow+validationQuery参数:每次从连接池取参数都会校验连接的有效性.实际上这种方式性能会比定时器差些.<br />
&nbsp;&nbsp;&lt;property name="testOnBorrow"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="validationQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;select 1 from dual&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
<br />
另外,也可以用testOnReturn+validationQuery,不过未必会解决问题:这表示每次使用完连接,归还连接池的时候检查连接的有效性,这有可能导致使用一次无效的连接,最好不要用.<br />
<br />
<br />
上面的几种方法可以合并使用,只是检查的点多了,未必是好事<br />
<br />
<br />
另外,也可以使用Abandoned的那几个参数,来删除连接池中的连接.也能达到效果.我没测试.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/super/aggbug/332102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2010-09-15 17:57 <a href="http://www.blogjava.net/super/archive/2010/09/15/332102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>