我有一些“基本操作”存储过程,例如BookAVehicle
和UnBookAVehicle
。他们都在交易中。
但是现在我需要一个更复杂的存储过程:RescheduleBooking
。它还需要是交易性的。
现在,在ResceduleBooking
内,我想调用BookAVehicle
,在这种情况下,我不希望内部事务回滚。
但是当我直接呼叫BookAVehicle
时,我想继续回滚。
有关如何优雅地做到这一点的任何建议吗?
我正在考虑使用“包装器”存储过程,作为参数获取存储过程的名称,并且只包含事务和对参数存储过程的调用。
所以,当我“直接”称呼它时,我打电话给:
TransactionWrapper(BookAVehicleWithoutTrans)
当我从另一个交易中调用它时,我打电话:
RescheduleBooking -> BookAVehicleWithoutTrans
答案 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