在Azure SQL数据仓库中提交后,事务未完成

时间:2018-01-17 11:57:49

标签: azure azure-sqldw

我正在使用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)");
   }           
}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

看起来我们必须手动结束交易。

看起来像这样

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。它跟踪它正在管理的交易,并决定对其发送的内容“聪明”。因此,执行手动COMMIT TRAN以在执行任何DDL命令之前关闭所有打开的事务。

这很奇怪,因为我们不必为其他仓库或数据库执行此操作,但它可以正常工作。而且,这没有记录。