首页 > 解决方案 > 如何修复“SQLServerException:连接已关闭”。在这个 Try-With-Resources 块中出现?

问题描述

我正在对 DBMS 进行性能测试。我必须为我的硕士论文手动完成。我必须有一定数量的线程,每个线程都打开自己的与数据库的 JDBC 连接(连接池不是一个选项)并提交相同数量的相同事务(每个线程执行相同的工作)。我将连接作为try-with-resources块中的资源打开。连接应该保持打开直到try-with-resources作用域结束,但有时会,有时不会。

try (Connection conn = getConn();
    PreparedStatement simpleSelectStmt = conn
                         .prepareStatement(tcInstance.getQueryMap().get("SimpleSelect").getSimpleSelect())) {

        setConnIsolation(conn);

        long startTime = System.nanoTime();
        singleThread.execute(new Runnable() {

            @Override
            public void run() {

                for (int j = 0; j < tcInstance.getnT(); j++) {
                    try {
                        conn.setAutoCommit(false);
                        simpleSelectStmt.execute();
                        conn.commit();
                    } catch (Exception e) {
                        error++;
                        if (detectDeadlock(e.getMessage())) {
                            deadlock++;
                            System.out.println("Deadlock detected!");
                        } else {
                            e.printStackTrace();
                        }

                        try {
                            if (conn != null) {
                                conn.rollback();
                            }
                        } catch (SQLException e1) {
                            System.out.println("There was an error in rolling back the transaction.");
                            e1.printStackTrace();
                        }

                    }

                    if (j != (tcInstance.getnT() - 1)) {
                        try {
                            Thread.sleep(t);// ms
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

                measureCPUusage(Thread.currentThread().getId());
                singleThread.shutdown();

        });

        long endTime = System.nanoTime();
        ....doing some other measurements....

    } catch (Exception e) {
        System.err.println("Error");
    }

这是getConn()用于获取 jdbc 连接的方法:

private Connection getConn() throws SQLException {
    return DriverManager.getConnection(tcInstance.getJDBCurl(), tcInstance.getUser(), tcInstance.getPassword());
}

我希望通过整个 try-with-resources 块打开连接,但是行上有 Connection is closed 异常conn.setAutoCommit(false);conn.rollback();

标签: javajdbctry-with-resources

解决方案


简而言之,您的代码流似乎是这样的:

try (Connection conn = getConn()) {
    setConnIsolation(conn);

    // Posted from Thread-1
    singleThread.execute(new Runnable() {

        @Override
        public void run() {

        // Thread-2 accesses conn created on Thread-1
        // use conn here..
    });

   // ....doing some other work....

} catch (Exception e) {
    System.err.println("Error");
}

//Conn is released

当runnable开始工作时,它对应的线程可能正在使用一个已经释放的conn。这是因为,在发布可运行对象之后,发布线程从 Try-With-Resources 块中出来,并且作为其中的一部分,Conn 被释放。

解决方案:将 Conn 带出 Try-With-Resources 块。


推荐阅读