0

次のような分散トランザクションを実行する 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ブロックに渡され、エラーに関する情報が取得されます(「エラー」を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

なんで?これらのエラーをキャッチ ブログに記録する必要があります。

4

1 に答える 1

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

于 2009-02-13T17:23:44.530 に答える