SQL Server 2008事务,需要回滚吗?

时间:2010-10-22 13:31:55

标签: sql-server tsql transactions rollback

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

如果提供了超出边界值的某些计算会导致算术溢出错误,则事务可能会失败。在任何插入/更新语句之前都会发生此错误。

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

谢谢,

汤姆

5 个答案:

答案 0 :(得分:8)

更简单的方法是:

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等。第一段的单次运行会重置所有交易。

答案 1 :(得分:6)

简短回答:是的。

每当我使用BEGIN TRANSACTION时,总是包括使用错误处理和ROLLBACK。遇到意外(和/或无法预料的 - 您无法知道将来可能需要修改代码的情况)的情况会导致生产服务器上的开放事务过于严重而无法执行此操作。

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

答案 2 :(得分:5)

我喜欢布拉德的方法,但它需要一点点清理,以便您可以看到导致问题的错误。

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

答案 3 :(得分:3)

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

答案 4 :(得分:1)

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