У меня есть хранимая процедура 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 в столбце идентификатора, тогда все работает не так, как я ожидаю. Транзакция ДЕЛАЕТ откат, но управление НЕ передает блоку catch. Вместо этого выполнение просто умирает, и это печатается в окне вывода:
The Microsoft Distributed Transaction Coordinator (MS DTC) has cancelled the distributed transaction
Почему? Мне нужно зарегистрировать эти ошибки в блоге catch.