一尘不染

相同的旧故事:Tomcat DBCP + MySQL,MySQLNonTransientConnectionException:连接关闭后不允许进行任何操作

tomcat

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

我在server.xml以下位置配置了Tomcat 6,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,它是default 28800

总而言之,我尝试了几种选择,但似乎问题在于mysql连接处于空闲状态时达到28800秒,服务器关闭了它们。我认为pool应该以某种方式使用validationQueryand
处理这种情况testOnBorrow,但似乎我错了。

如果在闲置时间后使用autoReconnecturl我的第一个查询尝试将导致“ ...CommunicationsException: The last packet successfully received from the server was 157,493,261 milliseconds ago.”,但此后它可以正常工作。

如果我使用autoReconnectForPoolsurl或只是不使用它-闲置时间(8小时)后,每次都会得到“
.MySQLNonTransientConnectionException: No operations allowed after connection closed”。

在这两种情况下,当应用加载时,一切都会顺利进行。因此,我得出的结论是,连接是从mysql一侧关闭的。

帮助,我错过了什么?我想在不更改Mysql中的wait_timeout的情况下解决此问题。目标-
稳定的应用程序,如果发生这种情况,它可能会在空闲时间中幸免于难:)


阅读 356

收藏
2020-06-16

共1个答案

一尘不染

我想了一下,决定离开这个问题,尽管问题根本不在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,连接将再次恢复活动。Pool从未触及连接,因为它从未被释放。

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

private MyResource getMyResource() {
  return new MyResource(getConnection());
}

就我而言,这是合理的。进行此更改后,所有事情开始按预期工作。

2020-06-16