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

发布于 2024-09-28 11:49:58 字数 322 浏览 0 评论 0原文

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

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

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

谢谢,

汤姆

I have a stored procedure that has a BEGIN TRANSACTION and COMMIT TRANSACTION statement. Within the transaction is a select query WITH(XLOCK, ROWLOCK).

The transaction can potentially fail due to some calculations that cause an arithmetic overflow error if out of bounds values are supplied. This error would happen before any insert/update statements.

My question is, should I wrap the transaction in a TRY/CATCH and rollback or is this not really required and all locks would be released automatically if the transaction fails? My only concern here is that SQL would not release all locks of the transaction in case the transaction fails.

Thanks,

Tom

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

落墨 2024-10-05 11:49:58

更简单的方法是:

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

A much easier way is:

set xact_abort on

This will cause the transaction to be rolled back automatically when an error occurs.

Example code:

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

If you execute the second segment multiple times, you'll see the transaction count increase to 2,3,4 etc. A single run of the first segment resets all transactions.

放肆 2024-10-05 11:49:58

简短回答:是的。

每当我使用 BEGIN TRANSACTION 时,我总是包括使用错误处理和 ROLLBACK。如果遇到意外(和/或无法预料的——您无法知道将来可能需要如何修改您的代码)的情况,从而在生产服务器上留下未完成的事务,那么后果将非常严重,因此不能不这样做。

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

Short answer: Yes.

Whenever I use BEGIN TRANSACTION, I always include use error handling and ROLLBACK. The consequences of hitting an unanticipated (and/or unanticipatable -- you can't know how your code may need to be modified in the future) situation that leaves an open transaction on a Production server are too severe to not do it.

In SQL Server 2000 and earlier, you have to use @@Error logic. In SQL 2005 and up, you get to use the (far superior) TRY...CATCH... syntax.

翻了热茶 2024-10-05 11:49:58

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

I like Brad's approach but it needed a little clean up so you can see the error that caused the problem.

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
一身软味 2024-10-05 11:49:58

释放锁定不需要 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

TRY/CATCH isn't required to release locks. However, I think that the following template would be good for most transactions.

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
秋千易 2024-10-05 11:49:58
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文