sql-server - 在分布式事务中检查约束绕过CATCH block

标签 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

这很好。

如果我添加此第三插入语句:
  insert into LNKSRV.INST.dbo.zz (id, val) values ('error', 'b');

...它正确失败-事务在远程服务器上回滚并且控制权传递给CATCH块,我得到有关错误的信息(无法将“错误”转换为int)。

但是,如果我添加以下插入语句:
  insert into LNKSRV.INST.dbo.zz (id, val) values (-1, 'b');

..并且我在远程表上有一个检查约束,要求id列中的值> 0,那么事情就没有按我期望的那样工作。事务不会回滚,但控制权不会转移到catch块。取而代之的是,执行只是终止而已,这被打印到输出窗口:
The Microsoft Distributed Transaction Coordinator (MS DTC) has cancelled the distributed transaction

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

最佳答案

由于分布式事务处理协调器正在处理此事务,因此当事务在事务的分布式部分上失败时,DTC将以注意的形式发送消息,这将阻止您的代码执行,并且TRY/CATCH无法处理。

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

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

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

关于sql-server - 在分布式事务中检查约束绕过CATCH block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/546781/

相关文章:

将 .bak 恢复到新数据库的 TSQL 语法

vb6 - 陷阱错误或 'Resume Next'

c# - 如何使用 C# 在 SQL Server 2008 中插入多个列表?

sql-server - 如何调试 SQL Azure 服务器上的速度变慢?

c# - .net + SQL + 超时问题

sql-server - SELECT 语句中的 SQL WHERE 语句

c# - 检查 SQL Server 数据库表中是否存在表或列

sql - 基于 If 语句的 T-SQL 查询 'Where'

mysql调用过程错误代码: 1241.操作数应包含1列

vb.net - 防止VB.Net中的HTMLAgilitypack错误