新闻正文

出现MYSQL BUG #5020的解决方法

来源:    2008-7-22 10:31:02 网友评论 0 条 字体:[ ] ~我要投稿!
MYSQL BUG #5020描述:
  
Bug#5020:autoReconnect / autoReconnectForPools broken since 3.0.11
               
  
Our Systems run 24 Hours a Day, but at night nobody connects, so the Socket Connections time out. At morning the first attempts to do anything (e.g. login) fail until we are able to close() and create..() the Connections again.
  
This did not happen until after 3.0.11


错误MESSAGE:
    
Connection was closed due to the following exception:

** BEGIN NESTED EXCEPTION ** 

java.sql.SQLException
MESSAGE: Communication link failure: java.net.SocketException, underlying cause: Software caused connection abort: recv failed

** BEGIN NESTED EXCEPTION ** 

java.net.SocketException
MESSAGE: Software caused connection abort: recv failed

STACKTRACE:

java.net.SocketException: Software caused connection abort: recv failed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)


    at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:222)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:277)
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1385)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:1532)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1923)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1163)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1272)


    at com.mysql.jdbc.Connection.execSQL(Connection.java:2236)
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1555)
    at net.sf.hibernate.impl.BatcherImpl.getResultSet(BatcherImpl.java:89)
    at net.sf.hibernate.loader.Loader.getResultSet(Loader.java:880)
    at net.sf.hibernate.loader.Loader.doQuery(Loader.java:273)
    at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:138)
    at net.sf.hibernate.loader.Loader.doList(Loader.java:1063)
    at net.sf.hibernate.loader.Loader.list(Loader.java:1054)
    at net.sf.hibernate.hql.QueryTranslator.list(QueryTranslator.java:854)
    at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1554)
    at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1531)
    at net.sf.hibernate.impl.SessionImpl.delete(SessionImpl.java:1678)
    at net.sf.hibernate.impl.SessionImpl.delete(SessionImpl.java:1664)

出错原因:

    我们的系统一天24小时运行,但在夜晚的时候是没有人连接的,因此Socket连接就超时了。早上尝试做任何事情(比如:登录)都将以失败告终,除非我们关闭连接或者重新建立连接。3.0.11后才会发生这种情况。
   

专家建议:
   
3.0.11以后,autoreconnect的方法变得更加安全并且和autoCommit状态有关联,这样的话就能使当前‘in-flight’事务失败。请查看相关解释文档,文档的修复故障中包括如何正确实用这个属性。无论在哪种情况下,如果TCP/IP在没有连接的情况下并且还不会冒着数据库被瘫痪的危险,是没有百分之百的方式使得JDBC驱动器被自动重连接的,这也是为何要移除Autoreconnect功能的原因。不管网络发生什么情况,JDBC 都不会说明这个连接是否处于连接状态。JDBC driver 客户端负责处理网络故障,只有应用程序本身(实际上是应用程序的开发者)知道如何正确应对事务失败的情况。在服务器上过期的‘Waittimeout’基本上是服务器给与的强制性网络故障。你通过把‘Waittimeout’设置的高点儿就可以改正它,尽管如此,作为一个开发者,你的代码应该包含相关的异常处理并采取适当的恢复措施,不要都把它们传到调用堆中。连接错误总是有一个SQL状态‘08’。如果你发现它的话,你可以再连接一次并重试事务。不管什么原因,如果这样不起作用的话,配置你的连接池来测试是否处于连接状态并且那些长时间闲置连接。
    如果有一个事务在运行的话,就能得到一个特别简单的例子:
    
---如果连接在autoCommit模式下,autoReconnect是安全的。
    
---如果连接不在autoCommit模式下,但是没有打开的事务,autoReconnect是安全的。
    ---如果连接不在autoCommit模式下,有打开的事务,这样就会抛出异常。
   这样会解决你不在
autoRecomnnect模式下的忧虑并且会保留应用程序的功能性。
   尽管如此,在它改变的时候,在改变日志中没有任何记录说明发生了改变,这点令我很烦。由于这种改变很可能破坏我的应用程序,这种变化因该添加到CHANGE文件中。

  

实际可行的做法:
  (STRUTS+SPRING+HIBERNATE)
  1、把mysql的变量
interactiveClient由 默认的28800(8个小时)延长。并告知用户多长时间后,重新启动TOMCAT服务器。不过,MYSQL5.0.12版本以前的所有版本,只要你设置成 了默认语言为GBK,所有对interactive_timeout(wait_timeout)的时候如何设置,重新连接或者重新启动MYSQL后,都是28800。


  2、在HIBERNATE当中加入:
..
<property name="hibernate.connection.url">jdbc:mysql://192.168.100.111/eai?autoReconnect=true</property>
<property name="enableDeprecatedAutoreconnect">true</property>
<!--  如下的语句是使用第三方的DBCP来建立连接池 -->
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<!--  看到了没有,这个maxWait一定要大于MYSQL默认的28800(秒) -->
<property name="dbcp.maxWait">30000</property>
<property name="dbcp.maxIdle">10</property>

<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">30000</property>
<property name="dbcp.ps.maxIdle">10</property>
..
    
    如上两种方法均可,推荐大家使用第二种方法,来遮挡一下MYSQL的BUG。


收藏到ViVi   收藏此页到365Key
上一篇:request.getParameter()与request.setAttribute()的区别
下一篇:一个简单而非常有用的调试功能
用户名:新注册) 密码: 匿名评论 [所有评论]
评论内容:不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
本栏搜索
  • Google
   网站首页 -  网站地图 -  技术学习 -  网站投稿 -  帮助中心
Copyright 2003-2008 www.javah.net All Rights Reserved
2008 如果你喜欢本站 请收藏本站 并推荐给你的朋友一起分享