检查约束在分布式事务中绕过CATCH块

时间:2009-02-13 17:09:10

标签: sql-server tsql error-handling transactions distributed-transactions

我有一个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

这很好用。

如果我添加第3个插入语句:

  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');

..我在遥控桌上有一个检查约束,要求值&gt; id列中的0,然后事情不能像我期望的那样工作。事务 DOES 回滚,但控制不会转移到catch块。相反,执行就会消失,并将其打印到输出窗口:

The Microsoft Distributed Transaction Coordinator (MS DTC) has cancelled the distributed transaction

为什么呢?我需要在catch博客中记录这些错误。

1 个答案:

答案 0 :(得分:2)

由于分布式事务协调器正在处理此事务,当事务在事务的分布式部分上失败时,DTC以注意的形式发送消息,这会阻止代码执行,以及TRY / CATCH不能执行过程

当您尝试将不正确的数据类型插入表(甚至在远程实例上)时,SQL Server可以检测到您,但是在链接服务器上处理约束,这会导致注意力被发送到DTC和你的TRY / CATCH被忽略了。

有关详细信息,请参阅位于以下位置的SQL Server 2008联机丛书中“在Transact-SQL中使用TRY ... CATCH”部分中的第一个“注意”部分:

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