階層型DBMSの核心:PCB(プログラム通信ブロック)定義構文と論理ビュー設計の極意
こんにちは。チーフアーキテクトの私だ。
今日のコードレビューで、また「なんとなくコピペで作られたようなPCB(Program Communication Block)定義」を見かけた。
リレーショナルデータベース(RDBMS)全盛の現代において、IMS DBなどの階層型DBMSを触る機会は絶滅危惧種的かもしれない。しかし、金融、航空、公共といったミッションクリティカルな領域では、その圧倒的なI/O効率と決定論的なパフォーマンスゆえに今なお現役で稼働している。
そして、階層型DBMSの成否を握る最大の肝は、アプリケーションと物理データベースを繋ぐ「PCB(プログラム通信ブロック)の設計」にある。
今回は、PCB定義構文の本質、`SENSEG`や`PROCSEQ`を用いた論理ビューの制限、そして現場で即座に使える堅牢な設計パターンを、妥協のないエンジニアの視点で叩き込む。
—
1. そもそもPCBとは何か? — 物理と論理の完全なデカップリング
RDBMSでは、アプリケーション(SQL)はテーブルの構造を直接知っているか、ビューを介してアクセスする。しかし、階層型DBMSの世界では思想が異なる。
アプリケーションは物理データベースの構造(DBD:Database Description)を直接意識してはならない。
プログラムが触れるのは、あらかじめ定義された「窓」――すなわちPCBを介した論理ビューのみである。
[物理データベース (DBD)]
├── 根セグメント (ROOT)
├── 子セグメントA (CHILD_A)
└── 子セグメントB (CHILD_B) <-- アプリXには隠蔽したい機密データ
│
└── 孫セグメントC (GRANDCHILD_C)
▲ (アクセス制御・論理ビュー定義)
[PCB定義 (PSB)]
├── PCB (アプリX用) ---> ROOT -> CHILD_A のみが見える
└── PCB (アプリY用) —> 全セグメントが見える(PROCSEQあり)
この「情報隠蔽」と「アクセス経路の制限」をコンパイル時に強制するのが、PSB(Program Specification Block)ジェネレータであり、その構成要素がPCBなのだ。
—
2. PCB定義構文の解剖と `SENSEG` の極意
百聞は一見にしかず。まずは典型的なPCB定義のコードを見てほしい。IMS/ESAをベースにした標準的なマクロ構文だ。
———————————————————————-
- PCB定義: 顧客・契約管理プログラム用 (CUSTPRG)
———————————————————————-
PCB TYPE=DB, データベース用PCBを指定 秘
DBDName=CUSTDB, 参照する物理DBD名 密
Access=GSAM, (※通常はSHMISS等を指定) 度
ProcSeq=CUSTNAME セカンダリインデックス指定 高
- — 根セグメントの定義 —
SENSEG Name=CUSTSEG, 物理セグメント名
Parent=0, 根なので親はなし
ProcOpts=G 参照(Get)のみ許可
- — 子セグメントの定義(機密データは除外) —
SENSEG Name=CONSEG, 契約セグメント
Parent=CUSTSEG, 親はCUSTSEG
ProcOpts=G 参照のみ
- — 孫セグメントの定義(更新を許可) —
SENSEG Name=DTLSEG, 詳細セグメント
Parent=CONSEG, 親はCONSEG
ProcOpts=R 置換(Replace)を許可
`SENSEG`(Sensitive Segment)の設計哲学
`SENSEG`は、単なる「見せる・見せない」のフィルターではない。アプリケーションがナビゲートできる論理的な階層パスそのものを再定義する構文だ。
1. 最小権限の原則 (Principle of Least Privilege)
`ProcOpts`(処理オプション)の指定には細心の注意を払え。
- `G` (Get): 読み取り専用。バグによるデータ破壊を物理レベルで防ぐ。
- `R` (Replace): 更新のみ。挿入(`I`)や削除(`D`)を許可しないことで、構造の整合性を守る。
- `A` (All): 全許可。これは本当に特権を持ったバッチプログラムだけに限定すべきだ。安易な`A`の付与は設計の怠慢とみなす。
2. 不要なセグメントの隠蔽
物理DBDに存在しても、PCBの`SENSEG`リストに載せなければ、アプリケーションはそのセグメントの存在すら知ることはできない。給与情報や暗号化されたキーなど、アクセス権のないデータ領域をアプリケーション層のバグから完全に隔離できる。
—
3. `PROCSEQ` パラメータ:論理ビューの魔術とパフォーマンスの罠
階層型DBMSの最大の弱点は、「親を辿らなければ子にたどり着けない」という構造上の制約だ。例えば、「契約番号(子セグメントのキー)」から直接データを引きたい場合、通常のルートからの走査では致命的な性能劣化を招く。
ここで登場するのが、`PROCSEQ`(プロシージャル・セカンダリ・インデックス)である。
PCB TYPE=DB,
DBDName=CUSTDB,
ProcSeq=CON_IDX_DBD 契約番号順のセカンダリインデックス
アーキテクトとしての警告:`PROCSEQ`の代償
`PROCSEQ`を使うことで、アプリケーションはあたかも「契約番号が根セグメントであるかのように」データをフェッチできるようになる。論理ビューの美しさとしては完璧だ。
しかし、実務では以下のコストを常に頭に叩き込んでおけ。
- I/Oコストの増加: セカンダリインデックスを経由したアクセスは、実質的に「インデックスセグメントの読み込み」+「ターゲットセグメントのポインタ追跡」という2段構えのI/Oが発生する。
- 位置づけ (Positioning) の罠: `PROCSEQ`を使用している場合、`GU`(Get Unique)や`GN`(Get Next)を発行した際の「カセグメントポジション」の動きが物理順とは異なる。ジュニアプログラマーがこの挙動を誤解し、無限ループや意図しないスキップを引き起こす障害が後を絶たない。
設計レビューでは、本当にその`PROCSEQ`が必要か、親セグメントからの物理パスで十分なスループットが出せないか、必ず実行計画(というかバッファヒット率とI/Oトレース)を確認すること。
—
4. 実務で使える堅牢なPCB設計パターン
現場で私が新人・中堅によく指導する、堅牢なPCB設計のプラクティスをいくつか共有しよう。
パターンA:オンライン用とバッチ用の「PSB分離の原則」
オンライン画面(CICS等から呼ばれる)と、夜間バッチプログラムで、同一の物理DBDに対して全く同じPCBを使い回してはならない。
- オンライン用PCB:
- `ProcOpts=G` または限定的な `R`。
- 誤更新を防ぐため、不要なセグメントは一切`SENSEG`に入れない。
- デッドロックを防ぐため、アクセスパスは常に単一の方向(上から下)に絞る。
- バッチ用PCB:
- 大量データ処理のため、必要に応じて `I` (Insert) や `D` (Delete) を許可。
- ただし、更新系バッチであっても、参照専用の処理には必ず専用の「参照用PCB」を切る。
パターンB:論理子(Logical Child)を絡めた複雑なPCB
実務では、複数の物理DBDを結合した「論理関係(Logical Relationship)」を扱うPCBに遭遇する。
SENSEG Name=ORDERSEG,Parent=0,ProcOpts=G
SENSEG Name=ITEMSEG,Parent=ORDERSEG,Source=((ITEMDB,ITEMSEG))
- `Source` パラメータを用いることで、別DBDのセグメントをあたかも自DBDの子であるかのように見せかけることができる。
- 注意: このような複雑な論理ビューは、DBA以外のプログラマーが構造を理解しにくくする。必ず設計ドキュメントに「どの物理DBDとどう結合されているか」のER図(ならぬ階層構造図)を添付させ、コードレビュー時には「このSENSEGのSourceが物理I/Oに与える影響を説明しろ」と詰めること。
—
5. チーフアーキテクトからのメッセージ
階層型DBMSのPCB定義は、単なる「設定ファイルの記述」ではない。
「アプリケーションに許された世界の境界線をどこに引くか」という、システム全体のセキュリティとパフォーマンスを支配する境界線設計そのものなのだ。
コードを書き換える前に自問せよ。
- 「このプログラムは、本当にこのセグメントの更新権限(`R` / `I` / `D`)を必要としているか?」
- 「この`PROCSEQ`は、バッチの処理時間を本当に許容範囲内に収めているか?」
技術がどれだけ古びようとも、データ構造とアクセス制御の本質は変わらない。
美しく、無駄がなく、堅牢なPCB設計によって、あなたのシステムを揺るぎないものにしてほしい健闘を祈る。
コメント