03.1資源の逐次化(排他制御)を行う(ENQとDEQ)

By 神居 - Posted: 2008/11/16 Last updated: 2010/10/08 - Leave a Comment

MVSではあらゆるデータを資源(Resource)として扱うことができます。CPU自身、1つのDASDボリューム、1つのデータセット、データセット内の1つのレコード、実行するプログラム・モジュール、仮想記憶上の領域、などプログラムがアクセスできる装置やデータはすべて資源になります。MVSでは同時に複数のプログラムが動くので、同じ資源を扱うプログラムがその内容を同時に書き換えようとすることが起き得ます。これが資源の競合です。MVSでは競合を解決する手段として、資源を順番に使用させる、逐次化(Serialization)と言う制御を行います。プログラムには逐次化を行うためのENQおよびDEQと呼ばれるサービスを提供しています。
競合する資源には名前を付けて管理します。名前はQ名およびR名で構成されます。一般にQ名が資源(データ)の分類名、R名が資源自身の名前となりプログラムで自由に付けることができます。ただしQ名はMVS自身が制御で使用する名前と重複すると混乱するのでSYSで始まる名前を使うべきではありません。MVSはQ名/R名を実際の資源と関連付けることはしません。存在しない資源の名前を付けることも自由です。ただし同じ資源を使うプログラムはすべて同じQ名/R名を使う必要があります。資源には有効範囲がありスコープと呼ばれます。MVSはQ名、R名、スコープの3つが同じであれば、同一資源とみなしFIFOでその使用を1つのタスクにのみ許可します。ENQは資源の使用許可願い、DEQは資源の使用終了連絡となります。


ENQ/DEQの基本的な使い方

アプリケーションっぽいENQ/DEQの例です。マスターファイル内の口座レコードの残高を更新します。マスターファイルから更新対象レコードを読み込み、残高フィールドを更新して書き戻します。レコードを読み込み?書き戻しまでの間、同じレコードが他のプログラムで書き込まれないように排他制御を掛けます。レコードの整合性を保つため、レコードの読み込み前に排他制御を掛けています。

ENQで排他制御を掛け、DEQでそれを解放します。Q名は8バイト固定で内容は任意です。R名は1から255バイトで内容は任意です。スコープはOS内全体(複数のジョブ間で排他制御を行える)を指定しています。ENQマクロに指定したRET=HAVEは、資源が獲れなければ獲れるまで待ち状態に入ることを示します。ENQ/DEQにRETオプションが指定されていると、ENQ/DEQに失敗すると復帰コードで通知されます。GR15が0ならば要求は成功です。失敗した場合、GR15にはENQ/DEQのパラメーターリストのアドレスが格納されます。復帰コードそのものが格納されるわけではないことに注意して下さい。

ENQ/DEQの特徴はロックする資源は実体を伴わない点にあります。Q名とR名はプログラム間で取り決めたものであって、現実に対応する装置、ボリューム、データセットなどの実体の名前との関連付けなどは行われません。またQ名とR名で指定された資源に対し、物理的に参照や更新などのアクセス自体をできなくすることもありません。あくまでもプログラム間で「○○する時はQ名とR名が書かれた札を取ってから行いましょう、札が使われていたら空くまで待ちましょう。」と言うルールを取り決めているだけです。ENQ/DEQはそのルールで使う札のしくみを提供しているようなものです。Q名とR名の札は、単線の鉄道で使われる通票と同じで、それを持っていないと列車を走らせることができません。
関係するプログラムすべてが同じルールを守ることが前提の排他制御なので、掟破りをする者がいれば成り立ちません。ENQを無視してデータセットに書き込みをすればレコードは壊れてしまいます。トランザクションのキューイングやカウンターの更新であれば、ロストしてしまうかも知れません。MVSは排他制御のしくみを提供するだけで、正しい排他制御がなされるかはあくまでもアプリケーションの設計と運用に掛かってきます。
現在はデータベース・システムを使うので、サンプルで示したようなマスターファイルのレコード更新などはデータベース側の排他制御機能を利用することになります。しかし排他制御が必要な資源はデータベースに格納できるデータレコードだけではありません。ENQ/DEQによる資源の逐次化制御はMVSにおける排他制御の基本ですから、必ず理解しておきましょう。


可変長のR名

このサンプルではR名の長さをENQマクロのパラメーターではなく、R名領域の先頭1バイトに設定することで指定しています。この場合ENQマクロではR名長を0としておきます。この指定方法を使えば可変長のR名長に対応できます。なおR名先頭のレングスフィールドはR名には含まれません。
RET=TESTは指定した資源が誰かに使用されているかをテストする目的で使います。仮に誰も資源を使用していなくても実際にENQされることはありません。スコープはシステム全体(複数のOS間で排他制御を行える)を指定しています。SYSTEMS ENQでは各々のシステムのENQ要求はGRSによって変換・管理され、各々のシステムのGRSは互いのENQ要求をCTCやXCFを介して調整し合います。
サンプルで示したQ名とR名はISPFエディターが編集中のPDSメンバーをロックするためのものです。復帰コードが0でなければそのメンバーは誰かがISPFエディターで編集中ということになります。


複数資源の同時排他制御

複数のリソースを同時にENQすることもできます。サンプルのようにQ名,R名,タイプ,R名長,スコープの対を順番に指定します。RETパラメーターを省略しているので、指定したすべての資源の排他制御が獲れるまでプログラムには戻ってきません。二重ENQなどのプログラムミスがあった場合はABENDさせられます。二重ENQは運用上は問題がなくてもプログラムに誤りがあることには変わりません。ABENDを嫌ってRET=HAVEやRET=USEにすることは多いのですが、その場合は復帰コード8で通知されます。このコードを判定してエラー処理をしなければ二重ENQがあっても潜在化されてしまいます。

アプリケーションなどで1つの処理を行うために複数の資源を持つことはあり得ることです。この場合資源を獲得する順番はとても重要です。AとBの2つの資源がある時、PGM1はA→Bの順番で資源を確保し、PGM2はB→Aの順番で資源を確保しようとします。PGM1がA、PGM2がBの資源を持った状態でお互いが自分が持っていない資源を獲りに行きます。しかしその資源はすでに相手が持ってしまっていますから獲ることができません。このような状態がデッドロックです。これを防ぐ方法として必要な資源を確保する順番を決めると言うのがあります。PGM2もA→Bの順番で資源を確保すれば、Aの確保の時点で実行が止まり、BはENQされないのでデッドロックになりません。もう1つの方法は複数の資源を順番ではなく一度に全部確保することです。ENQ/DEQマクロで複数のリソースが指定できるのは後者の方法をサポートするためです。


データセットの排他制御

RETパラメーターにUSEを指定すると、指定した資源が他のタスクやジョブで使用されている場合、ENQサービス内で待ちになることなく、すぐにプログラムに制御が戻ります。復帰コードが4であれば資源の排他制御は確保されていません。リソースが空いたかどうかは自分で確認のロジックを作成する必要があります。またENQ資源はタスク単位に管理されます。ENQとDEQは同じタスクで発行しなければなりません。

このサンプルはJCLのDD文に定義されたデータセットと同じENQを発行しています。イニシエーターはDD文に定義されたデータセットを排他制御するためにENQを使います。Q名=SYSDSN、R名=データセット名、R名長=実際のデータセット名の長さ、SCOPE=SYSTEMです。DISP=SHRの場合は共用制御のS、SHRでなければ排他制御のEが指定されます。サンプルでは指定したDSNでJCLのDD文と同じENQを発行します。資源が獲得できたら20秒間WAITします。20秒後に起き上がり獲得した資源を解放します。このサンプルを実際に実行した場合、実行後20秒以内に以下のようなDD文を持つJCLをサブミットすれば、「JOB ???????? WAITING FOR DATA SETS」のメッセージを出して、データセットが使用可能になるまで実行開始が延期されるはずです。

SYSで始まるQ名のうち、MVSが制御のために使用するものは一般のプログラムでは使用できません。使用するためには最低でもAPF許可を受けていなければなりません。APF許可されていないプログラムではENQマクロ発行時にABENDS338してしまいます。MVSの各コンポーネントがどのようなQ名、R名でENQを行っているかはマニュアル(診断の解説書)にも載っています。
APF許可を受けたプログラムであれば、すぐに資源が利用できないとき、資源が使用できるようになったらECBに通知してもらったり、異なるタスクの資源をDEQしたりなど、制御プログラム用の機能を利用することができます。

この記事で解説したENQ/DEQに関する機能はMSPもVOS3も共通です。

Posted in .基礎編 • • Top Of Page