ロック・ストラテジーには、ペシミスティック、オプティミスティック、およびロックなしがあります。 ロック・ストラテジーを選択する場合、各タイプの操作の比率、ローダーを使用するかどうかなどの問題を考慮する必要があります。
ロックはトランザクションに
束縛されます。以下のロック設定を指定することができます。
- ロックなし: ロック設定を使用しないと、実行は最速になります。
読み取り専用データを使用していれば、ロックは必要ない場合があります。
- ペシミスティック・ロック: エントリーに対するロックを取得し、コミット時までそのロックを保持します。
このロック戦略は、スループットを低下させる代わりに、優れた一貫性を提供します。
- オプティミスティック・ロック: トランザクションがタッチするすべてのレコードの以前のイメージを取得して、トランザクションのコミット時に、そのイメージと現在のエントリーの値を比較します。
エントリーの値が変更された場合、そのトランザクションはロールバックします。
コミット時までロックは保持されません。このロック戦略は、ペシミスティック戦略よりも並行性において優れていますが、トランザクション・ロールバックのリスクがあり、エントリーのコピーを作成するためにメモリーを消費します。
BackingMap でロック戦略を設定します。
各トランザクションのロック戦略を変更することはできません。XML ファイルを使用してマップに対してロック・モードを設定する方法を示す XML スニペットの例は以下のとおりです。この場合、
cc は、
objectgrid/config 名前空間用の名前空間であるとします。
<cc:backingMap name="RuntimeLifespan" lockStrategy="PESSIMISTIC" />
ペシミスティック・ロック
ほかのロック・ストラテジーが可能でない場合は、マップの読み書きにペシミスティック・ロック・ストラテジーを使用します。ObjectGrid マップがペシミスティック・ロック・ストラテジーを使用するように構成されている場合、トランザクションが最初に BackingMap からのエントリーを取得すると、マップ・エントリーのペシミスティック・トランザクション・ロックが取得されます。ペシミスティック・ロックは、アプリケーションがトランザクションを完了するまでは保留されます。通常の場合、ペシミスティック・ロック・ストラテジーは、以下の状態で使用されます。
- BackingMap がローダー付き、またはローダーなしで構成され、バージョン管理情報が使用可能でない場合。
- BackingMap が、並行処理制御について eXtreme Scale からの支援を必要とするアプリケーションによって直接使用されている場合。
- バージョン管理情報は使用できるが、更新トランザクションがバッキング・エントリー上で頻繁に衝突し、その結果、オプティミスティック更新が失敗する場合。
ペシミスティック・ロック・ストラテジーは、パフォーマンスとスケーラビリティーに最大のインパクトを与えるので、このストラテジーはほかのロック・ストラテジーが実行可能でないときのマップの読み取りと書き込みにのみ使用してください。
例えば、こうした状態には、オプティミスティック更新の失敗が頻繁に発生する場合や、オプティミスティック障害からのリカバリーをアプリケーションが処理するには難しい場合が含まれます。
オプティミスティック・ロック
オプティミスティック・ロック・ストラテジーでは、並行して実行中に、2 つのトランザクションが同じマップ・エントリーを更新することはないと想定します。このことから、トランザクションのライフサイクル中、ロック・モードを保留する必要はありません。これは、複数のトランザクションがマップ・エントリーを並行して更新するとは考えられないためです。
オプティミスティック・ロック・ストラテジーは通常、以下の場合に使用されます。
- BackingMap がローダー付き、またはローダーなしで構成され、バージョン管理情報が使用可能である場合。
- BackingMap のほとんどのトランザクションが読み取り操作を実行するトランザクションである場合。
BackingMap に対するエントリーの挿入、更新、または除去操作は、あまり行われません。
- BackingMap は、読み取りと比べてより頻繁に挿入、更新、または除去されるが、トランザクションは同じマップ・エントリー上でほとんど衝突しない場合。
ペシミスティック・ロック・ストラテジーと同様に、
ObjectMap インターフェース上のメソッドは、
eXtreme Scale が、アクセス中のマップ・エントリーのロック・モードを自動的に取得する方法を決定します。ただし、ペシミスティック・ストラテジーとオプティミスティック・ストラテジーの間には、以下のような違いがあります。
- ペシミスティック・ロック・ストラテジーと同様に、メソッドの呼び出しの際、get メソッドおよび getAll メソッドによって S ロック・モードが取得されます。しかし、オプティミスティック・ロックを使用すると、
S ロック・モードはトランザクションが完了するまで保留されません。
代わりに、S ロック・モードはメソッドがアプリケーションに戻す前に保留解除されます。
ロック・モードの取得の目的は、eXtreme Scale が、その他のトランザクションからのコミット済みデータのみが現行トランザクションに可視となるように保証できるようにすることです。
eXtreme Scale がそのデータがコミット済みであることを確認した後で、S ロック・モードは保留解除されます。コミット時に、オプティミスティック・バージョン管理チェックが実行され、
現行トランザクションがその S ロック・モードを保留解除した後で、マップ・エントリーを変更したトランザクションが他にないことが確認されます。
更新、無効化、または削除される前にマップからエントリーがフェッチされない場合、eXtreme Scale ランタイムによって、暗黙的にマップからエントリーがフェッチされます。この暗黙的な
get 操作は、エントリーの変更が要求された時点における現行値を取得するために実行されます。
- ペシミスティック・ロック・ストラテジーとは異なり、
getForUpdate メソッドと getAllForUpdate メソッドは、
オプティミスティック・ロック・ストラテジーが使用された場合には、
get メソッドと getAll メソッドと同様に処理されます。
つまり、S ロック・モードはメソッドの開始時に取得され、S ロック・モードはアプリケーションに戻る前に保留解除されます。
その他の ObjectMap メソッドは、すべてペシミスティック・ロック・ストラテジーの場合と同様に処理されます。つまり、commit メソッドが呼び出されると、
挿入、更新、除去、タッチ、または無効化されたマップ・エントリー用に X ロック・モードが獲得され、
トランザクションがコミット処理を完了するまで X ロック・モードが保留されます。
オプティミスティック・ロック・ストラテジーでは、並行して実行中のトランザクションが同じマップ・エントリーを更新することはないと想定します。この想定から、トランザクションの存続期間中、ロック・モードを保留する必要はありません。
これは、複数のトランザクションがマップ・エントリーを並行して更新するとは考えられないためです。
しかし、ロック・モードが保留されなかったため、現行トランザクションがその S ロック・モードを保留解除した後で、別の並行トランザクションがマップ・エントリーを更新する可能性があります。
この可能性に対処するため、eXtreme Scale はコミット時に X ロックを取得し、
オプティミスティック・バージョン管理チェックを行って、現行トランザクションが BackingMap からマップ・エントリーを読み取って以降、
他にマップ・エントリーを変更したトランザクションがないことを確認します。
別のトランザクションがマップ・エントリーを変更した場合、バージョン・チェックは失敗し、OptimisticCollisionException 例外が発生します。この例外により、現行トランザクションが強制的にロールバックされ、トランザクション全体がアプリケーションによって再試行されることになります。オプティミスティック・ロック・ストラテジーは、
マップがほとんど既読で、同じマップ・エントリーに対する更新が起こる可能性が低い場合に非常に便利です。
ロックなし
BackingMap がロックなしストラテジーを使用するよう構成されている場合、マップ・エントリーのトランザクション・ロックは獲得されません。
ロックなしストラテジーは、アプリケーションが Enterprise JavaBeans (EJB) コンテナーなどのパーシスタンス・マネージャーである場合や、アプリケーションが Hibernate を使用して永続データを取得している場合に有効です。このシナリオでは、BackingMap はローダーを使用せずに構成され、
パーシスタンス・マネージャーによってデータ・キャッシュとして使用されます。またこのシナリオでは、パーシスタンス・マネージャーにより、同じマップ・エントリーにアクセスするトランザクション間の並行性制御が提供されます。
WebSphere® eXtreme
Scale は、並行性制御のためにトランザクション・ロックを入手する必要はありません。これは、パーシスタンス・マネージャーが、コミットされた変更で ObjectGrid マップを更新する前にそのトランザクション・ロックをリリースしないことを前提としています。パーシスタンス・マネージャーがロックを解放する場合は、ペシミスティックまたはオプティミスティック・ロック・ストラテジーを使用しなければなりません。例えば、EJB コンテナーのパーシスタンス・マネージャーが、EJB コンテナー管理のトランザクション内でコミットされたデータで ObjectGrid Map を更新していると仮定します。ObjectGrid マップの更新が、パーシスタンス・マネージャーのトランザクション・ロックが解放される前に発生する場合、ロックなしストラテジーを使用することができます。パーシスタンス・マネージャーのトランザクション・ロックが解放された後で ObjectGrid マップ更新が発生する場合は、オプティミスティックまたはペシミスティックのいずれかのロック・ストラテジーを使用してください。
ロックなしストラテジーの使用が可能なもう 1 つのシナリオは、アプリケーションが BackingMap を直接使用し、ローダーがマップに対して構成されているときです。このシナリオでは、ローダーは、Java Database Connectivity (JDBC) または Hibernate のいずれかを使用してリレーショナル・データベース内のデータにアクセスすることによって、リレーショナル・データベース管理システム (RDBMS) によって提供される並行性制御サポートを使用します。
ローダーの実装は、オプティミスティックまたはペシミスティックのいずれかの方法を使用できます。
オプティミスティック・ロックまたはバージョン管理方法を使用するローダーは、大量の並行性およびパフォーマンスの達成を支援します。
オプティミスティック・ロック手法の実装について詳しくは、
データベース・ローダーの構成の OptimisticCallback セクションを参照してください。基礎となるバックエンドのペシミスティック・ロック・サポートを使用するローダーを使用する場合は、ローダー・インターフェースの get メソッドに渡される
forUpdate パラメーターを使用することがあります。
アプリケーションがデータを取得するために ObjectMap インターフェースの getForUpdate メソッドを使用した場合は、このパラメーターを true に設定します。ローダーはこのパラメーターを使用して、読み取り中の行のアップグレード可能なロックを要求するかどうかを判別できます。
例えば、DB2® は、SQL の SELECT ステートメントに FOR UPDATE 節が含まれている場合、アップグレード可能なロックを獲得します。このアプローチは、ペシミスティック・ロックで説明されているのと同じデッドロック防止を提供します。
詳しくは、ロック または ロック・マネージャーを参照してください。