同样的老故事:Tomcat DBCP + MySQL,MySQLNonTransientConnectionException:连接关闭后不允许任何操作

时间:2013-01-24 11:28:26

标签: java mysql tomcat connection-pooling apache-commons-dbcp

我在这里讨论了有关这个主题的相关问题,并且还搜索了一段时间。似乎我仍然不理解Tomcat的DBCP配置或机制中的某些内容。

我获得了Tomcat 6,在server.xml中配置了DBCP资源:

<Resource name="jdbc/myDB" auth="Container" description="Database connection"
  type="javax.sql.DataSource"
  driverClassName="com.mysql.jdbc.Driver"
  url="jdbc:mysql://myhost:3306/mydb?autoReconnectForPools=true&useUnicode=true"
  username="user"
  password="password"
  validationQuery="SELECT 1"
  testOnBorrow="true"
  testWhileIdle="true"
  timeBetweenEvictionRunsMillis="10000" minEvictableIdleTimeMillis="60000"
  maxActive="20" maxWait="20000" maxIdle="10"
  removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" />

我也查找了mysql的wait_timeout,它是默认的28800

总之,我尝试了几个选项,但似乎问题是mysql连接空闲28800秒,服务器关闭它们。我认为池应该以{{1​​}}和validationQuery处理这种情况,但似乎我错了。

如果我在闲置期后testOnBorrow使用autoReconnect我的第一次查询尝试会产生“url”,但在此之后它会正常工作。

如果我在...CommunicationsException: The last packet successfully received from the server was 157,493,261 milliseconds ago.中使用autoReconnectForPools或只是不使用它 - 在闲置期(8小时)之后我每次都会收到“url”。

在这两种情况下,当应用程序加载时,事情会顺利进行。所以,我得出结论,连接是从mysql的一边关闭的。

帮助,我错过了什么?我想在不改变Mysql中的wait_timeout的情况下解决这个问题。目标 - 稳定的应用程序,如果发生,可以在空闲时间内存活:)

2 个答案:

答案 0 :(得分:0)

不确定它是否会有所帮助,但是在Tomcat 7.x中有一个更新的(应该更好的)连接池实现 - 要使用它,将其添加到你的配置中:

factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"

我很确定所有其他选项都是一样的。 见http://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html

答案 1 :(得分:0)

我想了一下,并决定留下这个问题,尽管问题根本不在Tomcat DBCP中。我的决定是出于这样的事实,即我发现了很多类似的问题,其中很多都没有得到答复,也从未找到可能发生的事情的线索。所以,我在这里留言只是一个警告,对于突然走同一条道路的人来说:

问题是我有一个使用数据库的资源,它只被初始化了一次,如:

class MyClass {
   private MyResource res = null;

   private MyResource getMyResource() {
      if (res == null) res = new MyResource(getConnection());
      return res;
   }

   private Connection getConnection() {
      ....
      con = dataSource.getConnection();
      ....
      return con;
   }
}

当我的应用程序在Servlet中时,它导致了MyResource实例是唯一的实例,并且打开了连接。因此,当MySQL服务器终止过期连接时,我的应用程序将在第一次查询时获得有关超时的异常,但由于后续查询的autoReconnect连接将再次存在。游泳池刚刚没有触及连接因为它从未被发布过。

最后我意识到了这一点,并通过将getMyResource更改为:

来解决
private MyResource getMyResource() {
  return new MyResource(getConnection());
}

就我而言,这是合理的。在这一改变之后,所有事情都开始按预期工作。