4

TransactionScopeでnpgsqlを使用できると誰かが言うことができますか?

ここのマニュアルで例として提供されているコード: http://npgsql.projects.postgresql.org/docs/manual/UserManual.htmlは機能しません。サーバー上に 2 つの準備済みトランザクションを作成するだけです。

この質問と同じ問題があります: TransactionScope and Npgsql - Prepared Transaction Issue

TransactionScopeでnpgsqlを使用するための解決策はありますか?

UPD: まず第一に、私のターゲット: ソフトウェアで単一の論理トランザクションで 2 つの接続を使用する必要があります。これに対する最適なソリューションは、TransactionScope です。Npgsql は、システム トランザクションでの参加のサポートを宣言します。

次に、問題が発生します。ドキュメントのコードを使用します。このコードは次のことを行います。

  1. トランザクション スコープの作成
  2. 最初の接続を開く
  3. 2 番目の接続を開く
  4. 最初の接続に挿入する
  5. 2 番目の接続に挿入する
  6. 2 番目の接続を閉じる
  7. 最初の接続を閉じる
  8. scope.Complete() を呼び出す
  9. スコープを破棄

9 ステップ後にデータが完全に db にコミットされるのを待ちます。実際、ステップ 6 と 7 で npgsql は準備済みトランザクションを作成し、ステップ 9 では何もしません。最後に、データベースをブロックする 2 つの準備済みトランザクションがあります。そして、それらをコミットまたはロールバックする人は誰もいません。

一般に、スコープで呼び出しが完了する前に接続を閉じると(たとえば、例外のため)、npgsqlはテーブルをブロックする準備済みトランザクションを作成します。正しくない行為だと思います。スコープ破棄後、データが完全にコミットまたは完全にロールバックされるのを待ちます。準備されたトランザクションなし。

ドキュメントのコードでこのバグを繰り返すことができます。参考までに、Devart フリー ライブラリは正しく動作します。

4

1 に答える 1

8

答えを議論する前に明確にする必要がある 3 つの別個の概念があります。

  1. 接続に関連付けられた準備済みステートメントがあり、毎回ステートメントを解析して計画する必要なく、実行ごとに新しい値をプラグインできる「フレームワーク」ステートメントを提供します。利点は、実行ごとにステートメントを解析して計画するために必要な CPU 時間を節約できることです。欠点は、計画が最善の「一般的な」計画に基づいて行われることです。これは、割り当てられる可能性のあるすべての値に対して最善の計画であるとは限りません。プリペアド ステートメントはNpgsqlCommand.prepare()メソッドによって作成されます。

  2. 接続に関連付けられ、一連の関連するデータベース アクティビティのコンテキストを提供するトランザクションがあります。1 つのトランザクションのすべてのアクティビティは、1 つのサーバーの 1 つのデータベースにあります。メソッドによってトランザクションが作成されNpgsqlConnection.BeginTransaction()ます。

  3. 2 フェーズ コミット (2PC) を使用して、複数の接続、異なる接続、異なるデータベース、異なるサーバー上、またはまったく異なるサーバー製品を 1 つの論理的な「分散トランザクション」として使用して、複数のトランザクションを管理する準備済みトランザクションがあります。この機能の使用は、常に高品質のトランザクション マネージャーによって処理される必要があります。通常、分散トランザクションに参加しているデータベースの一部ではない製品です。目標は、関連するすべてのトランザクションの作業が完了すると、トランザクション マネージャーがそれぞれにコミットの「準備」を指示することです。それぞれが、成功または失敗の指示でトランザクション マネージャーに応答する前に、失敗する可能性のあるすべてのことを実行しようとします。すべてのトランザクションが「準備」フェーズで成功すると、トランザクション マネージャーは各トランザクションにコミットするように指示します。準備されたトランザクションは、「準備」フェーズの成功がトランザクション マネージャーに伝えられた直後にサーバーがクラッシュした場合でも、トランザクション マネージャーが要求したときにコミットできる必要があります。TransactionScopeコンストラクタ。 独自のアドホック トランザクション マネージャーを作成しようとしないことを強くお勧めします。トランザクション マネージャーは複雑で微妙なソフトウェアであり、正しく行うのは非常に難しく、正しく行わない と深刻な悪影響をもたらす可能性があります。

質問の意図は最初の 2 つの機能を使用することですが、3 番目の機能は使用しないというのが私の印象です。これが当てはまる場合、トランザクションの管理に間違った方法が使用されています。

参照されているドキュメント ページには、合理的な方法でトランザクションと準備済みステートメントを使用する例があります。クラスを使用するSystem.Transactionsと呼ばれる機能は、TransactionScopeあなたがやりたいことには必要ないようで、問題を引き起こしているようです。を使用した例を見てくださいconn.BeginTransaction()

于 2012-05-12T17:56:02.127 に答える