2.9.9 デッドロック
2つのトランザクションが2つ以上の資源の確保をめぐって互いに相手を待つ状態となり,そこから先へ処理が進まなくなることをデッドロックといいます。
詳細については,マニュアル「HiRDB UAP開発ガイド」の「デッドロックと回避策」を参照してください。
デッドロックの例を次に示します。
- 〈この項の構成〉
(1) ルートレコードを格納しているページ間のデッドロックの例
4V FMBまたはSD FMBのSDBデータベースでは,2つのトランザクションが複数のルートレコードに対して同時に逆順にアクセスした場合,デッドロックが発生するおそれがあります。次に示す場合にも同様にデッドロックが発生するおそれがあります。
-
4V AFMのSDBデータベースで,異なる仮想ルートレコード下の子レコードを逆順にアクセスした場合
-
SD FMBのSDBデータベースに対して,二次インデクスを使用し,ファミリが異なる複数の子レコードを逆順にアクセスした場合
複数のルートレコードを逆順にアクセスした場合のデッドロックの例を,次の図に示します。
- [説明]
-
-
参照トランザクションがルートレコードAの格納ページにSRモードで排他を掛けて,レコードを参照します。
-
更新トランザクションがルートレコードBの格納ページにEXモードで排他を掛けて,レコードを更新します。
-
参照トランザクションがルートレコードBの格納ページにSRモードで排他を掛けようとしますが,更新トランザクションがEXモードで排他を掛けているため,ページの排他解除待ちとなります。
-
更新トランザクションがルートレコードAの格納ページにEXモードで排他を掛けようとしますが,参照トランザクションがSRモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
ここでは,同一のレコード型内の複数のルートレコードに対する例を挙げましたが,レコード型が異なる複数のルートレコードを逆順にアクセスした場合にもデッドロックが発生するおそれがあります。
(2) 子レコードを格納しているページ間のデッドロックの例【4V AFM,SD FMB】
4V AFMのSDBデータベースでは,2つのトランザクションが複数のデータベースキー値のレコードを同時に逆順にアクセスした場合,デッドロックが発生するおそれがあります。
SD FMBのSDBデータベースでは,二次インデクスを使用して子レコードを検索する場合,子レコードを逆順にアクセスすると,子レコード格納ページ間で,デッドロックが発生するおそれがあります。
デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,複数のデータベースキー値のレコードを逆順にアクセスした場合のデッドロックの例です。
-
参照トランザクションがデータベースキー値A(1)のレコードの格納ページにSRモードで排他を掛けて,レコードを参照します。
-
更新トランザクションがデータベースキー値A(2)のレコードの格納ページにEXモードで排他を掛けて,レコードを更新します。
-
参照トランザクションがデータベースキー値A(2)のレコードの格納ページにSRモードで排他を掛けようとしますが,更新トランザクションがEXモードで排他を掛けているため,ページの排他解除待ちとなります。
-
更新トランザクションがデータベースキー値A(1)のレコードの格納ページにEXモードで排他を掛けようとしますが,参照トランザクションがSRモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
ここでは,同一のレコード型内の複数のデータベースキー値に対する例を挙げましたが,レコード型が異なる複数のデータベースキー値のレコードを逆順にアクセスした場合もデッドロックが発生するおそれがあります。
なお,4V AFMのSDBデータベースのレコードの格納時には,格納位置を決めるために発生する検索の方向を指定する検索コードに従って子レコードの挿入位置を検索します。HiRDB/SDは指定された検索コードによってレコード間をNEXT方向またはPRIOR方向に,子レコードが格納されているページに順次アクセスする場合があります。このように直接子レコードを操作しなくても,上記のデッドロックが発生するおそれがあるため,検索方向にも注意してください。
(3) 仮想ルートレコードを格納しているページと子レコードを格納しているページ間のデッドロックの例【4V AFM】
4V AFMのSDBデータベースに対するアクセスでは,HiRDB/SDが内部的に仮想ルートレコードにアクセスすることがあるため,仮想ルートレコードを格納しているページと子レコードを格納しているページとの間でデッドロックが発生するおそれがあります。デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,仮想ルートレコードを格納しているページと子レコードを格納しているページ間のデッドロックの例です。
-
トランザクション1が,データベースキー値A(1)を参照するため,仮想ルートレコードの格納ページにSRモードで排他を掛けます。
-
トランザクション1が,データベースキー値A(1)を参照するため,子レコードの格納ページにPUモードで排他を掛けて,子レコードを参照します。
-
トランザクション2が,データベースキー値A(1)を参照するため,仮想ルートレコードの格納ページにSRモードで排他を掛けます。
-
トランザクション1が,データベースキー値A(1)を削除するため,仮想ルートレコードの格納ページにEXモードで排他を掛けようとしますが,トランザクション2がSRモードで排他を掛けているため,ページの排他解除待ちとなります。
-
トランザクション2が,データベースキー値A(1)を参照するため,子レコードの格納ページにPUモードで排他を掛けようとしますが,トランザクション1がPUモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
ここでは,レコードの削除とレコードの検索が競合した場合の例を挙げましたが,このほかにも次のSDBデータベースを操作するAPIの競合時にも同じようにデッドロックが発生するおそれがあります。
-
レコードの削除とレコードの格納
-
レコードの削除とレコードの削除
また,異なるレコード型の間(例えば,4V FMBのSDBデータベースのルートレコードを格納しているページと,4V AFMのSDBデータベースの子レコードを格納しているページの間)でも,同じようにデッドロックが発生するおそれがあります。
(4) ルートレコードを格納しているページと子レコードを格納しているページ間のデッドロックの例【4V FMB,SD FMB】
次のどちらかの条件で,ルートレコードの検索またはルートレコードの位置指示子の位置づけを実行すると,その後の子レコードの更新,格納,または削除の際,ルートレコード格納ページと子レコード格納ページとの間でデッドロックが発生するおそれがあります。
-
SDBデータベース種別が4V FMBのSDBデータベースで,かつ排他オプションが占有モード以外である。
-
SDBデータベース種別がSD FMBのSDBデータベースで,かつSDB用UAP環境定義のsubschemaオペランドの-pオプションにsharerootを指定している。
また,SD FMBのSDBデータベースでは,二次インデクスを使用して子レコードを検索する場合,子レコードを逆順にアクセスするときも,ルートレコード格納ページと子レコード格納ページ間で,デッドロックが発生するおそれがあります。
デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,ルートレコードを格納しているページと子レコードを格納しているページ間のデッドロックの例です。
-
トランザクション1が,データベースキー値Aを参照するため,ルートレコードの格納ページにSRモードで排他を掛けて,ルートレコードを参照します。
-
トランザクション1が,データベースキー値A(1)を参照するため,子レコードの格納ページにPUモードで排他を掛けて,子レコードを参照します。
-
トランザクション2が,データベースキー値Aを参照するため,ルートレコードの格納ページにSRモードで排他を掛けて,ルートレコードを参照します。
-
トランザクション2が,データベースキー値A(1)を参照するため,子レコードの格納ページにPUモードで排他を掛けようとしますが,トランザクション1がPUモードで排他を掛けているため,ページの排他解除待ちとなります。
-
トランザクション1が,データベースキー値A(1)を削除するため,ルートレコードの格納ページにEXモードで排他を掛けようとしますが,トランザクション2がSRモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
(5) 排他モード1の指定が異なる検索が混在するトランザクションと,ほかのトランザクションが同じレコードに対してアクセスした場合のデッドロックの例【4V FMB,4V AFM】
4V FMBまたは4V AFMのSDBデータベースでは,SDBデータベースを操作するAPIの,排他モード1の指定が異なる検索が混在するトランザクションと,ほかのトランザクションが同じレコードに対してアクセスした場合,デッドロックが発生するおそれがあります。デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,排他モード1の指定が異なる検索が混在するトランザクションと,ほかのトランザクションが同じレコード(同じページ)に対してアクセスした場合の,デッドロックの例です。
-
トランザクション1(個別開始X)が,データベースキー値Aを参照するため,レコードの格納ページにSRモードで排他を掛けます。
-
トランザクション1(個別開始X)が,個別終了を行います(個別終了処理では排他制御は行いません)。
-
トランザクション2が,データベースキー値Aを参照するため,レコードの格納ページにPUモードで排他を掛けます。
-
トランザクション2が,データベースキー値Aを更新するため,レコードの格納ページにEXモードで排他を掛けようとしますが,トランザクション1(個別開始X)がSRモードで排他を掛けているため,ページの排他解除待ちとなります。
-
トランザクション1(個別開始Y)が,データベースキー値Aを参照するため,レコードの格納ページにPUモードで排他を掛けようとしますが,トランザクション2がPUモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
ここでは,同じページに格納された同じレコードに対するアクセスが競合した場合の例を挙げましたが,このほかに次の場合にも,同じようにデッドロックが発生するおそれがあります。
-
同じページに格納された異なるレコードに対するアクセス
-
異なるページ間でのアクセス
(6) FOR UPDATEオペランドの指定の有無が異なる検索が混在するトランザクションと,ほかのトランザクションが同じレコードに対してアクセスした場合のデッドロックの例【SD FMB】
SD FMBのSDBデータベースでは,FOR UPDATEオペランドの指定の有無が異なる検索が混在するトランザクションと,ほかのトランザクションが,同じレコードに対してアクセスをすると,デッドロックが発生するおそれがあります。デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,FOR UPDATEオペランドの指定の有無が異なる検索が混在するトランザクションと,ほかのトランザクションが,同じレコード(同じページ)に対してアクセスした場合の,デッドロックの例です。
-
トランザクション1が,参照目的(FOR UPDATEオペランドの指定なし)でルートレコードAを参照するため,レコードの格納ページにSRモードで排他を掛けます。
-
トランザクション2が,更新目的(FOR UPDATEオペランドの指定あり)でルートレコードAを参照するため,レコードの格納ページにPUモードで排他を掛けます。
-
トランザクション1が,更新目的(FOR UPDATEオペランドの指定あり)でルートレコードAを参照するため,レコードの格納ページにPUモードで排他を掛けようとしますが,トランザクション2がPUモードで排他を掛けているため,ページの排他解除待ちとなります。
-
トランザクション2が,ルートレコードAを更新するため,レコードの格納ページにEXモードで排他を掛けようとしますが,トランザクション1がSRモードで排他を掛けているため,ページの排他解除待ちとなり,デッドロックが検知されます。
-
ここでは,同じページに格納された同じレコードに対するアクセスが競合した場合の例を挙げましたが,このほかに次の場合にも,同じようにデッドロックが発生するおそれがあります。
-
同じページに格納された異なるレコードに対するアクセス
-
異なるページ間でのアクセス
(7) レコード格納用RDエリア間のデッドロックの例【SD FMB】
SD FMBのSDBデータベースでは,「表2-38 同一レコード格納用RDエリアに対する,SDBデータベースへのアクセスの同時実行可否(SD FMBのSDBデータベースの場合)」で説明しているように,レコード格納用RDエリアの排他によって待ち状態になることがあります。そのため,レコード格納用RDエリアにPRモード,PUモード,またはEXモードで排他を掛けるトランザクションと,ほかのトランザクションが,複数のレコード格納用RDエリアに対して同時に逆順にアクセスした場合,デッドロックが発生するおそれがあります。デッドロックの例を次の図に示します。
- [説明]
-
上記の図は,複数のレコード格納用RDエリアに逆順にアクセスした場合の,レコード格納用RDエリア間のデッドロックの例です。
-
トランザクション1(SD排他モード:exclusive,アクセス目的:retrieve)が,ルートレコードAを参照するため,レコード格納用RDエリア1にEXモードで排他を掛けます。
-
トランザクション2(SD排他モード:shared,アクセス目的:retrieve)が,ルートレコードBを参照するため,レコード格納用RDエリア2にSRモードで排他を掛けます。
-
トランザクション1(SD排他モード:exclusive,アクセス目的:retrieve)が,ルートレコードBを参照するため,レコード格納用RDエリア2にEXモードで排他を掛けようとしますが,トランザクション2がSRモードで排他を掛けているため,レコード格納用RDエリアの排他解除待ちとなります。
-
トランザクション2(SD排他モード:shared,アクセス目的:retrieve)が,ルートレコードAを参照するため,レコード格納用RDエリア1にSRモードで排他を掛けようとしますが,トランザクション1がEXモードで排他を掛けているため,レコード格納用RD エリアの排他解除待ちとなり,デッドロックが検知されます。
-
(8) デッドロックプライオリティ値による排他制御
デッドロックが発生した場合,どのトランザクションをエラーとするかをデッドロックプライオリティ値で制御できます。
この機能を使用する場合,システム共通定義のpd_deadlock_priority_useオペランドにYを指定してください。クライアント環境定義などからプログラム単位にHiRDB/SDがデッドロック優先順位を決定します。
デッドロックプライオリティ値が小さい方が処理の優先度が高く,値が大きくなるほどエラーになってロールバックされる可能性が高くなります。値が同じときは,後発のトランザクションの方がエラーとなって暗黙的にロールバックされます。
なお,この機能を使用しない場合は,後発のトランザクションがエラーとなり,暗黙的にロールバックされます。
(9) デッドロックの回避策
デッドロックは排他の範囲を広くすることで発生頻度を低減できますが,同時実行性は低下します。排他の範囲を狭くすると同時実行性は向上しますが,デッドロックの発生率が増加します。
デッドロックを回避するために,例えば次のような対策があります。
-
2つ以上のレコード型のレコードにアクセスする場合,またはSD FMBのSDBデータベースで2つ以上のレコード格納用RDエリアにアクセスする場合,アクセス順序を統一します。また,A,Bの順でアクセスした場合,再度Aをアクセスしないようにします(Aの値は保存しておきます)。
-
SD FMBのSDBデータベースの場合で,2つ以上のレコード格納用RDエリアにアクセスするときは,SDB用UAP環境定義のsubschemaオペランドの-eオプション(SD排他モード)にsharedを指定します。
-
2つ以上のルートレコード(4V AFMのSDBデータベースの場合,データベースキー値のレコード)にアクセスする場合,アクセス順序を統一します。また,A→Bの順でアクセスしたら,再度Aはアクセスしないようにします(Aの値は保存しておきます)。
検索の方向※を指定する検索コードに,NEXT方向の検索とPRIOR方向の検索が混在している場合,アクセス順序が統一されていないため,混在しないように指定します。
- 注※
-
レコードの検索(FETCH)では,検索する方向のことです。レコードの格納(STORE)では,格納位置を決定するための検索の方向のことです。
-
検索トランザクションの場合,排他自動解除機能を使用すると,排他保持期間を短くできるため,排他待ちの発生を低減できます。
排他自動解除機能については,「2.9.4 排他自動解除機能」を参照してください。
-
SDBデータベース格納定義でSUBPAGE NUMBER句を指定し,サブページ分割機能を適用します。サブページ分割をすると,複数レコードを異なる排他資源(サブページ)に格納できるため,排他待ちの発生を低減できます。
-
検索時のSDBデータベースを操作するAPIの,排他モード1の指定を'O'(占有モード)に変更します。同時実行性は低下しますが,SDBデータベース定義でのSUBPAGE NUMBER句の指定の変更やSDBデータベースを操作するAPIの実行順序の変更をすることなく,デッドロックの発生率を低下させることができます。
-
SD FMBのSDBデータベースの場合,検索時にFOR UPDATEオペランドを指定します。同時実行性は低下しますが,SDBデータベース定義でのSUBPAGE NUMBER句の指定の変更や,DMLの実行順序の変更をしなくても,デッドロックの発生率を低下させることができます。
-
業務要件に適合する場合,次のように無排他検索を適用してください。これによって,SDBデータベースを操作するAPIまたはDMLの実行順序を変更することなく,デッドロックの発生率を低下させることができます。
-
SDBデータベースを操作するAPIの排他モード1の指定値を'N'(無排他モード)に変更する。
-
操作対象が4V TAMのSDBデータベースの場合,TAMのデータベースの無排他検索機能を適用する。
-
操作対象がSD FMBのSDBデータベースの場合,SDB用UAP環境定義のsubschemaオペランドの-eオプション(SD排他モード)にnonprotectedを指定する。
-
-
子レコードを更新,格納,または削除する場合,ルートレコードの検索では次のように指定します。
-
操作対象が4V FMBのSDBデータベースの場合,SDBデータベースを操作するAPIの排他モード1の指定値を'O'(占有モード)に変更する。
-
操作対象がSD FMBのSDBデータベースの場合,SDB用UAP環境定義のsubschemaオペランドの-pオプションを指定しない。
-
デッドロックが発生する原因と対策を次の表に示します。
排他資源 |
発生原因 |
対策 |
|
---|---|---|---|
レコード型とレコード型 |
レコード型のアクセス順序の不定 |
|
|
レコード格納用RDエリア(SD FMBのSDBデータベースの場合) |
レコード格納用RDエリアのアクセス順序の不定 |
|
|
ページ |
複数ページ |
|
|
子レコードの更新,格納,削除 |
|
||
SD FMBのSDBデータベースの,二次インデクスを使用した子レコードの検索 |
|
||
単一ページ※1 |
■4V FMBまたは4V AFMのSDBデータベースの場合 同一トランザクション内で,同一ページに対する検索を,次の順序で実行※2する。
|
|
|
■SD FMBのSDBデータベースの場合 同一トランザクション内で,同一ページに対する検索を,次の順序で実行する。
|
|
デッドロックが発生すると,自動的にHiRDB/SDがデッドロックとなったトランザクションのどれかをエラーにしてロールバックさせます。デッドロックによって暗黙的にロールバックされたUAPは,ROLLBACK文,またはDISCONNECT文でトランザクションを終了させないと,SDBデータベースを操作するAPIを実行してもエラーとなります。また,OLTP環境でX/Openに従ったアプリケーションプログラムをクライアントとした場合に,実行したアプリケーションプログラムがデッドロックとなったときもトランザクションの終了が必要です。
なお,デッドロック発生時にデッドロック情報を出力したい場合,システム共通定義またはユニット制御情報定義のpd_lck_deadlock_infoオペランドにYを指定する必要があります。pd_lck_deadlock_infoオペランドについては,マニュアル「HiRDB システム定義」を参照してください。