【问题标题】:SQL Server 2008 Transaction, rollback required?SQL Server 2008 事务,需要回滚吗?
【发布时间】:2010-10-22 13:31:55
【问题描述】:

我有一个包含BEGIN TRANSACTIONCOMMIT TRANSACTION 语句的存储过程。事务中有一个选择查询WITH(XLOCK, ROWLOCK)

如果提供超出范围的值,由于某些计算会导致算术溢出错误,事务可能会失败。这个错误会在任何插入/更新语句之前发生。

我的问题是,我是否应该将事务包装在 TRY/CATCH 中并回滚,或者这不是真正需要的,如果事务失败,所有锁都会自动释放?我唯一担心的是,如果事务失败,SQL 不会释放事务的所有锁。

谢谢,

汤姆

【问题讨论】:

    标签: sql-server tsql transactions rollback


    【解决方案1】:

    一个更简单的方法是:

    set xact_abort on
    

    这会导致事务发生错误时自动回滚。

    示例代码:

    set xact_abort on
    begin transaction
    select 1/0
    go
    print @@trancount -- Prints 0
    
    set xact_abort off
    begin transaction
    select 1/0
    go
    print @@trancount -- Prints 1
    

    如果您多次执行第二个段,您会看到事务计数增加到 2、3、4 等。第一个段的单次运行会重置所有事务。

    【讨论】:

      【解决方案2】:

      简短回答:是的。

      每当我使用 BEGIN TRANSACTION 时,我总是包括使用错误处理和 ROLLBACK。遇到意料之外的(和/或意料之外的——你不知道你的代码将来可能需要如何修改)的情况,在生产服务器上留下一个开放的事务的后果太严重了,不能不去做。

      在 SQL Server 2000 及更早版本中,您必须使用@@Error 逻辑。在 SQL 2005 及更高版本中,您可以使用(非常出色的)TRY...CATCH... 语法。

      【讨论】:

        【解决方案3】:

        我喜欢 Brad 的方法,但需要稍微清理一下,以便您可以看到导致问题的错误。

        begin try
            begin transaction;
        
            ...
        
            commit transaction;
        end try
        begin catch
            declare @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int;
            select @ErrorMessage = ERROR_MESSAGE() + ' Line ' + cast(ERROR_LINE() as nvarchar(5)), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
            rollback transaction;
            raiserror (@ErrorMessage, @ErrorSeverity, @ErrorState);
        end catch
        

        【讨论】:

          【解决方案4】:

          TRY/CATCH 不是必需来释放锁。但是,我认为以下模板对大多数交易都有好处。

          BEGIN TRY
              BEGIN TRAN
              ...
              IF (@@error <> 0)
                 ROLLBACK TRAN
          END TRY
          BEGIN CATCH
              ROLLBACK TRAN
          END CATCH
          --BEGIN FINALLY (doesnt exist, which is why I commented it out)    
              IF (@@trancount > 0)
                 COMMIT TRAN
          --END FINALLY
          

          【讨论】:

            【解决方案5】:
            begin transaction; -- you don't want to hit catch block if begin transaction will fail
            begin try
            
                 ... updates/inserts/selects ...
            
               commit transaction; -- the last statement in try code block is always commit
            end try
            begin catch
               rollback transaction; -- first step before other error handling code is rollback  transaction
               declare @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int;
               select @ErrorMessage = ERROR_MESSAGE() + ' Line ' + cast(ERROR_LINE() as nvarchar(5)),  @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
               raiserror (@ErrorMessage, @ErrorSeverity, @ErrorState);
            end catch
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-01-19
              • 2010-12-17
              • 2013-10-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多