PL/Iの「自由」に潜む罠:BUFFEREDとUNBUFFEREDの深い淵
若手のエンジニア諸君、今日もメインフレームの迷宮に潜っているか?
PL/Iという言語は、C言語やJavaのような「厳格な予約語」の束縛から解放された、極めて自由度の高い言語だ。識別子を命名する際、`IF`や`THEN`といったキーワードすら変数名に使えてしまう(コンパイラは文脈で判断する)。しかし、この「自由」は諸刃の剣だ。入出力制御という、システムの心臓部に手を突っ込む際、この自由さが時に取り返しのつかないパフォーマンス劣化や、不可解な排他制御の競合を招くことになる。
今回は、SEQUENTIALファイルにおける `BUFFERED` と `UNBUFFERED` の挙動、そしてそれが実務のバッチ処理にどう影を落とすのかを解説しよう。
—
1. なぜ「バッファの有無」が生死を分けるのか
まず、基本を押さえておこう。`BUFFERED` を指定すると、PL/IのI/O管理ルーチンが中間バッファを介在させる。
- BUFFERED: OSのアクセス・メソッド(BSAM/QSAMなど)が提供するバッファをフル活用する。論理レコードの移動がメモリ間で行われるため、物理的なI/O回数が激減する。
- UNBUFFERED: アプリケーションの作業域(レコード変数)と、データセットが直接結びつく。いわば「直結」だ。
現場の教訓:
「とりあえずバッファしておけば速いだろう」というのは素人の考えだ。大量のシーケンシャル読込を行うバッチなら `BUFFERED` 一択だが、`UPDATE` モードでレコードを書き換える場合、このバッファリングが厄介な「排他制御のタイムラグ」を生むことがある。
—
2. 実践的なコード例:UPDATE処理の作法
以下は、VSAM(ESDSやKSDS)をSEQUENTIALアクセスで更新する際の標準的なテンプレートだ。`UNBUFFERED` を選択するケースは、即座に物理的な更新をコミットさせたい、あるいは排他ロックのタイミングを厳密に制御したい場合だ。
1
/ —————————————————————— /
/ VSAM SEQUENTIAL UPDATE処理の標準パターン /
/ —————————————————————— /
UPDATE_PROC: PROCEDURE OPTIONS(MAIN);
DCL IN_FILE FILE RECORD SEQUENTIAL UPDATE UNBUFFERED;
DCL 1 REC_DATA,
2 KEY_ID CHAR(8),
2 DATA_BODY CHAR(100);
/ ONユニットによる例外制御の基本 /
ON ENDFILE(IN_FILE) BEGIN;
PUT SKIP LIST(‘データ終端に到達しました。’);
GO TO FINISH;
END;
OPEN FILE(IN_FILE);
/ レコードの読み込みと更新 /
READ FILE(IN_FILE) INTO(REC_DATA);
DO WHILE(^ENDFILE(IN_FILE));
/ ここで何らかの加工を行う /
SUBSTR(DATA_BODY, 1, 5) = ‘UPDATED’;
/ UNBUFFEREDのため、REWRITEで即座に物理IOへ反映される /
REWRITE FILE(IN_FILE) FROM(REC_DATA);
READ FILE(IN_FILE) INTO(REC_DATA);
END;
FINISH:
CLOSE FILE(IN_FILE);
END UPDATE_PROC;
—
3. 実務で遭遇するトラブルと「深淵」への対処
現場で最も恐ろしいのは、`BUFFERED` を指定した状態で、非同期の外部プロセスが同じデータセットを覗きに来たときだ。
BUFFERED特有の「ズレ」
`BUFFERED` を使用していると、`READ` した時点では最新のデータがバッファに乗っているが、他のジョブが書き込みを行っても、こちらのバッファには「古いデータ」が残ったままになる可能性がある。これを防ぐには、単に属性を変えるだけでなく、`ON RECORD` ユニットを駆使して例外をキャッチし、必要に応じて `CLOSE/OPEN` でバッファをフラッシュする泥臭いテクニックが必要になることもある。
デバッグのコツ
もし、更新が正しく反映されない、あるいはデッドロックが多発するという事態に陥ったら、まずはコンパイラオプションを確認せよ。そして、JCLの `DCB` パラメータとPL/Iのファイル宣言が矛盾していないか徹底的に洗い出すこと。
特に、`UNBUFFERED` を使う場合は、システムのI/O負荷と引き換えに「データ整合性の確実性」を買っていると心得るべきだ。
—
最後に:ベテランからのアドバイス
「PL/Iは古い」と口にする若手もいるが、基幹システムのバックボーンで脈々と動き続けているこの言語は、コンピュータサイエンスの真理を突いている。バッファリング一つとっても、メモリと物理デバイスの距離を意識する能力は、現代のクラウドネイティブな開発においても決して錆びつかない武器になる。
次にバッチのパフォーマンスチューニングを任されたら、まずは `BUFFERED/UNBUFFERED` の指定を見直してみろ。JCLの `BUFNO` パラメータと組み合わせて調整するだけで、劇的に処理時間が短縮される瞬間があるはずだ。
困ったことがあれば、いつでもまた聞きに来い。現場からは以上だ。
