2

我遇到了一个奇怪的情况,准备好的语句使用 MySQL Connector/J 命中 MySQL 数据库。在某些环境中,我会定期遇到更长(> 5 分钟)的准备好的语句的问题。调用 executeBatch 时,我经常遇到异常:

“语句关闭后不允许任何操作”

但是,没有代码可以关闭我可以看到的语句。代码如下所示:

private void execute(MyClass myObj, List<MyThing> things) throws SQLException {
    Connection con = null;
    PreparedStatement pstmt = null;

    try {
        con = ConnectionHelper.getConnection();
        pstmt = con.prepareStatement(INSERT_SQL);
        int c = 0;

        for (MyThing thing : things) {
            pstmt.setInt(1, myObj.getA());
            pstmt.setLong(2, thing.getB());
            pstmt.addBatch();

            if (++c % 500 == 0) {
                pstmt.executeBatch();
            }
        }

        pstmt.executeBatch();
    }
    finally {
        ConnectionHelper.close(pstmt, con);
    }
}

ConnectionHelper.close 本质上只是在语句和连接上调用 close。ConnectionHelper.getConnection 有点像兔子洞——它使用 java.sql.DriverManager 和 proxool 粗略地从池中检索连接,然后用 Spring DataSourceUtils 包装它。

通常它会在最后一个 pstmt.executeBatch() 上失败,但有时会在其他地方失败。我已经检查了 wait_timeout 和 interactive_timeout 配置为默认值(绝对 > 5 分钟)。此外,在大多数情况下,连接和语句都在循环中使用,但几秒钟后,语句在循环外失败。数据库服务器和应用程序服务器运行在同一个子网上,因此网络问题似乎不太可能。

寻找有关如何调试此问题的任何提示——目前,我正在尝试深入研究 MySQL 连接器/J 代码,看看是否能以某种方式获得一些额外的调试语句。不幸的是,我无法附加调试器,因为它目前只能在选定的几个环境中重现。

4

1 回答 1

0

看一下这条线:

            if (++c % 500 == 0) {
                pstmt.executeBatch();
            }

如果它被执行,但循环终止会发生什么。然后,您再次调用 pstmt.executeBatch,批处理中没有任何内容。

于 2014-12-17T19:59:47.763 回答