このトピックでは、eXtreme Scale Query API および MapRangeIndex 索引付けプラグインがロックとどのように相互作用するのかを説明し、マップに対してペシミスティック・ロック・ストラテジーを使用する際に並行性を増し、デッドロックを減らす、ベスト・プラクティスを いくつか示します。
ObjectGrid Query API では、ObjectMap キャッシュ・オブジェクトおよびエンティティーに対して SELECT 照会を行うことができます。照会エンジンが実行されると、可能であれば MapRangeIndex を使用して、照会の WHERE 文節にある値に一致する一致キーを検索し、または、リレーションシップをブリッジします。索引が使用可能でない場合、照会エンジンは、1 つ以上のマップの各エントリーをスキャンして、適切なエントリーを検索します。照会エンジンおよび索引プラグインは、どちらもロックを取得して、ロック・ストラテジー、トランザクション分離レベル、およびトランザクション状態に応じて、整合データを検査します。
eXtreme Scale HashIndex プラグイン を使用すると、キャッシュ・エントリー値に保管された単一の属性に基づいてキーを検出できます。索引は、キャッシュ・マップとは別のデータ構造に索引付けされた値を保管します。索引は、ユーザーに返す前にマップ・エントリーに対してキーを検証し、正確な結果セットになるようにします。ペシミスティック・ロック・ストラテジーが使用され、ローカル ObjectMap インスタンス (クライアント/サーバー ObjectMap に対するものとして) に対して索引が使用される場合、索引は各一致エントリーに対してロックを取得します。オプティミスティック・ロックまたはリモート ObjectMap を使用する場合、ロックは直ちに解放されます。
取得されるロックのタイプは、ObjectMap.getIndex メソッドに渡される forUpdate 引数によって異なります。forUpdate 引数は、索引が取得すべきロックのタイプを指定します。false の場合、共有可能 (S) ロックが取得され、true の場合は、アップグレード可能 (U) ロックが取得されます。
ロック・タイプが共有可能の場合、セッションのトランザクション分離設定が適用され、ロックの期間に影響します。トランザクション分離を使用してアプリケーションに並行性を追加する方法についての詳細は、トランザクション分離のトピックを参照してください。
eXtreme Scale 照会エンジン は、キャッシュ・エントリーが照会のフィルター基準を満たしているかどうかを検査するためにキャッシュ・エントリーをイントロスペクトするのに必要な場合は、S ロックを取得 します。ペシミスティック・ロックで反復可能読み取りトランザクション分離を使用する場合、照会結果に含まれるエレメントに対してのみ S ロックが保持され、結果に含まれていないエントリーについては解放されます。低いトランザクション分離レベルまたはオプティミスティック・ロックを使用している場合、S ロックは保持されません。
eXtreme Scale 照会を クライアントから使用する場合、照会内で参照されているすべてのマップまたはエンティティーがクライアントに対してローカル (例: クライアント複製マップまたは 照会結果エンティティー) でない限り、 通常、照会はサーバーで実行されます。読み取り/書き込みトランザクションで実行されるすべての照会は、前のセクションで説明したように S ロックを保持します。 トランザクションが読み取り/書き込みトランザクションでない場合は、セッションはサーバーで保持されず、S ロックは解放されます。
共有可能ロックは、並行性および整合性が重要な場合に有効です。共有可能ロックでは、トランザクションの存続期間中、エントリーの値が変わらないことが保証されます。他の S ロックが保持されている間、他のトランザクションが値を変更することはできず、エントリーを更新するインテントを設定できるのは他の 1 つのトランザクションのみです。S、U、および X ロック・モードに関する詳細は、ペシミスティック・ロック・モードのトピックを参照してください。
アップグレード可能ロックは、ペシミスティック・ロック・ストラテジーを使用する場合にキャッシュ・エントリーの更新インテントを特定するために使用されます。アップグレード可能ロックでは、キャッシュ・エントリーを変更しようとするトランザクション間の同期を行うことができます。トランザクションは、S ロックを使用して引き続きエントリーを参照することができますが、他のトランザクションは U ロックまたは X ロックを取得できなくなります。多くのシナリオでは、デッドロックを回避するため、先に S ロックを取得せずに U ロックを取得することが必要になります。 一般的なデッドロックの例については、ペシミスティック・ロック・モードのトピックを参照してください。
ObjectMap orderMap = session.getMap("Order");
ObjectQuery q = session.createQuery("SELECT o FROM Order o WHERE o.orderDate=?1");
q.setParameter(1, "20080101");
q.setForUpdate(true);
session.begin();
// Run the query. Each order has U lock
Iterator result = q.getResultIterator();
// For each order, update the status.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
orderMap.update(o.getId(), o);
}
// When committed, the
session.commit();
Query q = em.createQuery("SELECT o FROM Order o WHERE o.orderDate=?1");
q.setParameter(1, "20080101");
q.setForUpdate(true);
emTran.begin();
// Run the query. Each order has U lock
Iterator result = q.getResultIterator();
// For each order, update the status.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
}
tmTran.commit();
setForUpdate 属性が使用可能になっている場合、トランザクションは、自動的に読み取り/書き込みトランザクションに変換され、予期されたようにサーバーに対してロックが保持されます。照会が索引を使用できない場合、 マップをスキャンして、照会結果を満足しないマップ・エントリーに対して一時的に U ロックをかけ、結果に含まれるエントリーに対しては U ロックを保持するようにする必要があります。