У меня есть хранимая процедура MSSSQL, выполняющая распределенную транзакцию, которая выглядит следующим образом:
SET XACT_ABORT ON;
SET NOCOUNT ON;
BEGIN TRY
BEGIN DISTRIBUTED TRANSACTION
insert into LNKSRV.INST.dbo.zz (id, val) values (1, 'a');
insert into LNKSRV.INST.dbo.zz (id, val) values (2, 'b');
COMMIT TRANSACTION
END TRY
BEGIN CATCH
if (XACT_STATE() <> 0)
BEGIN
ROLLBACK TRANSACTION;
END
print ERROR_MESSAGE();
print ERROR_LINE();
print ERROR_SEVERITY();
END CATCH
Это отлично работает.
Если я добавлю этот третий оператор вставки:
insert into LNKSRV.INST.dbo.zz (id, val) values ('error', 'b');
... происходит сбой правильно - транзакция откатывается на удаленном сервере, и управление переходит к блоку CATCH, и я получаю информацию об ошибке (не могу преобразовать 'error' в int).
Но если я добавлю этот оператор вставки:
insert into LNKSRV.INST.dbo.zz (id, val) values (-1, 'b');
.. и у меня есть контрольная проверка удаленной таблицы, требующая значения> 0 в столбце id, тогда все не работает так, как я ожидаю. Транзакция ОТВЕТИВАЕТ откат, но управление НЕ переносится в блок перехвата. Вместо этого выполнение просто умирает, и это выводится в окно вывода:
The Microsoft Distributed Transaction Coordinator (MS DTC) has cancelled the distributed transaction
Почему? Мне нужно записать эти ошибки в блоге catch.