概要:
同じ行を更新しようとして大量のメッセージが発生し、Oracle デッドロック エラーが発生する高スループット アプリケーションのベスト プラクティスを知りたいです。これらのエラーを回避できないことはわかっていますが、何度も何度も発生するデッドロック エラーによって行き詰まることなく、どのようにして正常に回復するのでしょうか。
詳細:
高スループットの JMS メッセージング アプリケーションを構築しています。本番環境は、2 つの weblogic 11g ノード (それぞれ 6 つの MDB リスナー インスタンスを実行) になります。Oracle データベースで同じ行を更新しようとする約 1000 のメッセージを取得すると、Oracle デッドロック エラー (ORA-00060) が発生していました。ノード間の Java 同期は、標準の Java スレッド API では不可能です (テラコッタなどのサードパーティ ソリューションを使用したくない他のソリューションがない場合を除きます)。
Oracleの「select for update WAIT n secs」ステートメントが役立つことを期待していました。これにより、競合するスレッド(同じ行の)が最初のスレッド(最初に行のロックを取得したスレッド)が処理されるまで数秒待機するようになるためです。 .
「SELECT FOR UPDATE WAIT n」の最初の問題は、待機時間にミリ秒を使用できないことです。これは、アプリケーションのスループットに悪影響を及ぼし始めます。これは、1 秒の WAIT (最小待機時間) を設定するとメッセージの遅延が発生するためです。
次に、weblogic キューの再配信遅延パラメーター (この場合は 30 秒) をいじっています。デッドロック エラーが原因でスレッドが跳ね返るたびに、再試行されるまで 30 秒待機します。
私たちの経験では、1000 件の競合するメッセージがあり、デッドロックが何度も発生し続けるため、多くの状況で処理に永遠に時間がかかります。
現在のアーキテクチャでは、(1000 件の競合するメッセージの場合) 関係なくデッドロック エラーが発生するはずですが、アプリケーションは、ループ メッセージを再試行した後にこれらのエラーから回復するのに十分な回復力を備えている必要があることを理解しています。
ここで何が欠けているか分かりますか? 以前に同様の問題に対処したことがある人はいますか?
このデッドロック状態から回復し、追加のハードウェアをあまり使用せずに適切な時間内にすべてのメッセージを最終的に処理できるように、これを弾力的に機能させることができる設計のアイデアを探しています。
計算の詳細: これらの 1000 のメッセージは、それぞれに関連付けられた数量を持つ 4 つの異なるポジション タイプの 4 つのオブジェクトを作成します。これらの数量は、(ポジション タイプに応じて) 4 つの異なるスロットに統合する必要があります。これらの 4 つの個別のスロットが個別のスレッドによって更新されているときに、デッドロックが発生しています。競合状態を回避するために、データベース行に適用される前に、これらの個々の更新を特定の順序で並べ替えています。