【问题标题】:Transaction not getting completed after commit in Azure SQL Data Warehouse在 Azure SQL 数据仓库中提交后事务未完成
【发布时间】:2018-01-25 19:23:48
【问题描述】:

我正在 Azure SQL 数据仓库中尝试使用 JDBC 的事务。事务处理成功,但事务处理后,DDL 命令失败,错误为Operation cannot be performed within a transaction

这就是我想要做的。

connection.createStatement().execute("CREATE TABLE " + schema + ".transaction_table (id INT)");
connection.createStatement().execute("INSERT INTO " + schema + ".transaction_table (id) VALUES (1)");
connection.createStatement().execute("INSERT INTO " + schema + ".transaction_table (id) VALUES (2)");

// Transaction starts
connection.setAutoCommit(false);
connection.createStatement().execute("DELETE FROM " + schema + ".transaction_table WHERE id = 2");
connection.createStatement().execute("INSERT INTO " + schema + ".transaction_table (id) VALUES (10)");
connection.commit();
connection.setAutoCommit(true);
// Transaction ends

// Next DDL command to succeed, but it does not
connectiom.createStatement().execute("CREATE TABLE " + schema + ".transaction_table_new (id INT)");
// Fails with `Operation cannot be performed within a transaction`

那么,我们如何关闭 Azure SQL 数据仓库中的事务。

我试着这样做。

try {
     // This fails
     connection.createStatement().execute("CREATE TABLE " + schema + ".transaction_table_new (id INT)");
} catch (SQLServerException e) {
   if (e.getMessage().contains("Operation cannot be performed within a transaction")) {
        // This succeeds
        // Somehow the transaction was closed, may be because of the exception
        connection.createStatement().execute("CREATE TABLE " + schema + ".transaction_table_new "(id INT)");
   }           
}

【问题讨论】:

    标签: azure azure-sqldw


    【解决方案1】:

    SQL 数据仓库要求 CREATE TABLE 语句在事务之外运行。通过将connection.setAutoCommit 设置为true,您将强制Java 在事务中运行执行。我对 Java 有点弱(已经有一段时间了),但是您应该能够通过简单地注释掉 setAutoCommit(true) 行来运行第二个 DDL 语句。这将使 JDBC 驱动程序仅处于执行模式,而不是在事务中运行 execute() 操作。

    【讨论】:

    • 即使我们将自动提交设置为 true,它也不起作用。通常Java中使用jdbc驱动的事务结构是connection.setAutoCommit(false); // 语句 1 // 语句 2 connection.commit();连接.setAutoCommit(true);我们需要将 auto commit 设置为 true 以执行任何 DDL 命令。此事务结构适用于 Azure SQL 数据库。仅对于 Azure SQL 数据仓库,我遇到了这个问题。而且,从上面提到的代码sn-p,事务在异常的情况下完成,因此下一个DDL命令成功。
    • 我也尝试关闭每个语句。没用。
    • 我的第一条评论有误。我的意思是即使我们注释掉 setAutoCommit(true) 行它也不起作用。
    【解决方案2】:

    看来我们必须手动结束事务。

    看起来像这样

    connection.setAutoCommit(false);
    // Transaction statement 1
    // Transaction statement 2
    connection.commit();
    connection.setAutoCommit(true);
    connection.createStatement().execute("IF @@TRANCOUNT > 0 COMMIT TRAN");
    

    这是因为,对于 Azure SQL 数据仓库,jdbc connection.commit() 似乎并不总是发出 COMMIT。它跟踪它正在管理的交易,并决定对它发送的内容“聪明”。因此,在执行任何 DDL 命令之前,会执行手动 COMMIT TRAN 以关闭所有打开的事务。

    这很奇怪,因为我们不必对其他仓库或数据库执行此操作,但它确实有效。而且,这没有记录。

    【讨论】:

      猜你喜欢
      • 2019-09-22
      • 2016-06-30
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多