Проверьте ограничение в обход блока CATCH в распределенной транзакции - PullRequest
0 голосов
/ 13 февраля 2009

У меня есть хранимая процедура 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.

1 Ответ

2 голосов
/ 13 февраля 2009

Поскольку координатор распределенных транзакций обрабатывает это, когда транзакция завершается неудачно в распределенной части транзакции, DTC отправляет сообщение в форме внимания, которое останавливает выполнение вашего кода и которое TRY / CATCH не может процесс.

SQL Server может обнаружить с вашей стороны, когда вы пытаетесь вставить неверный тип данных в таблицу (даже на удаленном экземпляре), но ограничение обрабатывается на связанном сервере, что приводит к тому, что внимание направляется на DTC и Ваш TRY / CATCH будет проигнорирован.

Дополнительные сведения см. В первом разделе «Примечание» раздела «Использование TRY ... CATCH в Transact-SQL» электронной документации по SQL Server 2008, расположенном по адресу:

http://msdn.microsoft.com/en-us/library/ms179296.aspx

...