【问题标题】:Check Contraint Bypassing CATCH block in Distributed Transaction在分布式事务中检查约束绕过 CATCH 块
【发布时间】:2010-10-07 12:03:11
【问题描述】:

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

..我在远程表上有一个检查约束,要求 id 列中的值 > 0,然后事情就不像我预期的那样工作。事务DOES 回滚,但控制DOES NOT 转移到catch 块。相反,执行会终止,并打印到输出窗口:

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 所以你的回答是,“我搞砸了”? :-|
    • @Clyde:不完全是,您可以在调用数据库代码的级别上处理它。异常会在那里冒泡并且可以在那里被捕获。
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2015-12-09
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 2014-12-25
    • 1970-01-01
    相关资源
    最近更新 更多