Проверка ограничения обхода блока CATCH в распределенной транзакции

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


person Clyde    schedule 13.02.2009    source источник


Ответы (1)


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

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

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

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

person casperOne    schedule 13.02.2009
comment
Так что ваш ответ, я облажался? :-| - person Clyde; 13.02.2009
comment
@Clyde: Не полностью, вы бы справились с этим на уровне того, что вызывает код базы данных. Исключение будет пузыриться там и может быть поймано там. - person casperOne; 13.02.2009