3.9.1 資源の排他制御
OpenTP1では,複数のユーザがDAMファイルやTAMファイル以外の資源も共用できるようにしています。資源を管理して整合性を保つことができる機能を排他制御といいます。排他資源の占有,および待ち状態はlcklsコマンドで表示できます。
(1) 排他制御の管理単位と有効範囲
OpenTP1は,資源の排他要求時から排他資源の解放要求時まで排他を管理します。排他制御の管理単位は,グローバルトランザクションです。ただし,DAMサービスが使用する排他制御機能の管理単位は,トランザクションブランチです。
排他制御の有効範囲は,一つのOpenTP1システム内だけです。ほかのOpenTP1システム上のUAPとの排他制御はできません。また,複数のノードから構成される一つのOpenTP1システム内でも,ノード間の排他制御はできません。
(2) 資源の排他要求
資源を確保するときは,UAPからdc_lck_get関数を呼び出します。このとき,引数に資源名称と排他制御モードを指定します。排他制御モードとは,同じ資源にアクセスするほかのUAPに対する排他の方式です。
排他制御モードには,資源を参照するだけのUAPとは資源を共用し,資源を更新するUAPだけを排他するPRモードと,一つのUAPが資源を占有し,ほかのUAPをすべて排他するEXモードがあります。
排他制御モードを次の表に示します。
排他制御モード |
資源の処理 |
排他の内容 |
---|---|---|
PR |
参照 |
ほかのUAPに対して,参照だけを許可します。 |
EX |
更新 |
ほかのUAPに対しては,参照,更新を許可しません。 |
排他制御モードの組み合わせによる資源の共用を次の表に示します。
使用中の排他制御モード |
要求元の排他制御モード |
|
---|---|---|
PR |
EX |
|
PR |
○ |
× |
EX |
× |
× |
(3) 資源の解放
ユーザは,次に示す方法で資源を解放します。
-
資源名称ごとの排他解除要求をUAPが出す
-
全資源の一括排他解除要求をUAPが出す
また,トランザクションの終了時に,システムが全資源を自動的に解放します。
これによって,UAPでの解放漏れや,UAP異常終了が発生した場合でも,資源が不当に占有されることがなくなります。
(4) 排他待ち
資源を排他できない場合,資源を排他できるまで待つかどうか,dc_lck_get関数の引数で指定します。排他待ちするのは,次の場合です。
-
排他要求したときに,ほかのUAPがすでにEXモードで資源に排他をかけている場合
-
排他要求したときに,ほかのUAPがすでにPRモードで資源に排他をかけていて,かつ自UAPでEXモードの排他をかける場合
資源が解放されるまで待つと指定した場合には,排他待ちの優先順位に従って,ほかのUAPが資源の排他を解除するまで待ちます。待たないと指定した場合は,すぐにエラーリターンします。排他待ちの優先順位は,ユーザサービス定義でUAPのサービスグループごとに定義します。優先順位を高く設定すれば,排他待ちしている,優先順位の低いほかのUAPよりも先に資源を排他できます。逆に,優先順位を低く設定したUAPは,あとから排他要求した優先順位の高いUAPに追い越されることがあるので,排他待ちの優先順位の設定には注意が必要です。排他待ちの優先順位と排他順序を次の図に示します。
ロックサービス定義で排他待ち限界経過時間を指定すると,排他待ち状態がこの時間を超えたとき,その排他要求をエラーリターンします。
(5) デッドロックの対処方法
複数のUAPが複数の資源に対して異なる順番で排他要求を行った場合,それぞれのUAPが相手の占有する資源の排他解除を互いに待ち続けて,処理が止まってしまう場合があります(デッドロック)。
OpenTP1は,デッドロック状態を検出して速やかに解消するため,定期的にデッドロック状態になっているかどうかを監視しています。
同一ノード内のUAP間では,定期的に排他待ち状態を監視してデッドロックを検知します。
異なるノードのUAPにRPCでサービス要求して,そのサービスとの間でデッドロックが起こっても,検知できません。そのため排他待ち時間監視をする必要があります。排他待ち限界経過時間は,ロックサービス定義で指定します。
デッドロックの例を次の図に示します。
(a) デッドロック時のOpenTP1の処置
デッドロックが起こった場合,OpenTP1はUAPの排他待ち優先順位に従って,優先順位の低いUAPプロセスからの排他要求をエラーリターンさせます。UAPの排他待ち優先順位は,ユーザサービス定義のdeadlock_priorityオペランドに指定します。
デッドロックによって,資源を確保しようとした関数がエラーリターンした場合,UAPでは次のように対処してください。
-
SUP,SPPのデッドロック時の処置
SUP,またはSPPの処理でデッドロックが起こった場合は,dc_trn_unchained_rollback関数,dc_trn_chained_rollback関数などロールバックする関数で,トランザクションをロールバックさせてください。デッドロックでロールバックしたSUP,または SPPは再実行(リトライ)しません。もう一度該当するサービスをクライアントUAPから要求し直してください。
-
MHPのデッドロック時の処置
MHPの処理でデッドロックが起こった場合は,dc_mcf_rollback関数でロールバックしてください。再実行(リトライ)するかどうかは,dc_mcf_rollback関数の引数に指定します。
(b) デッドロック情報,タイムアウト情報の出力
デッドロックが起こった場合,デッドロックの原因となったUAPの詳細情報を,ロックサービスがあるノードのディレクトリに出力できます。この情報をデッドロック情報といいます。
資源の解放を待っているUAPが,ロックサービス定義のlck_wait_timeoutオペランドに指定した時間を超えた場合,UAPから呼び出した関数はエラーリターンします。このとき,確保しようとした資源に関する詳細情報を,ロックサービスがあるノードのディレクトリに出力できます。この情報をタイムアウト情報といいます。
デッドロック情報,タイムアウト情報を出力するかどうかは,ロックサービス定義のlck_deadlock_infoオペランドに指定します。
デッドロック情報,タイムアウト情報の出力形式については,マニュアル「OpenTP1 プログラム作成の手引」を参照してください。
取得したデッドロック情報,タイムアウト情報は削除できます。情報を削除する方法を次に示します。
-
コマンドで削除する方法
lckrminfコマンドを実行します。
-
OpenTP1の開始時に,前回までのオンラインで作成した情報を削除する方法
ロックサービス定義のlck_deadlock_info_remove_levelオペランドに,削除する条件を指定しておきます。