2.9.10 コミットしていない削除データの排他制御
次のどちらかの操作をする場合,SDBデータベースを操作するAPIまたはDML(ERASEまたはMODIFY)でレコードを削除または更新するほかのトランザクションと競合することがあります。このとき,インデクス上で削除レコードのインデクスキー,または更新レコードの更新前インデクスキーを読み飛ばします。そのため,通常は,削除レコードまたは更新レコードを検索できません。
-
SDBデータベースを操作するAPIまたはDML(FETCH,FIND,またはFETCHDB ALL)で,4V FMBまたはSD FMBのSDBデータベースのルートレコードを検索する
-
SDBデータベースを操作するDML(FETCH,またはFIND)で,二次インデクスを使用し,SD FMBのSDBデータベースの子レコードを検索する
しかし,レコードを削除または更新したトランザクションがロールバックした場合,そのレコードの内容が回復されるため,検索トランザクションでは,結果的にそのレコードを読み飛ばしたことになります。
この問題は,検索トランザクションで削除中のレコードのインデクスキー,または更新中のレコードの更新前インデクスキーを参照したときに,レコード格納ページ(コミットしていない削除データ)に排他を掛けることで回避できます。
(1) 適用基準
次のどちらかの場合に,コミットしていない削除データに排他を掛けることを推奨します。それ以外の場合は,コミットしていない削除データに排他を掛けない運用を推奨します。
-
4V FMBまたはSD FMBのSDBデータベースに対して,次のSDBデータベースを操作するAPIまたはDMLを同時実行する可能性があり,検索トランザクションで削除中または更新中のルートレコードを読み飛ばすことができない業務がある場合
-
ルートレコードを削除対象とするレコードの削除(ERASE),または二次インデクスキーを更新対象とするルートレコードの更新(MODIFY)
-
レコードの検索(FETCH),位置指示子の位置づけ(FIND),または複数レコードの検索(FETCHDB ALL)
-
-
SD FMBのSDBデータベースに対して,次のDMLを同時実行する可能性があり,検索トランザクションで削除中または更新中の子レコードを読み飛ばすことができない業務がある場合
-
子レコードを削除対象とするレコードの削除(ERASE),または二次インデクスキーを更新対象とする子レコードの更新(MODIFY)
-
二次インデクスを使用して子レコードを検索対象とするレコードの検索(FETCH),または二次インデクスを使用して子レコードを走査対象とする位置指示子の位置づけ(FIND)
-
(2) 指定方法
システム共通定義のpd_lock_uncommited_delete_dataオペランドにWAITを指定すると,コミットしていない削除データに排他を掛けることができます。詳細については,マニュアル「HiRDB システム定義」のpd_lock_uncommited_delete_dataオペランドの説明を参照してください。pd_lock_uncommited_delete_dataオペランドの説明を参照する際の注意点を次に示します。
-
「DELETE文」を「SDBデータベースを操作するAPI(ERASE)によるレコードの削除」,または「DML(ERASE)によるレコードの削除」に読み替えてください。
-
「UPDATE文」を「SDBデータベースを操作するAPI(MODIFY)によるレコードの更新」,または「DML(MODIFY)によるレコードの更新」に読み替えてください。
-
このオペランドの指定に関係なく,「一意性制約」に関しては「2.9.11 重複するインデクスキー値を格納する際の実行中トランザクション終了待ち合わせ【4V FMB,SD FMB】」を参照してください。
なお,HiRDB/SDが内部的に発行する,4V AFMのSDBデータベースの仮想ルートレコードの検索では,このオペランドの指定値に関係なく,WAITが指定されたものとして動作します。このオペランドにNOWAIT(省略値)を指定して4V AFMのSDBデータベースを操作する場合,マニュアル「HiRDB システム定義」のpd_lock_uncommited_delete_dataオペランドの説明に記載されているHiRDBファイルの使用可能サイズの制限はありません。
(3) コミットしていない削除データに排他を掛けた場合の効果
コミットしていない削除データに排他を掛けた場合の効果を次に示します。
-
4V FMBまたはSD FMBのSDBデータベースのルートレコードを検索中に,コミットする前の削除データまたは更新前のインデクスキーを検知した場合,検索トランザクションは,削除または更新トランザクションのコミットまたはロールバックの決着を待ってから検索処理を行います。これによって,削除または更新トランザクションでロールバックが発生した場合でも,検索トランザクションからの検索読み飛ばしを防止します。
-
二次インデクスを使用して,SD FMBのSDBデータベースの子レコードを検索中に,コミットする前の削除データまたは更新前のインデクスキーを検知した場合,検索トランザクションは,削除または更新トランザクションのコミットまたはロールバックの決着を待ってから検索処理を行います。これによって,削除または更新トランザクションでロールバックが発生した場合でも,検索トランザクションからの検索読み飛ばしを防止します。
(4) インデクス検索時の排他制御
システム共通定義のpd_lock_uncommited_delete_dataオペランドにWAITを指定した場合,インデクス検索時に削除中または削除済みのレコードを格納していたページにも排他を掛けます。
pd_lock_uncommited_delete_dataオペランドにWAITを指定した場合と,NOWAIT(省略値)を指定した場合のインデクス検索の動作の違いを次の図に示します。
- 注
-
上記の図は,削除中のレコードのインデクスキーを検索する例です。更新中のレコードの更新前のインデクスキーを検索する場合も,インデクス検索の動作は上記の図と同じ流れになります。
- 注※1
-
削除中または削除済みのレコードのインデクスキーも含みます。
- 注※2
-
排他制御モードについては,次の個所を参照してください。
- 注※3
-
削除中または削除済みのレコードのインデクスキーは含みません。
- 注※4
-
排他待ちが発生した場合に削除されていることがあります。
(5) 注意事項
(a) インデクスの残存エントリ
SDBデータベースを操作するAPIまたはDMLで次のどちらかの操作を行った場合,インデクスキーエントリは削除されません。残存エントリとしてインデクス内に残ります。
-
レコードの削除(ERASE)によって,インデクスが定義されたレコード型のレコードを削除した場合(この場合,削除レコードのインデクスキーエントリが残存エントリとして残ります)
-
レコードの削除(ERASE)またはレコードの一括削除によって,仮想ルートレコード配下の子レコードをすべて削除した場合(この場合,仮想ルートレコードのシステム用構成要素がX'0000'のインデクスキーエントリが残存エントリとして残ります)
-
レコードの更新(MODIFY)によって,インデクスが定義された構成要素を更新した場合(この場合,更新レコードの更新前のインデクスキーエントリが残存エントリとして残ります)
インデクスの残存エントリの注意事項については,マニュアル「HiRDB UAP開発ガイド」の「コミットしていない削除データの排他制御」のインデクスの残存エントリの注意事項を参照してください。インデクスの残存エントリの注意事項を参照する際の注意点を次に示します。
-
残存エントリの発生条件については,前述したとおりです。
-
「pdrorg」を「pdsdbrogおよびpdsdblod」に読み替えてください。
-
回避策2はSDBデータベースには適用できないため,無視してください。
-
「表の残存エントリ」の説明は無視してください。