0

我们运行一个用 Java 编写的网站,该网站使用 JDBC 和 jTDS 来访问 SQL Server 数据库。

我们的数据库包含一个复杂的存储过程,通常需要 10 分钟才能运行。如果我们直接执行存储过程(例如从 SQL Server Management Studio),存储过程可以正常工作,因为它不在事务中运行。但是如果我们使用 jTDS 执行它,它会锁定整个网站 10 分钟。发生这种情况是因为 jTDS 在事务中运行它,因此所有网站请求都处于暂停状态,等待事务完成。

例如,以下由于交易而锁定网站:

Connection connection = DriverManager.getConnection("jdbc:jtds:sqlserver://example/example");
CallableStatement callableStatement = connection.prepareCall("exec dbo.procTest");
callableStatement.execute();

有没有什么方法可以让我们使用 JDBC / jTDS 运行存储过程,而无需在事务中运行?

请注意,在 jTDS 连接上调用它是无效的:

connection.setTransactionIsolation(Connection.TRANSACTION_NONE);

这会引发一个异常,指出 jTDS 不支持 Connection.TRANSACTION_NONE 参数。


编辑:我可能会更好地问这个问题:核心问题不是事务本身,问题是事务导致数据库锁定保持 10 分钟。要么我需要摆脱事务,要么我需要在事务期间释放锁

4

3 回答 3

2

在我们的例子中,必须调用 StoredProcedure,当从 jtds 调用时抛出异常:

无法在事务中执行备份或恢复操作。

我发现@ https://communities.bmc.com/docs/DOC-66239 是 exec 调用需要在前面加上“SET IMPLICIT_TRANSACTIONS OFF;”

这是基于弹簧的片段的样子:

try {
  jdbcTemplate.getJdbcOperations.execute("SET IMPLICIT_TRANSACTIONS OFF;")
  //noinspection ConvertExpressionToSAM   // we have 1.6 code version
  jdbcTemplate.getJdbcOperations.call(new CallableStatementCreator {
    override def createCallableStatement(con: Connection): CallableStatement = {
      val callableStatement = con.prepareCall(
        s""" EXEC dbo.RestoreLatestCopy
           |      @ID = ?
           |""".stripMargin)
      callableStatement.setInt(1, getMappedRestoreId(fromDbName))
      callableStatement
    }
  }, parameters ++ rsParams)
} catch {
于 2018-12-07T14:44:20.957 回答
0

调用Connection#close()orConnection#commit()应该提交并结束事务。Connection您是否像在块中一样关闭数据库资源finally

于 2010-07-26T12:53:18.287 回答
0

我最终使用了以下丑陋的解决方法。如果有人能解释我如何正确地做到这一点,我仍然很感兴趣;但解决方法暂时可行。

数据库在网络服务器上的同一台机器上运行,因此我能够使用标准 SQL Server 命令行工具来运行存储过程。触发它的 Java 代码是:

    try {
        Process process = Runtime.getRuntime().exec("sqlcmd -E -d \"example\" -Q \"EXEC dbo.procTest;\"");
        process.waitFor();
    } catch (IOException e) {
        // Handler here
    } catch (InterruptedException e) {
        // Handler here
    }

所以运行完全相同的存储过程——不同之处在于网络服务器没有锁定,因为sqlcmd没有在单个事务中运行它。是的,它很丑……但这是我所知道的唯一可行的选择!

于 2010-07-28T03:44:52.573 回答