Проверьте ограничение, обходя блок CATCH в распределенной транзакции
-
23-08-2019 - |
Вопрос
У меня есть хранимая процедура 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, и я получаю информацию об ошибке (не могу преобразовать «ошибку» в 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.
Решение
Поскольку этим занимается координатор распределенных транзакций, при сбое транзакции в распределенной части транзакции DTC отправляет сообщение в форме предупреждения, которое останавливает выполнение вашего кода и которое TRY/CATCH не может обработать.
SQL Server может обнаружить на вашей стороне, когда вы пытаетесь вставить неправильный тип данных в таблицу (даже на удаленном экземпляре), но ограничение обрабатывается на связанном сервере, что приводит к отправке внимания в DTC и ваш TRY/ CATCH, который следует игнорировать.
Дополнительные сведения см. в первом разделе «Примечание» раздела «Использование TRY...CATCH в Transact-SQL» электронной документации по SQL Server 2008, расположенного по адресу: