【问题标题】:How to use SET XACT_ABORT ON the right way如何正确使用 SET XACT_ABORT ON
【发布时间】:2021-12-19 07:12:09
【问题描述】:

我们最近被空降到一个新的 ETL 项目,代码非常糟糕。 我手中有一个包含 700 行和各种更新的查询。

我想使用SET XACT_ABORT ON; 对其进行调试,目标是在只有一个事务失败时回滚所有内容。

但我找到了几种在 StackOverflow 上存档的方法,例如 this:

BEGIN TRANSACTION;
BEGIN TRY

-- Multiple sql statements goes here

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

this:

BEGIN TRY
BEGIN TRANSACTION

-- Multiple sql statements goes here

COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT(ERROR_MESSAGE())
ROLLBACK TRANSACTION
END CATCH

这些都没有使用SET XACT_ABORT ON;

我不明白,SET XACT_ABORT ON 和使用BEGIN TRY BEGIN TRANSACTION 一样吗?

我可以使用吗:

SET XACT_ABORT ON;

-- Multiple sql statements goes here

并摆脱所有:

BEGIN TRANSACTION;
BEGIN TRY

?

另外,我应该使用BEGIN TRANSACTION 然后BEGIN TRY 还是相反?

【问题讨论】:

    标签: sql-server tsql try-catch rollback xact-abort


    【解决方案1】:

    不一样。它决定何时抛出错误。

    您应该始终使用SET XACT_ABORT ON,因为它更加一致;几乎总是,错误会停止执行并抛出错误。否则,一半的事情会抛出错误,另一半会继续执行。

    Erland Sommarskog's site 上有一个关于整个主题的精彩 article,如果您访问 this point,您将看到一个描述这种奇怪行为的表格。总之,我推荐General Pattern for Error Handling,因为它有很好的文档记录,并为您提供了根据其自己的文档对其进行调整的机会。一个这样的调整是使用 raiserror() 微软说停止使用并改用 throw ;但是你必须记住 throw() 在 2012 之前的版本中不存在。

    【讨论】:

      【解决方案2】:

      感谢@George Menoutis 提供的资源。

      我在这里发布我的实用解决方案:

      SET XACT_ABORT ON;
      BEGIN TRY
            BEGIN TRANSACTION;
      
      
            -- Multiple sql statements goes here
      
      
            COMMIT TRANSACTION;
      END TRY
      BEGIN CATCH
            IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
            THROW;
      END CATCH;
      GO
      
      SET XACT_ABORT OFF;
      

      【讨论】:

      • 谢谢@GeorgeMenoutis,请在您的回复中发布。实际上,我遇到了来自 Erland 的与 RETURN 55555 相关的代码问题。
      • 我猜只是抛出@msg
      【解决方案3】:

      如果您有XACT_ABORT ON,则无需手动捕获任何错误,除非您正在记录错误。 XACT_ABORT 将导致所有错误导致事务失败并回滚。

      你只需要

      SET XACT_ABORT ON;
      BEGIN TRAN;
      --do stuff
      COMMIT;
      

      如果只有一个语句,那么你甚至不需要BEGIN TRAN;COMMIT;

      【讨论】:

      • 我测试了@Charlieface,如果我不使用BEGIN TRAN;COMMIT;,则在我的数据库中创建表并插入数据。这意味着SET XACT_ABORT ON; 需要BEGIN TRAN;COMMIT;
      • 你误会了:BEGIN TRAN COMMIT 如果你想要两个语句之间的原子性是必需的。 XACT_ABORT ON 表示如果发生错误,打开的事务会自动中止。所以如果你使用一个事务那么你应该使用XACT_ABORT。但单个语句不需要事务,反正它有自己的
      猜你喜欢
      • 1970-01-01
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      相关资源
      最近更新 更多