SQL Server 2008事务,是否需要回滚?

7
我有一个存储过程,其中包含BEGIN TRANSACTION和COMMIT TRANSACTION语句。事务中有一个带有(XLOCK, ROWLOCK)选项的select查询。
如果提供了超出范围的值,一些计算可能导致算术溢出错误,从而导致事务失败。在任何插入/更新语句之前都会发生此错误。
我的问题是,我应该将事务包装在TRY/CATCH中并回滚,还是这确实不需要,如果事务失败,所有锁都会自动释放?我唯一的担忧是,如果事务失败,SQL可能不会释放事务的所有锁。
谢谢,
汤姆
5个回答

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

6

简短回答:是的。

每当我使用BEGIN TRANSACTION时,我总是包括错误处理和ROLLBACK。在生产服务器上发生无法预料的(或无法预测的-您无法知道未来可能需要修改代码的方式)情况将导致开放式事务的后果太严重了,因此不这么做。在SQL Server 2000及更早版本中,必须使用@@Error逻辑。在SQL 2005及更高版本中,您可以使用(更好的)TRY…CATCH…语法。


5

我喜欢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

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接