Вы не сможете найти решение, которое откатывает только работу, выполненную в usp_MyProcedure
при любых условиях .Рассмотрим наиболее очевидный пример: тупик.Когда вы получаете уведомление об исключении 1205 (вы были выбраны в качестве жертвы тупика), транзакция уже откатилась (чтобы разрешить прогресс).Поскольку обработка ошибок идет, единственным безопасным вариантом является дальнейшее повышение и повторный бросок, чтобы у вызывающей стороны была возможность отреагировать.«Неуправляемая транзакция» - это всего лишь вариация этой темы: просто невозможно, чтобы обработка ошибок могла восстановиться в такой ситуации таким образом, чтобы это было целесообразно для вызывающей стороны, когда вызывающая сторона начала транзакцию.Лучше всего поднять (перебросить).Вот почему я использовал шаблон, который вы видели в моем блоге по адресу Исключительная обработка и вложенные транзакции
Учитывая это в контексте Service Broker, это означает, что не существует полностью пуленепробиваемого, исключительного безопасногопроцедура обработки сообщенийЕсли вы нажмете на незафиксированную транзакцию (или транзакцию, которая уже откатилась к тому времени, когда вы обрабатываете блок перехвата, например 1205 взаимоблокировка), тогда весь пакет полученных сообщений должен будет откатиться.Регистрация обычно выполняется в таких ситуациях после самого внешнего блока перехвата (как правило, найдите активированную процедуру).Вот псевдокод того, как это будет работать:
usp_myActivatedProc
as
@commited = false;
@received = 0;
@errors = 0;
begin transaction
begin try
receive ... into @table;
@received = @@row_count;
foreach message in @table
save transaction
begin try
process one message: exec usp_myProcedure @msg
end try
begin catch
if xact_state()=1
rollback to savepoint
@errors += 1;
-- decide what to do with failed message, log
-- this failure may still be committed (receive won't roll back yet)
else
-- this is a lost cause, re-throw
raiserror
end catch
fetch next @table
endfor
commit
@commited = true;
end try
catch
@error_message = error_message();
if xact_state() != 0
rollback
end catch
if @commited = false
begin
insert into logging 'failed', @received, @error_message
end