如何修复“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 块中出现?的主要内容,如果未能解决你的问题,请参考以下文章