如何修复“SQLServerException:连接已关闭”。在这个 Try-With-Resources 块中出现?

Posted

技术标签:

【中文标题】如何修复“SQLServerException:连接已关闭”。在这个 Try-With-Resources 块中出现?【英文标题】:How to fix the "SQLServerException: The connection is closed." occurrence in this Try-With-Resources block? 【发布时间】:2019-05-22 09:00:20 【问题描述】:

我正在对 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");
    

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

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

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

【问题讨论】:

不应该每个线程都有自己的连接吗? 是的,他们应该这样做。我每个线程有一个连接,并且该线程的所有事务(其中 nT)都共享该一个连接。至少我认为我是这样的。我做错了吗?背景:整个 try-with-resources 块位于代表一个线程的类的 work() 方法中,该类在 Main 类的循环的每次迭代中被实例化。 您应该将try-with-resource 移动到singleThread.execute 方法中 非常感谢,我按照你的建议做了,异常不再发生。我想对您的评论进行投票,但我需要 15 声望才能启用该选项(我是新来的)...谢谢,谢谢,谢谢! 【参考方案1】:

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

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。这是因为,发布线程在发布 runnable 之后,从 Try-With-Resources 块中出来,并且作为其中的一部分,Conn 被释放。

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

【讨论】:

【参考方案2】:

请为每个线程打开单独的连接。您的一个线程的打开连接被另一个线程关闭,因此您收到异常。另外,请提供有关 detectDeadlock 的更多信息以进一步帮助您。我希望您在多线程环境中的简单连接不需要这些东西。

【讨论】:

以上是关于如何修复“SQLServerException:连接已关闭”。在这个 Try-With-Resources 块中出现?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复漏洞

如何修复WMI

PHP网站漏洞怎么修复 如何修补网站程序代码漏洞

如何修复这些漏洞? (npm audit fix 无法修复这些漏洞)

如何修复AppScan漏洞

如何在DOS环境下修复系统