XACT_ABORT 不回滚 SQL Server 2012 上的事务

Posted

技术标签:

【中文标题】XACT_ABORT 不回滚 SQL Server 2012 上的事务【英文标题】:XACT_ABORT not rolling back a transaction on SQL Server 2012 【发布时间】:2018-01-08 15:41:47 【问题描述】:

这是我编写的一个简单测试。

SET XACT_ABORT ON

BEGIN TRANSACTION
GO

CREATE PROCEDURE [usp_MyTest1]
AS
GO

CREATE PROCEDURE [usp_MyTest1]
AS
GO

CREATE PROCEDURE [usp_MyTest2]
AS
GO

COMMIT TRANSACTION

据我了解,既然我有SET XACT_ABORT ON,当第二个创建过程失败时,整个事务将回滚。相反,只有发生错误的事情(第一个创建过程)被回滚,最后一个创建过程执行得很好。然后我收到一条消息说The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

我看到人们对 RAISEERROR 有疑问,但 XACT_ABORT 的文档说 RAISEERROR 不符合 XACT_ABORT。但这并没有提及任何有关错误的信息,例如创建不支持 XACT_ABORT 的重复过程。

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql

THROW 语句不支持 SET XACT_ABORT RAISERROR。新应用程序应使用 THROW 而不是 RAISERROR。

这适用于 SQL Server 2012,如果相关的话。

【问题讨论】:

查看 Remus Rusanu 的回答:***.com/questions/34178270/… 更多详情请参见:sommarskog.se/error-handling-I.html#scope-abortion 事务是运行时结构,而不是词法结构。当事务回滚时,usp_MyTest2 的创建在它自己的事务中继续进行,大概是自动提交。事务不跨越从分析文本的创建到提交/回滚。此外,xact-abort 将中止批处理,但 go 是批处理分隔符,因此最后一次创建在它自己的批处理中。 【参考方案1】:

确实回滚事务。

你可以很清楚地看到这一点

SET XACT_ABORT ON

BEGIN TRANSACTION
GO
SELECT @@TRANCOUNT, 'Point1'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
SELECT @@TRANCOUNT, 'Point2'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
/*
  The earlier transaction has now been rolled back and 
  now running outside an explicit transaction. @@TRANCOUNT is 0
 */
SELECT @@TRANCOUNT, 'Point3'
GO
CREATE PROCEDURE [usp_MyTest2] AS
GO
SELECT @@TRANCOUNT, 'Point4'
GO
/*Nothing to commit so error*/
COMMIT TRANSACTION

返回

到第 3 点时,事务已回滚(包括 usp_MyTest1 的初始创建),usp_MyTest2 的创建发生在新的 auto commit transaction 中。所以最终结果是数据库包含 usp_MyTest2 而不是 usp_MyTest1 假设一开始都不存在。

这就是为什么您在最后也会看到错误

消息 3902,级别 16,状态 1,第 19 行 COMMIT TRANSACTION 请求 没有对应的 BEGIN TRANSACTION。

要在发生错误并回滚事务后终止脚本执行(而不是继续执行后续批处理),最可靠的方法是在 SSMS 中启用 sqlcmd 模式并将其添加到脚本顶部 @ 987654329@

【讨论】:

以上是关于XACT_ABORT 不回滚 SQL Server 2012 上的事务的主要内容,如果未能解决你的问题,请参考以下文章

如何使 SET XACT_ABORT ON 回滚事务?

sql set xact_abort on 用例

事务在休眠中不回滚

设置 xact_abort 并尝试一起捕捉

java jdbc addBatch批处理不回滚

存储过程中的 SET XACT_ABORT ON 和事务