3.4.6 インデクスキー値無排他
インデクスキー値無排他とは,インデクスキー値で排他制御をしないことをいいます。この場合,表のデータだけで排他制御をします。
インデクスキー値無排他を適用した場合,インデクスを利用した検索処理ではインデクスキー値に対して排他は掛けません。また,表に対する更新処理(行挿入,行削除,及び列値更新)の場合にも,更新対象列に定義されているインデクスのインデクスキー値に対して排他は掛けません。
(1) 適用基準
インデクスキー値無排他は基本的に適用することをお勧めします。
ただし,ユニークインデクスの一意制制約保証処理の動作,残存エントリ,及び表データ更新時に出力されるシステムログ量を考慮した上で決めてください。ユニークインデクスの一意制制約保証処理の動作,残存エントリについては,「ユニークインデクスの残存エントリ」を参照してください。また,表データ更新時に出力されるシステムログ量については,マニュアル「HiRDB システム導入・設計ガイド」を参照してください。
(2) インデクスキー値無排他の指定方法
インデクスキー値無排他を適用する場合,システム定義のpd_indexlock_modeオペランドにNONEを指定します。pd_indexlock_modeオペランドについては,マニュアル「HiRDB システム定義」を参照してください。
なお,システム定義のpd_inner_replica_controlオペランドの指定値が1より大きい場合,システム定義のpd_indexlock_modeオペランドの指定に関係なく,pd_indexlock_modeオペランドにはNONEが仮定されます。
(3) デッドロック回避の例
図「デッドロックの例」のようにデッドロックが発生した場合,インデクスキー値無排他を適用するとデッドロックを回避できます。インデクスキー値無排他によるデッドロック回避の例を次の図に示します。
(4) 注意事項
(a) ユニークインデクスの一意性制約保証処理の動作
インデクスキー値無排他を適用している場合,一意性制約定義が指定されている表では,行追加更新時での一意性制約保証処理の動作がインデクスキー値方式(インデクスキー値無排他ではない方式)とは異なります。インデクスキー値無排他を適用する場合は,この動作の違いを考慮しておく必要があります。
一意性制約の保証処理とは,行データの挿入,又は列値更新のときに,インデクス(ユニークインデクス)を使用して追加しようとしているキーを持つデータが既に表にあるかをチェックするとともに,排他制御で追加キーの一意性を保証する処理のことをいいます。一意性制約の保障ができたら直ちにユニークインデクスのインデクスキーエントリを挿入し,その後に行データの挿入,又は列値更新が行われます。
一意性制約の保証処理では,同一キーを持つインデクスキーエントリが見つかった場合,すぐにユニークエラーとなります。そのインデクスキーを操作している相手トランザクションが未決着状態で,ロールバックする可能性があったとしても,排他制御でのチェックをしないですぐにユニークエラーとなります。ただし,相手トランザクションが,そのインデクスキーエントリに対する行データの挿入を終えていなかったときは,相手トランザクションが決着するまで排他待ちします。また,この排他待ちが関係しデッドロックが発生するおそれもあります。デッドロックになるのは,自トランザクションが排他を掛けている排他資源で,相手トランザクションも排他待ちした場合です。
すぐにユニークエラーにしないで,インデクスキーを操作している相手トランザクションの決着を待ってから挿入,又は更新処理を試みるようにしたい場合には,pd_lock_uncommited_delete_dataオペランドにWAITを指定して,コミットしていない削除データに対して排他を行ってください。コミットしていない削除データの排他制御については,「コミットしていない削除データの排他制御」を参照してください。
(b) ユニークインデクスの残存エントリ
インデクスキー値無排他を適用する場合,ユニークインデクスで排他待ち,及びデッドロックが発生することがあります。
インデクスキー値無排他でのユニークインデクスでは,一意性制約保証のためにDELETE文,又はUPDATE文実行前のインデクスキーをインデクス上から削除しないで残すようにしています。この残っているインデクスキーのことを残存エントリといいます。
この残存エントリは,トランザクション決着後の適当なタイミングで削除されますが,残存エントリと同一のキーに対するINSERT文,又はUPDATE文を実行した場合,タイミングによっては予想外に待たされたり,デッドロックが発生したりすることがあります。また,データディクショナリ表にはユニークインデクスが定義されています。定義系SQL文やpdmodを繰り返し実行した場合,タイミングによっては予想外に待たされたり,デッドロックが発生したりすることがあります。
残存エントリによる排他待ちかどうかを判断したい場合,システム共通定義 pd_unique_indexlock_infoオペランドにYを指定してください。残存エントリによる排他待ちのおそれがある場合だけ,排他待ち解除時にKFPH25005-Iメッセージを出力します。タイムアウト情報やデッドロック情報と,KFPH25005-Iメッセージの情報を比較し,次の内容がすべて合致する排他資源が,残存エントリによって排他待ちとなっていたおそれがあります。
-
サーバ名
-
プロセスID
-
資源種別
-
資源情報
残存エントリによる排他待ちかどうかを判断する方法は,マニュアル「HiRDB メッセージ」のKFPH25005-Iのメッセージ内容を参照してください。
残存エントリによる排他待ちの回避策と回避策の選び方を次に示します。
- ●回避策1
-
一意性制約の列を更新しないようにUAPを作成する
回避策1によって,UPDATE文で一意性制約の列を更新する代わりにDELETE文とINSERT文で行の削除と追加をする場合でも,INSERT処理のタイミングによっては残存エントリによる排他待ちが発生するおそれがあります。そのため,回避策1とともに,回避策2の適用も検討してください。
- ●回避策2
-
システム共通定義のpd_dbreuse_remaining_entriesオペランドにALL以外を指定する
残存エントリによる排他待ちが少なくなります。詳細は,「残存エントリによる排他待ちの回避(行識別子の再利用抑止)」を参照してください。
なお,pd_dbreuse_remaining_entriesオペランドの指定値によって,排他待ちの軽減対象が異なります。詳細は,マニュアル「HiRDB システム定義」の「排他制御に関するオペランド」を参照してください。
- ●回避策3
-
システム共通定義のpd_unique_check_modeオペランドに1を指定してユニークチェック用排他による一意性制約保証を使用する
詳細は,「残存エントリによる排他待ちの回避(ユニークチェック用排他使用)」を参照してください。
表3‒24 回避策の選び方 回避策
適用可能なケース
デメリット
回避策1
一意製制約を指定した列を更新しないようにAPを作成・改修できる場合
業務APの設計が限定される。
回避策2
一意製制約を指定した列を更新する回数が少ない場合
更新する回数が多く,1ページで使用スロット数が255を超える場合,残存エントリによる排他待ちを回避できない。
回避策3
OSのメモリに余裕があり,更新により増加する排他資源を取得できる場合
HiRDBが使用する排他資源用プールサイズが増加する。
(c) インデクスキー値無排他を適用しても回避できないデッドロック
UAPのアクセス順序によって,インデクスキーとインデクスキーとでデッドロックが発生することがあります。これを回避するためには,(b)と同様に一意性制約の列を更新しないようにUAPを作成しなければなりません。