第11章 トランザクションと並行性
11.1. 同時アクセス リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
JBoss Cache はスレッドセーフのキャッシング API で、 独自の効率的なメカニズムを使用して同時アクセスを制御します。 MVCC (Multi-Version Concurrency Control) の革新的な実装をデフォルトのロックスキームとして使用します。 Boss Cache 3.x 以前のバージョンでは楽観的ロッキングスキームと悲観的ロッキングスキームが提供されていましたが、 MVCC の導入に伴いこれらのスキームは廃止されました。
11.1.1. MVCC (Multi-Version Concurrency Control) リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MVCC は、 共有データへの高速で安全な同時アクセスを制御するため最新のデータベース実装によって一般的に使用されるロックスキームです。
11.1.1.1. MVCC の概念 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MVCC は同時アクセスに対して次のような機能を提供します。
- ライターをブロックしないリーダー
- フェイルファストなライター
同時ライターにデータのバージョン化とコピーを使用してこれを実行します。 理論としては、 リーダーが共有ステートの読み取りを継続する間にライターが共有ステートをコピーし、 バージョン ID の値を増やしてバージョンが有効であることを検証した後 (別の同時ライターが先にステートを変更していないかなど) 共有ステートを書き戻すことになります。
これにより、 ライターの書き込みを妨害せずにリーダーは読み取りを継続することができます。 また、 リーダーがステートの古いバージョンを読み取れるため、 繰り返し可能な読み取りセマンティックが維持されます。
11.1.1.2. MVCC 実装 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MVCC の JBoss Cache 実装は一部の機能が基になっています。
- リーダーはロックを取得しない
- 単一のライターに対し、 共有ステートの 1 つの追加バージョンのみが維持される
- フェイルファストセマンティックを提供するため、 すべてのライターは順次である
スレッドの読み取りに対し、 JBoss Cache の MVCC 実装の大変優れたパフォーマンスを実現するには、 リーダーの同期やロッキングを必要としません。 各リーダースレッドに対して、
MVCCLockingInterceptor がスレッドの InvocationContext (トランザクションを実行している場合は TransactionContext) にあるライトウエイトコンテナオブジェクトのステートをラッピングします。 ステート上の後続操作はすべてコンテナオブジェクトより発生します。 Java の参照をこのように使用することにより、 実際のステートが同時に変更しても読み取りセマンティックを繰り返し可能にすることができます。
ライタースレッドは書き込みを開始する前にロックを取得する必要があります。 現在、 メモリのパフォーマンスを向上するためにロックストライピングを使用しています。 共有ロックプールの大きさは
locking 要素の concurrencyLevel 属性を使用して調整することが可能です。 詳細は 12章設定に関する参考資料 を参照してください。 FQN で排他的ロックを取得した後、 リーダースレッドと同様にライタースレッドがコンテナで変更されるステートをラッピングし、 書き込みに対してステートをコピーします。 コピーする際、 元のバージョンへの参照はコンテナ内で維持されます (ロールバックのため)。 その後、 コピーへ変更が加えられ、 書き込みが終了するとコピーが最終的にデータ構造へ書き込まれます。
これにより、 後続のリーダーは新しいバージョンを認識し、 既存のリーダーはコンテキストに元のバージョンへの参照を保持することができます。
一定期間にライターが書き込みロックを取得できない場合、
TimeoutException がスローされます。 ロック取得タイムアウトのデフォルト値は 10000 ミリ秒で、 locking 要素の lockAcquisitionTimeout 属性を使用して設定することができます。 詳細は 12章設定に関する参考資料 を参照してください。
11.1.1.2.1. 分離レベル リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
JBoss Cache 3.x は REPEATABLE_READ と READ_COMMITTED の 2 つの分離レベルをサポートします。 これらのセマンティックはデータベース分離レベルに相当します。 JBoss Cache の以前のバージョンは 5 つのデータベース分離レベルすべてをサポートしていました。 サポート対象外の分離レベルが設定されると、 最も近いサポート対象レベルにアップグレートまたはダウングレードされます。
以前のバージョンの JBoss Cache との互換性を維持するため、 REPEATABLE_READ がデフォルトの分離レベルとなっています。 READ_COMMITTED の分離は若干弱くなりますが、 REPEATABLE_READ よりもはるかにパフォーマンスが良くなります。
11.1.1.2.2. 同時書き込みと書き込みのスキュー リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MVCC はライターに書き込みロックの取得を強制しますが、 REPEATABLE_READ 使用時に書き込みスキューと呼ばれる現象が発生することがあります。
この現象は、 読み取りとなっていた値を基に並行トランザクションが読み取りの後に書き込みを実行すると発生します。 読み取りには、 トランザクションコンテキストにあるステートへの参照の保持が関係するため、 陳腐化した可能性のある元のステート読み取りを使用して後続の読み取りが行われることがあります。
書き込みのためステートをコピーする際に書き込みスキューが検出されると、 デフォルトの動作として
DataVersioningException がスローされます。 しかし、 ほとんどのアプリケーションでは書き込みスキューは問題となりません (書き込まれたステートが最初に読み取られたステートと関係ない場合など)。 アプリケーションで問題とならない場合は、 writeSkewCheck 設定属性を false に設定し、 書き込みスキューを許可します。 詳細は 12章設定に関する参考資料 を参照してください。
スレッドはコミット済みステート常に使用するため、 READ_COMMITTED を使用する場合は書き込みスキューは発生しません。
11.1.1.3. ロッキングの設定 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
MVCC を設定するには、次のように
<locking /> 設定タグを使用する必要があります。
<locking
isolationLevel="REPEATABLE_READ"
lockAcquisitionTimeout="10234"
nodeLockingScheme="mvcc"
writeSkewCheck="false"
concurrencyLevel="1000" />
nodeLockingScheme- 使用されるノードロッキングスキームです。 指定がないとデフォルトとして MVCC が適用されます。pessimisticやoptimisticなどの廃止されたスキームも使用できますが、 推奨されません。isolationLevel- トランザクションレベルです。 指定がない場合はデフォルトとして REPEATABLE_READ が適用されます。writeSkewCheck- 指定がない場合はtrueがデフォルトとして適用されます。concurrencyLevel- 指定がない場合はデフォルトとして 500 が適用されます。lockAcquisitionTimeout- MVCC を使用する時にライターのみに適用されます。 指定がない場合はデフォルトとして 10000 が適用されます。
11.1.2. 楽観的および悲観的ロッキングスキーム リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
JBoss Cache 3.x より 「MVCC (Multi-Version Concurrency Control) 」 が導入されたため、 悲観的ロッキングスキームと楽観的ロッキングスキームは廃止されました。 将来的にサポートが終了するため、 既存のアプリケーションにはレガシーなロッキングスキームを使用しないことが推奨されます。
本ユーザーガイドにはレガシーなロッキングスキームのドキュメントは含まれていません。 必要な場合は、 JBoss Cache ウェブサイトにある本書の旧バージョンを参照してください。