50

这个问题在 SO 中被问过几次,在其他网站上被问过很多次。但我没有得到任何令人满意的答案。

我的问题:
我有一个 java web 应用程序,它使用简单的JDBC通过Glassfish应用程序服务器 连接到mysql数据库。

我在 glassfish 服务器中使用了具有以下配置的连接池:
初始池大小:25
最大池大小:100
池调整大小:2
空闲超时:300 秒
最大等待时间:60,000 毫秒

该应用程序已经部署了 3 个月,并且运行也很完美。
但是从过去 2 天开始,登录时出现以下错误。

部分堆栈跟踪

com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed due to underlying exception/error:  

** BEGIN NESTED EXCEPTION **  

com.mysql.jdbc.CommunicationsException  
MESSAGE: Communications link failure due to underlying exception:  

** BEGIN NESTED EXCEPTION **  

java.io.EOFException  
MESSAGE: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.  

STACKTRACE:  

java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.  
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1997)  
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2411)  
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2916)  
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)  
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)  
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)  
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)  
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1448)  
............  
............  
my application traces....  

是什么突然导致这个错误?我为此浪费了很多时间。

编辑:重新启动服务器后问题甚至仍然存在。根据 DBA,两个重要的 mysql 服务器配置是:
wait_timeout : 1800 秒
connect_timeout : 10 秒
注意:部署在同一服务器上的其他应用程序连接到同一数据库并使用不同的池运行顺利。

EDIT-2:在阅读了很多东西并期待一些积极的结果之后,我对我的连接池进行了这些更改。

最大等待时间: 0(以前是 60 秒)
连接验证:必需
验证方法:
表名称:演示
最多验证一次: 40 秒
创建重试次数: 1
重试间隔: 5 秒
最大连接使用量: 5

这在应用程序持续运行 3 天时起作用。但我得到了一个非常奇怪和有趣的结果。在监控连接池时,我发现了这些数字:

NumConnAcquired: 44919 计数
NumConnReleased: 44919 计数
NumConnCreated: 9748 计数
NumConnDestroyed: 9793 计数
NumConnFailedValidation: 70 计数
NumConnFree: 161 计数
NumConnUsed: -136 计数

我怎么NumConnFree变成161 Maximum Pool Size = 100
怎么NumConnUsed变成-136,一个负数>怎么可能
NumConnDestroyed NumConnCreated

4

9 回答 9

12

The connection has failed, possibly due to a firewall idle-timeout, etc. If you don't have your JDBC driver configured to reconnect on failure, then this error will not go away unless you open a new connection.

If you are using a database connection pool (you are using one, right?), then you probably want to enable it's connection-checking features like issuing a query to check to see if the connection is working before handing it back to the application. In Apache commons-dbcp, this is called the validationQuery and is often set to something simple like SELECT 1.

Since you are using MySQL, you ought to use a Connector/J-specific "ping" query that is lighter-weight than actually issuing a true SQL query and set your validation query to /* ping */ SELECT 1 (the ping part needs to be exact).

于 2012-12-28T16:47:57.110 回答
9

这很可能意味着数据库已重新启动或与数据库的网络连接已中断(例如 NAT 连接已超时)......并且您的 webapp 正在尝试使用陈旧的数据库连接。

如果重新启动 Web 容器后问题仍然存在,则可能是更严重的问题。


你问了以下问题:

How can the NumConnFree become 161 as I have Maximum Pool Size = 100 ?
How can the NumConnUsed become -136, a negative number ?
How can the NumConnDestroyed > NumConnCreated ? 

从表面上看,这些没有意义。但是,它们可能只是某些使用计数器以非线程安全方式更新的结果。这不一定与您的原始问题有关。

于 2012-12-19T10:51:02.553 回答
9

这是 Java 中的 EndOfFileException,当您的光标起点位于终点或由于某些意外异常而关闭数据库连接时发生。

于 2012-12-28T07:25:32.767 回答
7

虽然我没有明确的解决方案,但似乎有些东西干扰了应用服务器和数据库之间的通信。以下是您可以尝试隔离问题的几件事:

  • 尝试确定这是 mysql 问题还是 java 代码问题。尝试使用命令行工具从与应用服务器相同的主机连接到 mysql,并发出类似的 SQL 以执行登录。使用一个简单的 java 代码进行选择,将其部署到相同的基础设施,看看会发生什么等等。还要检查 mysql 服务器日志,看看你是否能找到任何有用的东西

  • 空闲连接有两种关闭方式:通过在应用服务器内部运行的连接池代码,或通过 mysql 本身。确保检查双方的配置

  • 检查最近是否有任何网络基础架构配置发生更改。是否有任何新的防火墙规则干扰应用服务器 <--> mysql 连接?是否有任何设置禁止打开的 TCP 连接空闲时间超过 X?

  • 尝试不同的连接池库只是为了消除它是连接池的可能性

祝你好运

于 2013-01-03T05:42:41.670 回答
2

这可能是防火墙相关的问题。

于 2013-01-03T10:11:52.383 回答
1

我遇到了这个问题,但我无法更改 MySQL 数据库配置。因此,我确保在我的 sql 连接器类中,连接总是在再次启动之前关闭。就像是:

public static Connection getConnection() {

    if (DatabaseConnnector.conn == null) {
        initConn();
    } else {
        try {
            DatabaseConnnector.conn.close();          
        } catch (SQLException e) {
            e.printStackTrace();
        }
          initConn();
    }
    return DatabaseConnnector.conn;
}

这解决了问题。

于 2016-11-07T23:39:32.213 回答
1

尝试连接和/或从 mysql 服务器获取一些数据时在 PHPStorm 中出现此错误。复选框“单连接模式”为我修复了问题。我就把它留在这里。也许这将有助于将来的一些烈士。

https://www.jetbrains.com/help/phpstorm/configuring-database-connections.html

于 2019-10-29T14:38:39.360 回答
0

就我而言,它是 java mysql 驱动程序/连接器版本。即(即使服务器是版本 8)当我使用 mysql 驱动程序/连接器版本 5.1.44 时,它开始工作。

于 2021-09-24T14:31:13.317 回答
0

我遇到了同样的问题,它是由锁定时间太长引起的。

我们有一个很长的事务A,如果执行它,其他事务将被锁定util事务A完成,所以其他的总是被我们的mysql工具杀死(pt-kill)

于 2020-04-22T01:30:50.277 回答