13

分散リソースを含む 2 フェーズ コミットを実装しています。参加しているデータベースの障害をシミュレートするにはどうすればよいですか? テーブルのデッドロックが発生するため、ネットワーク ケーブルを引き抜くことはできません。StaleConnectionException現在、アプリケーション コードでフックを使用しており、クエリの実行前、クエリの実行後など、さまざまな時点でスローされます。このアプローチに関する私の懸念は次のとおりです。

  • DB 障害をシミュレートするより良い方法はありますか?
  • DB接続がうまくいかない場合、接続オブジェクトはどうなりますか? その値を保持しますか、それとも null になりますか?
  • アプリケーションが DB に再接続しようとすると、実際には何が起こるでしょうか?接続オブジェクトはどのような値を取得しますか?接続プールの既存の値を使用しますか?

また、クエリの実行中、コミット中(準備が送信された後など)のような中間点でテストしたいと思います。今、私はアプリケーションをデバッグ モードにし、関数呼び出しにステップ インして、その間にプラグをプルします。ただし、このアプローチは手動であり、大規模なテストには適していません。

これを行うのに役立つシミュレーター/エミュレーターまたはツールはありますか?

4

4 に答える 4

5

それはたくさんの質問です:)私は前の答えを完成させようとします。

Is there a better way to simulate the DB failure?

すべてのケースのテストは複雑です。主なケースをテストする1つの方法は、JCAコネクタを作成することです(DBドライバJCAコネクタです)。トランザクションに参加するコネクタ(3番目の参加者)から接続を取得できます。その後、接続によって特定のエラーが発生する可能性があります。

連携する3つの部分があります:(1)アプリケーション、(2)アプリ。サーバーのトランザクションマネージャー、および(3)jcaコネクター(いわゆるリソースアダプター)。

3つの部分の間の通信

接続は、を介してトランザクションにフックしManagedConnection.getXAResourceます。カスタムjcaコネクタを使用すると、アプリケーション(Connection画像内)またはアプリケーションサーバーのトランザクションマネージャ(画像内XAResourceから取得)に例外を発生させることができますManagedConnection。特に、との間に例外をスローできますXAResource.prepare。これは、2フェーズコミット XAResource.commitのエラーに対応します。

参加者のエンリメントの順序を制御するのは難しいことに注意してください(この質問を参照)。したがって、失敗の1つ(つまり、あなたの失敗)をテストするのは簡単prepareですが、それらが呼び出される順序を制御するのは困難です。2フェーズコミットのすべての可能な無効な状態を再現することは、特に最適化を実行する場合は複雑です。

(私はかつてJCAコネクタ(http://code.google.com/p/txfs)を作成しましたが、サンプルコードが必要な場合は、他にもあります。)

What happens to the connection object when DB connection goes bad? 
Does it retain its value or does it become null?

ManagedConnectionトランザクションマネージャに通知できます。通知の1つは、ConnectionEvent.CONNECTION_ERROR_OCCURREDこの特定の接続を使用しているときにエラーが発生したことを通知することです。

他の回答で述べたように、通常、トランザクションごとに1つの管理対象接続が関連付けられています。管理された接続は物理的な接続を抽象化するので、あまり多く使用したくありません。アプリケーションは「ハンドル」(Connection写真)のみを取得します。1つの特定のトランザクション内で取得されるハンドルはすべて、同じ管理対象接続を指します。これは、ほとんどのアプリサーバーがサポートする最適化です。

管理対象接続が無効になると、それを使用するハンドルも無効になります。ただし、ハンドルを「更新」することはできません。トランザクションはロールバックする必要があり、管理対象接続は破棄されます。別のトランザクションが開始されると、プールからの別の有効な管理対象接続に関連付けられます。

What actually happens when application tries to reconnect to DB?
What value does connection object get?
Does it use an existing value from the connection pool?

アプリサーバーは、管理対象接続のプールを管理します。前の段落で述べたように、それが使用されている間、人は悪くなるかもしれません。しかし、使われずに悪くなることもあります。たとえば、基になる物理接続がタイムアウトしたため、プールで使用されている管理対象接続が無効になる場合があります。通常、アプリサーバーには、管理対象接続が有効かどうかをテストしてから使用を開始する機能があります。そうでない場合は、プールから別の管理対象接続を試行するか、新しい接続を作成します。

于 2012-04-26T06:43:12.213 に答える
1

Andrej が質問の一部に答えたので、2 番目の部分に答えさせてください。

アプリケーションで取得する Connection オブジェクトは、物理接続の単なるラッパーです。そのラッパーは、接続プーリングとトランザクション管理で役割を果たします。DB に問題が発生すると、接続ラッパーが使用できなくなり、ロールバックしかできなくなります。2PC の起動前にのみ接続にアクセスし、2PC の起動前に行われたものは復元できないため、これは理にかなっています。

接続を解放して新しい接続を取得しようとしても何も変わらないことに注意してください。これは、特定のデータ ソースからの接続がトランザクションで使用されると、そのデータ ソースから常に同じ接続を取得するためです。同じ取引。これは、アプリケーションがトランザクション全体を再起動しないと「再接続」できないことを意味します。

一方、すべてのリソースが準備された後、すべてのリソースがコミットされる前に問題が発生した場合、トランザクションを回復するのはトランザクション マネージャーの責任です。しかし、これは舞台裏で行われ、アプリケーションは制御できません。また、この時点で、アプリケーションはそのトランザクションで使用されたすべての接続を解放しているはずです。

于 2012-04-11T19:10:52.310 に答える
0

あなたの最善の策は、おそらくメモリデータベースで使用することです。失敗を呼び出し、前後のデータ ソースの状態をチェックして、ロールバック/コミットが適切に実行されていることを確認します。

あなたの他の懸念に関しては、これらは非常に高コストで低報酬のテストのようです。ベンダーのドキュメントを読み、トランザクション環境が適切に構成されていることを確認してください。これが完了したら、おそらくそれを自動化して、手を離すべきです。

独自の 2PC プロトコル固有のトランザクション マネージャー + DB 実装を作成しない限り、これらの機能のテストはベンダーに任せます。

于 2012-04-11T19:27:40.313 に答える