Рекомендации по вложенным транзакциям в SQL Server
У меня есть некоторые "базовые операции" хранимые процедуры, такие как BookAVehicle
а также UnBookAVehicle
, Они оба в транзакции.
Но теперь мне нужно иметь более сложную хранимую процедуру: RescheduleBooking
, Это также должно быть транзакционным.
Теперь изнутри ResceduleBooking
Я хочу позвонить BookAVehicle
и в этом случае я не хочу откат внутренней транзакции.
Но когда я звоню BookAVehicle
Я хочу сохранить откат.
Любое предложение о том, как сделать это элегантно?
Я думал о чем-то вроде хранимой процедуры "обертка", которая в качестве параметра принимает имя хранимой процедуры и содержит только транзакцию и вызов хранимой процедуры параметра.
Поэтому, когда я называю это "напрямую", я звоню:
TransactionWrapper(BookAVehicleWithoutTrans)
и когда я звоню из другой транзакции, я звоню:
RescheduleBooking -> BookAVehicleWithoutTrans
1 ответ
Когда вы делаете НАЧАЛО СДЕЛКИ, внутренний счетчик увеличивается @@TRANCOUNT. ROLLBACK TRANSACTION выполнит откат всех BEGIN TRANSACTIONS, установив @@ TRANCOUNT в значение 0. Выполнение транзакции фиксации будет только уменьшать @@ TRANCOUNT, полная фиксация будет выполняться, если @@ TRANCOUNT равен 1, а затем установить 0.
Имея это в виду, предполагая, что вы объединили операции BEGIN и COMMIT в ваших операциях Book и UnBook, я бы выполнил процедуру 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