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 上的事务的主要内容,如果未能解决你的问题,请参考以下文章