JPA のデッドロックおよびトランザクション・タイムアウトのトラブルシューティング
データベースのデッドロックおよびトランザクション・タイムアウトは、同じデータベース・リソースにアクセスしようとする 2 つ以上のクライアント間での競合が原因となって発生します。 デッドロックは、2 つ以上のクライアント間で循環ブロッキング状態が発生し、互いにブロックし合って、どのクライアントも処理を進められないという、特殊な事例です。 これらの現象は、通常はプログラミング・エラーではありません。 これらは、複雑で相互に依存し合う方法でデータベース・リソースにアクセスするビジネス・ロジックが原因となっています。
このタスクについて
以下のベスト・プラクティスおよび対応策を使用することにより、これらの状態を最小化することができます。
手順
- エラーの原因となった、影響を受けるデータベース・リソースを特定します。
- エラーの発生時に (例外が発生している場合に) 例外を検査することにより、失敗状態の原因となった失敗エンティティーに関する手掛かりが得られることがあります。
- WebSphere® Application Server のデフォルト JPA プロバイダーが使用されている場合、EclipseLink アプリケーション用のトレース・グループ「eclipselink.logging.level.sql」または OpenJPA アプリケーション用のトレース・グループ「openjpa.jdbc.SQL=all」を有効にすることにより、問題となっているデータベース・リソースの SQL ステートメントおよびスレッド情報を収集できます。 情報を照合することにより、どのクライアントおよびエンティティーが失敗状態の原因となった成果物であるのかを調べることができます。
- より複雑な使用シナリオについては、データベース資料を参照して、データ競合の問題の原因となっているオブジェクトおよびトランザクションの特定に役立つ、専門化されたツールまたは技法がないか調べてください。
- 問題が特定されたら、それらのリソースを使用するビジネス・ロジックを検査して、それらの使用法が長時間に及ぶ競合の原因ではないことを判別します。 デッドロックとタイムアウトの問題を解決するための、単一の決まった解決策はありません。
ビジネス・ロジックとエンティティーの関係の複雑さに応じて、解決策は異なります。
デッドロックおよびタイムアウトを解決するための基本的な概念は、必要な時間を超えてリソースを保留することがないようにして、他のクライアントが同じリソースにアクセスできるようにすることです。
競合が避けられない場合には、このような失敗状態が起きたときの復旧方法をアプリケーションで設定する必要があります。
以下に、問題状態を最小化して、問題を解決するために 1 つ以上の方法を適用できるかどうかを判別するために役立つ対応策を示します。
- ビジネス・ロジックが必要以上にエンティティーをロックしないようにします。 主として読み取り専用である JPA アプリケーションでは、デフォルトで JPA によって提供される、オプティミスティック・ロック・セマンティクスを使用するようにしてください。JPA 2.0 では、必要に応じてアプリケーションでペシミスティックなエンティティー・ロックを明示的に指定できる、ペシミスティック・ロック機能が導入されています。 一度に適用されるペシミスティック・ロックの数を最適化してください。 過度なロックは、デッドロックとタイムアウトの機会を増やし、アプリケーションの並行性とスループットを損ないます。
- データ・ソース接続分離レベルを、必要以上に制限的に設定しないようにします。 分離レベルは、接続レベルでペシミスティック・ロック・セマンティクスが与える影響と同じ影響を与えます。 JPA では、基本的なデータ保全性の目的を達成するために、少なくとも「読み取りコミット」分離レベルが必要です。 WebSphere Application Server 接続マネージャーのデフォルトの分離レベルは、データベースごとに異なります。 JDBCConnectionSpec API の仕様情報については、『プログラミング・インターフェース』のトピックを参照してください。
- アクティブ・トランザクションの所要時間を最小化します。 アクティブ・トランザクションの時間が長いと、他のクライアントによって必要とされるリソースを占有してしまう可能性があります。 すべてのリソースが完了したら、すぐにトランザクションをコミットしてください。
- エンティティーの相互依存関係を回避するようにビジネス・ロジックを最適化します。 ビジネス・ロジックの 2 つのセットが類似のリソースを使用する場合に、従来型のデッドロック循環依存関係を避けるために同じ順序でリソースを更新するようにしてください。 このやり方は、使用される分離レベルによって異なります。 これは、次の対応策で説明されている、リソースに対する暗黙ロックの適用と同じ効果を持ちます。
- 共通リソースへの並行アクセスを同期させるためにペシミスティック・ロックを使用します。 これまで説明した対応策がお客様の状況に適用できない場合には、さまざまなクライアントによって並行して使用される共通リソースへのアクセスを同期させるための代わりの選択肢として、ペシミスティック・ロックがあります。 アプリケーションで JPA 2.0 のペシミスティック・ロック機能を使用して、トランザクションがコミットまたはロールバックされるまで、他のクライアントが共通リソースにアクセスするのをブロックすることができます。 ペシミスティック・ロックの使用が増えると、並行性およびスループットが影響を受けることがあります。 WebSphere Application Server の JPA アクセス・インテントによっても、EJB 呼び出しまたはユーザー定義のタスク名に基づいてデータ・リソースをロックするための、別の選択肢が用意されています。
- デッドロックおよびタイムアウト例外を処理し、この状態から復旧します。 ほとんどのデータベース・サーバーには、デッドロック予防メカニズムが組み込まれています。 このメカニズムがデッドロック状態を検出した場合にデータベースによって使用される代表的な対応策は、要求のうちの 1 つを取り消して、他の要求の処理を続行できるようにすることです。 ただし、どの要求が打ち切られるのかはデータベースによって異なり、特定されていません。 アプリケーションによって許可される場合には、デッドロック状態から復旧して操作を再試行することをお勧めします。


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tejb_jpadeadlock
ファイル名:tejb_jpadeadlock.html