【问题标题】:Why is my transaction being rolled back automatically when INSERT INTO fails?为什么 INSERT INTO 失败时我的事务会自动回滚?
【发布时间】:2019-09-08 04:25:07
【问题描述】:

令人惊讶的是,对于我遇到的这个问题,我找不到任何相关的解释或文档。

在这些 SQL 语句的情况下:

SELECT 1 AS Test INTO #tmpTest    
BEGIN TRAN    
SELECT 1 AS Test INTO #tmpTest    
ROLLBACK TRAN

当一一执行时,第 3 行的 SELECT ... INTO 失败,正如预期的那样,并显示消息 -

数据库中已经有一个名为“#tmpTest”的对象。

但是,在那之后,第 4 行中的 ROLLBACK 语句失败:

ROLLBACK TRANSACTION 请求没有对应的 BEGIN 交易。

即使事务 确实 BEGIN 从第 2 行成功。

我见过SQL Server - transactions roll back on error?,但答案不适用于这里,因为默认的xact_abortoff此外,answer from Quassnoianswer by Raj More 矛盾。

真正的解释是什么?

【问题讨论】:

  • 我在 SQL 2017 上尝试过并遇到了同样的情况。很有趣。
  • 使用SQL Server 2016,我在第二条SELECT语句前后添加了SELECT @@TRANCOUNT,然后逐行执行。第一个返回(如预期)1,然后SELECT 失败,然后第二个@@TRANCOUNT 返回0但是,将错误的SELECT 包装在try/catch 中,仍然有一个未处理的事务进入CATCH 块。令人着迷。
  • 我设法收到了这条消息:“消息 3998,级别 16,状态 1,第 1 行在批处理结束时检测到不可提交事务。事务已回滚。”
  • 另一个答案比您接受的答案更准确。批量中止是您所看到行为的关键。
  • 猜你是对的@MartinSmith。

标签: sql-server tsql sql-server-2008 transactions rdbms


【解决方案1】:

参考http://www.sommarskog.se/error-handling-I.html

在这种情况下,您得到的是批量中止,这会导致隐式回滚。该博客是关于 SQL Server 2000 错误处理的,但其中大部分内容仍然有效。

编辑:再挖掘一点,发现这个特别提到了尝试创建一个已经存在的表的情况: http://www.sommarskog.se/error_handling/Part2.html#BatchTranAbort

【讨论】:

    【解决方案2】:

    根据这篇 Microsoft 文章:XACT_STATE (Transact-SQL)

    (...) 发生了导致交易被分类的错误 作为不可提交的交易。请求无法提交 事务或回滚到保存点;它只能请求一个完整的 事务回滚。

    我先运行这个:

    SELECT 1 AS Test INTO #tmpTest    
    SELECT @@TRANCOUNT, XACT_STATE()
    BEGIN TRAN    
    SELECT @@TRANCOUNT, XACT_STATE()
    

    然后:

    BEGIN TRY
        SELECT 1 AS Test INTO #tmpTest    
    END TRY
    BEGIN CATCH
        SELECT @@ERROR, ERROR_MESSAGE()
        SELECT @@TRANCOUNT, XACT_STATE()
    END CATCH
    

    CATCH 块中的 SELECT 返回:“数据库中已经有一个名为 '#tmpTest' 的对象。”,@@TRANCOUNT1,但 @987654328 @ 是 -1,所以 SSMS 中的错误信息是:

    消息 3998,级别 16,状态 1,第 1 行不可提交事务是 在批次结束时检测到。事务被回滚。

    下一个SELECT @@TRANCOUNT 返回0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 2015-01-09
      • 2017-05-31
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多