【実務・中級編】 アクセス権限制御(PROCOPT) – 階層型DBMS

PROCOPTの魔力:なぜ階層型DBMSのアクセス制御はセグメント単位でなければならないのか

こんにちは。チーフアーキテクトの私だ。
今日のコードレビュー、あるいは基本設計レビューで、また「とりあえず全セグメントに `PROCOPT=G,R,I,D` を付与しました」という若手の手による爆弾を見つけてしまった。

――おいおい、待て。
現代のリレーショナルデータベース(RDBMS)のテーブル単位、あるいはカラム単位のGRANT文に毒された脳みそで、IBMのIMSに代表される階層型DBMS(Hierarchical DBMS)の設計に挑むと、本番稼働後に必ずシステムを焼き払うことになると何度も言っているはずだ。

階層型DBMSにおけるアクセス権限制御、すなわち PCB(Program Communication Block)定義における `PROCOPT`(Processing Options)パラメータ は、単なるセキュリティの「お題目」ではない。これは、アプリケーションの生存領域を定義し、データ整合性を物理レベルで担保するための極限の防壁なのだ。

今回は、この `PROCOPT` の本質と、実務の現場で絶対に守るべき堅牢な設計パターンをロジカルかつシャープに伝授しよう。

—

1. PROCOPTの基本:なぜ「セグメント単位」なのか

RDBMSの権限管理は「表(Table)」単位が基本だ。しかし、階層型DBMSのデータ構造は、親子関係がツリー状に絡み合う。
例えば、以下のような典型的な購買システムを考えてみよう。

  • `CUSTOMER`(顧客セグメント)
  • `ORDER`(注文セグメント)
  • `ITEM`(明細セグメント)

ここで、あるバッチプログラムに要求された要件は「顧客ごとの注文情報の集計(参照のみ)」だとしよう。この時、もしプログラムのバグや、悪意ある(あるいは無知な)コードによって、誤って `ITEM` セグメントを削除(D)したり、`ORDER` セグメントを挿入(I)したりしたらどうなるか? ツリー全体が破壊され、整合性は一瞬で崩壊する。

ここで登場するのが `PROCOPT` だ。
`PROCOPT` は、アプリケーション(PCB)ごとに、どのセグメントに対して、どの操作(G, R, I, D)を許可するかを厳密に制限する。

主要なプロセッシング・オプションの復習

  • `G` (Get): セグメントの取得・読み取り(GN, GU, GHN, GHUなど)
  • `R` (Replace): 既存セグメントの更新(REPL)
  • `I` (Insert): 新規セグメントの挿入(ISRT)
  • `D` (Delete): セグメントの削除(DLET)

これらをセグメント階層ごとにマッピングするのが、DBD(Database Description)とPSB(Program Specification Block)の職人芸である。

—

2. 実務コードレビュー:危ういPSB定義と正しい設計

実際のPSBGEN(PSB生成マクロ)の定義を見てみよう。
まずは、レビューで即座にリジェクトした「典型的なアンチパターン」だ。

❌ アンチパターン:全権限の無差別付与

  • — 危険なPSB定義例 —

PCB TYPE=DB,DBD=CUSTDB,PROCOPT=A
SENSEG NAME=CUSTOMER,PARENT=0
SENSEG NAME=ORDER,PARENT=CUSTOMER
SENSEG NAME=ITEM,PARENT=ORDER

チーフアーキテクトの指摘:
`PROCOPT=A` は「All(G, R, I, D すべて)」を意味する。これを上位のPCBレベル、あるいはすべてのセグメントにデフォルトで適用するエンジニアは、今すぐキーボードを置きたまえ。
アクセスする必要のないセグメント、あるいは「読むだけ」でいいセグメントに更新・削除権限を与えることは、アプリケーションの暴走によるデータ破損のリスクをドブに捨てるようなものだ。

⭕ 堅牢な設計パターン:最小特権の原則(Least Privilege)

では、どう書くべきか。
「顧客の注文情報を参照しつつ、特定の注文に対してステータス(更新のみ)を書き換えられるが、注文や明細の挿入・削除は絶対に許さない」というオンライン業務の要件をコードに落とし込んでみよう。

  • — 堅牢なPSB定義例(最小特権の徹底) —

PCB TYPE=DB,DBD=CUSTDB,PROCOPT=G
SENSEG NAME=CUSTOMER,PARENT=0,PROCOPT=G
SENSEG NAME=ORDER,PARENT=CUSTOMER,PROCOPT=GR
SENSEG NAME=ITEM,PARENT=ORDER,PROCOPT=G
PSGEN

解説:
1. PCB全体のデフォルト `PROCOPT` は `G`(取得)に絞る。
2. `CUSTOMER` は参照のみ(`PROCOPT=G`)。
3. `ORDER` は参照と更新(`PROCOPT=GR`)。これにより `REPL` は許可されるが、`ISRT` や `DLET` はハードウェア/DBMS層で完全にブロックされる。
4. `ITEM` は参照のみ(`PROCOPT=G`)。

この設計であれば、万が一アプリケーションロジックに脆弱性やバグが混入し、誤って `ITEM` を削除するDLICALL(DLET)を発行したとしても、IMSは即座にステータスコード `AJ`(機能不正)を返し、データを守り抜く。これがプロの仕事だ。

—

3. 排他制御(Enqueue)とPROCOPTの深淵な関係

ここからが、階層型DBMSを極めた者しか知らない「実務上の核心」だ。
`PROCOPT` は単なる「権限(Permission)」ではない。データベースの排他制御(ロック挙動)を決定づける極めて重要なファクターなのだ。

例えば、`PROCOPT=G` でセグメントを取得する場合、IMSは基本的に共有ロック(Shared Lock)を取得し、他のトランザクションの読み取りを妨げない。
しかし、更新を意図した取得(いわゆるホールド系コール:`GHU`, `GHN` など)を行う場合、PROCOPTに `R`, `I`, `D` のいずれかが含まれていなければならない。

もし、`PROCOPT=G` しか指定されていないPCBでホールドコールを発行すると、IMSは激怒して(実際には異常終了やステータスコード返却で)処理を拒否する。

デッドロックを回避するPROCOPTのチューニング

複数セグメントを更新するバッチプログラムを設計する際、すべてのセグメントに `PROCOPT=ALL` を与えると、不要な排他ロックの範囲が広がり、シスプレックス環境全体のスループットが急降下する。

  • 参照専用バッチには、徹底的に `PROCOPT=G` を貫くこと。
  • 更新バッチであっても、子セグメント `ITEM` の挿入(I)が必要ないならば、親 `ORDER` には `PROCOPT=GR`、子 `ITEM` には `PROCOPT=G`(あるいは `GI`)と、操作に必要な最小限のアルファベットのみを記述する。

このチューニングの積み重ねが、ピーク時のトランザクション処理性能(TPS)を数十パーセント引き上げる鍵となる。

—

4. チーフアーキテクトからの最終通告

階層型DBMSの設計において、手抜きは許されない。RDBMSのように「後からALTER TABLEで何とかする」という甘えは、IMSの硬質な世界には存在しないのだ。

次に君たちがPSBやDBDを設計・修正する時は、自問自答したまえ。

  • 「このプログラムは、本当にこのセグメントの削除権限(D)を必要としているか?」
  • 「PROCOPTの指定を最小限に絞ることで、データの安全性とロック競合の回避を最大化できているか?」

この細部へのこだわりこそが、何十年も止まらないミッションクリティカルな基幹システムを支える唯一の技術的担保なのだ。

コードに魂を込めろ。設計に妥協するな。以上だ。

コメント

タイトルとURLをコピーしました