【入門編】DB2埋め込みSQLにおけるトランザクション制御(COMMIT/ROLLBACK) – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいはビジネスの現場でバリバリ活躍されている言語のご経験がある方にとって、レガシーの代名詞とも言える「PL/I(ピーエルアイ)」や、IBMメインフレームの世界は、最初はちょっと近寄りがたい「黒魔術」のように見えるかもしれません。

「変数名のルールはどうなっているの?」
「CICSとDB2が絡むトランザクションって、なんだか難しそう……」

そんな不安を抱えていませんか? 大丈夫ですよ。安心してください。今日は、他の言語の経験があるあなたならスルスルッと頭に入ってくるように、PL/Iのユニークな識別子のルールから、現場で絶対に避けて通れない「CICSとDB2のトランザクション同期(UOW管理)」の核心まで、そっと手を取りながら丁寧にご案内しますね。

—

1. PL/Iの「予約語を持たない」という懐の深さと識別子のルール

まずは、JavaやCOBOLとはちょっと違う、PL/Iの面白い特徴からお話ししましょう。

多くのプログラミング言語には「予約語(Keyword)」というものがありますよね。例えばCOBOLなら `MOVE` や `DISPLAY`、Javaなら `class` や `public` といった単語は、変数名として使うことができません。コンパイラから「それ、私の命令語だから勝手に使わないでよ!」と怒られてしまいます。

ところが、PL/Iには原則として「固定的な予約語」が存在しません。
「えっ、じゃあ `IF` や `READ` って変数名にしちゃってもいいの?」はい、理論上は怒られません(コンパイラは前後の文脈から「あ、これは命令だな」「お、ここは変数名だな」と驚異的な空気を読んで解釈してくれます)。

とはいえ、実務の現場で `IF` という名前の変数を作る人はいませんし、そんなことをしたらコードレビューで先輩からこってり絞られてしまいますからね。常識の範囲内で、変数名(識別子)のルールを確認しておきましょう。

識別子の基本ルール

  • 文字数: 最大31文字まで使えます。
  • 使える文字: アルファベット(A〜Z)、数字(0〜9)、そして特殊文字の `$` (国記号)、`#` (ポンド記号)、`@` (アットマーク)。
  • 先頭の文字: 必ずアルファベットか、上記の特殊文字で始まらなければなりません(数字を先頭にすることはできません)。

例えば、CICSとDB2を連携させるプログラムでは、こんな風に変数にプレフィックス(接頭辞)をつけて整理することが多いです。

1
/ 変数宣言のサンプル /
DCL W_CUST_ID FIXED BIN(31) INIT(0); / 顧客ID(作業用) /
DCL W_RETURN_CD CHAR(2) INIT(‘ ‘); / リターンコード /

(※ `DCL` は DECLARE の略で、変数を宣言するときのキーワードです)

他の言語を知っているあなたなら、「なんだ、名前の付け方は基本に忠実にやれば全然怖くないな」と思っていただけるはずです。

—

2. 本題:CICSとDB2が織りなす「トランザクション制御」の切っても切れない関係

さて、ここからが今日のメインテーマです。
オンライン画面を制御するミドルウェア 「CICS(シス)」 と、データを安全に保管するリレーショナルデータベース 「DB2」。この二つがタッグを組む世界で、一番頭を悩ませるのが 「トランザクション制御(UOW:Unit of Work / 論理作業単位)」 です。

JavaのSpring Frameworkや、一般的なWebアプリケーションであれば、フレームワークがよしなにトランザクションのコミットやロールバックを管理してくれますよね。
しかし、メインフレームの世界では、私たちがコードのなかで「ここまで処理がうまくいったら確定(COMMIT)!」「何かエラーが起きたら全部なかったことに(ROLLBACK)!」と、明確に指示を出してあげる必要があります。

ここで、CICS環境特有の大きな落とし穴(というか仕様)があります。

> 「CICSのトランザクション制御コマンドと、DB2のSQL文は、それぞれ別々に動くわけではない。お互いにしっかり手をつながせなければならない」

という点です。

CICSの `SYNCPOINT` と DB2の `COMMIT / ROLLBACK` の関係

オンライン画面の一連の処理の中で、DB2のデータを更新し、最後に「よし、今回の更新を確定しよう!」と処理を終わらせる場面を想像してください。

ここで、CICSの標準的なコマンドである `EXEC CICS SYNCPOINT` を発行すると何が起きるでしょうか?
実は、これを発行すると、CICSが管理するリソース(ファイルや一時記憶など)と、DB2データベースの更新内容が「同時に(同期して)」確定(COMMIT)されます。

逆に、途中で致命的なエラーが発生し、処理を巻き戻したいときはどうするでしょう?
ここでうっかりDB2側だけでロールバックしようとしたり、CICS側で中途半端な制御をすると、「画面側では処理が成功したことになっているのに、データベース側は更新されていない」という、悪夢のような「データの不整合(リソースの不一致)」が発生してしまいます。

これを防ぐための鉄則を、次の実用コード例で見 てみましょう。

—

3. 【実用コード例】安全なトランザクション制御の書き方

CICS上で動作するPL/Iプログラムにおいて、DB2を更新し、安全にUOW(論理作業単位)を完了させる典型的なパターンをコードに落とし込んでみました。

1
/ ================================================================= /
/ プログラム名: CUSTUPDT /
/ 概要: CICS画面からの依頼を受け、DB2を更新してトランザクションを確定する /
/ ================================================================= /
CUSTUPDT: PROC OPTIONS(MAIN, CICS);

/ — 変数宣言セクション — /
DCL WS_SQLCODE FIXED BIN(31) INIT(0);
DCL WS_MSG CHAR(40) INIT(‘ ‘);

/ DB2のホスト変数宣言 /
DCL HV_CUST_ID FIXED BIN(31);
DCL HV_CUST_NAME CHAR(50);

/ 組み込みSQLの通信エリア(SQLCA)の取り込み /
EXEC SQL INCLUDE SQLCA;

/ — 1. 処理の開始 — /
/ (ここにCICSの画面からデータを受け取る RECEIVE MAP などの処理が入ります) /
HV_CUST_ID = 1001;
HV_CUST_NAME = ‘山田 太郎’;

/ — 2. DB2の更新処理(SQL) — /
EXEC SQL
UPDATE CUSTOMER_TBL
SET CUST_NAME = :HV_CUST_NAME
WHERE CUST_ID = :HV_CUST_ID;

/ SQLの実行結果をローカル変数に退避 /
WS_SQLCODE = SQLCODE;

/ — 3. 処理結果に応じたトランザクション制御 — /
IF WS_SQLCODE = 0 THEN DO;
/ 更新成功! CICSとDB2の変更を同時に確定(コミット)する /
EXEC CICS SYNCPOINT;

WS_MSG = ‘正常に更新を完了しました。’;
/ 画面へ完了メッセージを返す処理へ… /
END;
ELSE DO;
/ 更新失敗! 異常系なので処理を巻き戻す(ロールバック) /
/ CICSのSYNCPOINT ROLLBACKを使うことで、DB2も含めて全巻き戻しされます /
EXEC CICS SYNCPOINT ROLLBACK;

WS_MSG = ‘更新に失敗しました。処理を中断します。’;
/ 画面へエラーメッセージを返す処理へ… /
END;

RETURN;

END CUSTUPDT;

コードのここがポイント!

1. `EXEC CICS SYNCPOINT;` の威力
正常終了時には、DB2の個別な `COMMIT` 文をわざわざ書かなくても、CICSの `SYNCPOINT` を発行するだけで、DB2側も連動してコミットされます。これがCICSとDB2の同期挙動の基本です。
2. 異常系では `EXEC CICS SYNCPOINT ROLLBACK;` を使う
「データベースだけロールバックして、画面はそのまま」なんてことはメインフレームの世界では許されません。エラー時は必ずCICSの仕組みを通じてロールバックを行い、UOW(論理作業単位)の整合性を保ちます。

—

まとめ:レガシーのトランザクション制御も、基本の「同期」を押さえれば怖くない!

いかがでしたでしょうか?
PL/Iという名前や、メインフレーム特有の緑色の画面、そして「CICS」「DB2」といった重厚な響きに最初は圧倒されてしまうかもしれませんが、やっている本質はモダンなシステムと何ら変わりません。

  • 識別子はルールを守れば難しくない
  • CICSとDB2の同期は `SYNCPOINT`(確定)と `SYNCPOINT ROLLBACK`(巻き戻し)で一体管理する

この2点さえ心に留めておけば、バッチの改修やマイグレーション調査の現場に放り出されても、もう慌てる必要はありません。一つひとつの命令の意味を紐解いていけば、PL/Iは非常に素直で堅牢な、頼れる言語であることが分かってきますよ。

あなたのレガシーシステムの旅が、実りある素晴らしいものになるよう応援しています!

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