有关SQL Server中嵌套事务的建议

时间:2013-06-17 14:10:34

标签: sql-server stored-procedures nested-transactions

我有一些“基本操作”存储过程,例如BookAVehicleUnBookAVehicle。他们都在交易中。

但是现在我需要一个更复杂的存储过程:RescheduleBooking。它还需要是交易性的。

现在,在ResceduleBooking内,我想调用BookAVehicle,在这种情况下,我不希望内部事务回滚。

但是当我直接呼叫BookAVehicle时,我想继续回滚。

有关如何优雅地做到这一点的任何建议吗?

我正在考虑使用“包装器”存储过程,作为参数获取存储过程的名称,并且只包含事务和对参数存储过程的调用。

所以,当我“直接”称呼它时,我打电话给:

TransactionWrapper(BookAVehicleWithoutTrans)

当我从另一个交易中调用它时,我打电话:

RescheduleBooking -> BookAVehicleWithoutTrans

1 个答案:

答案 0 :(得分:1)

当您进行BEGIN TRANSACTION时,内部计数器会递增@@ TRANCOUNT。 ROLLBACK TRANSACTION将回滚所有BEGIN TRANSACTIONS设置@@ TRANCOUNT为0.执行提交事务只会减少@@ TRANCOUNT,它会在@@ TRANCOUNT为1之前执行完全提交,然后再将其设置为0.

考虑到这一点,假设你在Book和UnBook程序中配对了BEGIN和COMMIT TRANSACTIONS,我会做类似下面的RescheduleBooking程序,即使unbook失败也会保留第一本书......

CREATE PROCEDURE RescheduleBooking ...
AS
BEGIN
      BEGIN TRY
         BEGIN TRANSACTION
         EXEC BookAVehicle ...
         COMMIT TRANSACTION
      END TRY
      BEGIN CATCH
         IF @@TRANCOUNT > 0
         BEGIN
             ROLLBACK TRANSACTION
         END
         RETURN
      END CATCH;

   -- If the unbook fails the booking above will still stay.
      BEGIN TRY
         BEGIN TRANSACTION
         EXEC UnBookAVehicle ...
         COMMIT TRANSACTION
      END TRY
      BEGIN CATCH
         IF @@TRANCOUNT > 0
         BEGIN
             ROLLBACK TRANSACTION
         END
         RETURN
      END CATCH;
END