【问题标题】:Stale connections, validationQuery does not fix陈旧的连接,validationQuery 无法修复
【发布时间】:2012-02-22 13:43:56
【问题描述】:

我遇到了可怕的 MySQL JDBC 陈旧连接异常:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 243,263,541 milliseconds ago.  The last packet sent successfully to the server was 243,263,541 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.

似乎每个人都同意使用validationQuery + testOnBorrow解决了这个问题,但这并不能解决问题。

我正在使用以下软件 MySQL 5.1.41-3ubuntu12.10 连接器/J 5.1.18 雄猫 6.0.24

这是在 server.xml 中定义连接的方式,我们使用 tomcat-dbcp 来池化连接。

 <Resource
       auth="Container"
       driverClassName="com.mysql.jdbc.Driver"
       factory="org.apache.commons.dbcp.BasicDataSourceFactory"
       logAbandoned="true"
       maxActive="75"
       maxIdle="20"
       maxWait="10000"
       name="jdbc/jndiname"
       password="password"
       removeAbandoned="true"
       removeAbandonedTimeout="60"
       validationQuery="/* ping */SELECT 1"
       testOnBorrow="true"
       testOnReturn="true"
       timeBetweenEvictionRunsMillis="10000"
       testWhileIdle="true"
       scope="Shareable"
       type="javax.sql.DataSource"
       url="jdbc:mysql://host:3306/schema"
       username="username" />

【问题讨论】:

  • 在什么情况下您会遇到那些陈旧的连接异常?您是否正在发送实时查询,这就是结果?您是在执行查询时刚刚创建 JDBC 连接,还是从连接池中获取它们?
  • 每天早上当用户第一次连接到我们的网络应用程序时会发生连接异常。连接来自 Tomcat-DBCP 池。我们可以通过每天重启 Tomcat 来解决这个问题,但这只是掩盖了真正的问题。
  • 当您重新启动 Tomcat 时,您所做的只是让连接池重新设置自己。您是否认为解决此问题的方法是 tomcat 配置、mysql 配置或 tomcat-dbcp 池代码更改?...只是为了让我知道从哪个方向寻找答案。
  • 你看过这篇文章了吗:stackoverflow.com/questions/15949/…
  • 更多背景知识:过去我们使用 connector/J 版本 5.0.8 并遇到过时的连接。当时,我们使用 validationQuery 技巧解决了这个问题。最近我们有理由将连接器/J 升级到 5.1.18,并且旧的连接问题又回来了。更新 Tomcat 或 tomcat-dbcp 不是我们的选择。我已经查看了我能想到的所有可能的 server.xml 和 MySQL 变量,但已经没有想法了。

标签: mysql tomcat


【解决方案1】:

我可能会检查您的 my.cnf 文件中的 wait_timeout。默认值为 28800 秒或 8 小时。最长为 31536000 秒或 365 天。

对于您注意到的第一个异常:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException,我过去曾将其包装在 try/catch 块中。在捕获中,对于那个异常,我重新连接了连接,然后重新发送了查询。在知道我不想经常这样做并且仍然保持开放连接的情况下,我还将默认的 wait_timeout 增加到对我的应用程序来说合理的值。

参见手册参考:http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout

【讨论】:

  • 我们的 wait_timeout 设置为默认的 28800 秒,但我们宁愿解决问题的根本原因,而不仅仅是降低频率。
  • 它至少会给你一些喘息的空间,直到你能修复它。该值的含义如下:如果我的连接在 28800 秒内未使用,请终止它!在您的系统上,如果您的 Tomcat-DBCP 池没有保持其连接活动(如在 DDL 或 DML 语句/查询/插入/选择中),那么 MySQL 将在 8 小时后终止连接,但您可能还没有意识到直到您尝试执行所述 DDL/DML。您可以在设置连接池的位置发布代码吗? MySQL 的类似问题:forums.mysql.com/read.php?39,501441,501692#msg-501692
  • 我已更新问题以包含来自 server.xml 的完整连接属性。我们所有的数据库逻辑都是从 Hibernate 层开始,通过 tomcat-dbcp 到 Connector/J 驱动程序。
  • 那么,你终于找到the root cause了吗?似乎这个与 dbcp 的谜题多年来并没有变老:)
  • 我们将超时设置为最大值,并称之为一天。仍然会时不时地从服务器获得超时,但它不是一个停止器。
【解决方案2】:

您的验证查询不正确。去掉“select 1”,只留下ping。

【讨论】:

  • 不正确,请参阅dev.mysql.com/doc/connector-j/en/… 要使用此功能,请在连接池中指定以 /* ping */ protected static final String PING_MARKER = "/* ping */"; ... if (sql.charAt(0) == '/') { if (sql.startsWith(PING_MARKER)) { @987654327 开头的验证查询@}
  • 我的回复基于此:dev.mysql.com/doc/connector-j/en/… 以下 XML sn-p 说明了如何选择此选项:validationQuery/* ping / 注意 / ping */ 必须准确指定。
【解决方案3】:

mysqlmy.cnf 中,将以下属性设置为较大的值,例如 365 天 -

wait_timeout = 31536000
interactive_timeout = 31536000

会话wait_timeout 的值将被初始化为非交互式连接的全局wait_timeout 值和交互式连接的全局interactive_timeout 值。

PS - 两个值都以秒为单位。

【讨论】:

    猜你喜欢
    • 2015-06-15
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    相关资源
    最近更新 更多