【问题标题】:Is ROLLBACK TRANSACTION required?是否需要回滚交易?
【发布时间】:2012-07-10 00:01:10
【问题描述】:
USE AdventureWorks;
GO
BEGIN TRANSACTION;
GO
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 10;
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 11;
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 12;
GO
COMMIT TRANSACTION;
GO

如果第一个删除语句失败会发生什么?会执行第 2 和第 3 个删除语句吗?该示例没有任何错误处理,是否会在异常情况下保留打开的事务,还是 SQL Server 会自动回滚事务?打开事务 = 锁定资源,对吧?

我正在决定是否必须将 TRY...CATCH 应用于使用事务的存储过程。

我知道set xact_abort on,但想知道没有它会发生什么。

这是我在文档中找到的 - 控制事务(数据库引擎):

如果错误导致事务无法成功完成,SQL Server 会自动回滚事务并释放事务占用的所有资源

但是我在其他帖子中读到不会触发自动回滚。

【问题讨论】:

标签: sql-server transactions


【解决方案1】:

在您的示例中,不使用SET XACT_ABORT ON,即使第一条语句失败,事务也将继续并提交。在您引用的文本中,关键字是if an error **prevents** the successful completion of a transactionDELETE 语句失败不会阻止事务完成。

一个会导致自动回滚的错误示例是,如果与数据库的连接在事务中间被切断。再往下,您引用的MSDN article 说:

如果发生运行时语句错误(例如违反约束) 在批处理中,数据库引擎中的默认行为是滚动 只返回产生错误的语句。你可以改变这个 使用 SET XACT_ABORT 语句的行为。在 SET XACT_ABORT ON 之后 执行时,任何运行时语句错误都会导致自动回滚 当前交易的。编译错误,例如语法错误,是 不受 SET XACT_ABORT 影响。

使用错误处理来捕获错误并在需要时回滚总是一个好主意。

【讨论】:

  • 所以它会回滚失败的第一个删除语句,然后开始执行第二个,然后以同样的方式 - 第三个?最后会去commit语句吗?这意味着单个语句中的错误不会停止批处理执行,对吧?
  • 完全正确。另外,我更新了我的答案(希望)更清楚:)
  • 我从许多来源(例如this)中读到,事务是原子的,从某种意义上说,一切都成功或失败。但是,在同一个链接中,我看到了他们制作的一个手动处理错误的示例。所以我这样说是否正确,应该将交易理解为应该是原子的而不是保证是原子的?
【解决方案2】:

我更喜欢手动控制流程:

BEGIN TRY
BEGIN TRAN

   -- do work

COMMIT
END TRY
BEGIN CATCH
    ROLLBACK
    RAISERROR (...)
END CATCH
GO
猜你喜欢
  • 1970-01-01
  • 2011-12-19
  • 2021-09-19
  • 1970-01-01
  • 2014-10-29
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多