上記のご質問をいただきまして、背景として
ある処理中のエラーが発生した。その原因を調査するためにエラー発生時点でどのテーブル(物理ファイル)が処理中だったか、どのプログラムからどんな処理を実行中だったかを調べたい、というものでした。
Db2 for i のテーブル更新ログはジャーナルに書き出される
Db2 for i のテーブルはかつてはジャーナル(ログ)取得しないがデフォだった。
1980年代、ディスクは超高価でしたので本番システムでも200MB(TBじゃないですよw)とかざらな時代だったしデータ更新もCOBOL, RPGでネイティブI/OというSQLでない方式だったためジャーナル取得はオプション扱いでした。現在はSQLでCREATE TABLEするとDb2 for iでもジャーナル(ログ)が自動的に開始・取得されますが、昔からあるテーブルなどはジャーナルが未取得になってたりします。
ジャーナル取ってる?の確認
DSPFD FILE(DEMOLIB/TOKMASP2)
上記コマンドでDEMOLIBのTOKMASP2のテーブルの状況を確認できます。以下のようにジャーナルイメージに*AFTER または BOTHが入っていればジャーナル取得設定済みです。
ちなみにAFTERはレコード更新モードの場合更新後イメージのみ取得する、*BOTHは更新前後で合計2件ログ取得するモードです。ストレージ容量その他から必要性検討して設定します。
もしジャーナル取得されてない場合は、
STRJRNPF FILE(DEMOLIB/TOKMASP2) JRN(DEMOLIB/JRN01)
のように実行するとJRN01というジャーナルにログが取得されます。JRN01というジャーナルが存在していない場合は、上記コマンドの前に下記2つのコマンドを実行してジャーナル(ログ)を取得できる準備をします。
ジャーナルを保管するジャーナルレシーバーを作成
CRTJRNRCV JRNRCV(DEMOLIB/JRNRCV01)
DB更新時にジャーナルを取得して、ジャーナルレシーバーに格納してくれるジャーナルを作成
CRTJRN JRN(DEMOLIB/JRN01) JRNRCV(DEMOLIB/JRNRCV01)
以上でTOKMASP2の更新ログはジャーナルJRN01を通じて確認することができます。(ジャーナルレシーバーはジャーナルの件数が増えると自動的に次のジャーナルを新規作成、切り替わっていきます)
それではジャーナルでDb2 for i の更新情報を確認します。方法は大きく2種類あります。(5250から、SQLから)
ジャーナルの確認方法:5250を使う方法
ジャーナルの名前、確認したいテーブルのジャーナルを取得しているジャーナルの名前を指定して、下記コマンドを実行します。
DSPJRN DEMOLIB/JRN01
と実行すると下記のような画面が表示されます。
コード と タイプ というカラムがREAD/ADD/DELETEなどDBに対する処理パターンを表します。
下記で順序179の行は R UP で、レコードをREADしUPDATEした後のジャーナル(ログ)であることが分かります。
オプションに5を入力、エンターキーすると更新されたレコードの内容が表示されます。実際に更新されたレコード内のパックフィールドやDBCSが文字化けしてしまいますが、冒頭に 01010 アイリョカン などどのレコードかは確認ができます。
PF11キーを押すとHEXで表示されます。
コード、タイプの説明は下記マニュアルを参照してください。
https://www.ibm.com/docs/ja/i/7.3?topic=information-all-journal-entries-by-code-type
*プログラムでジャーナルの各レコードを取得して処理したい場合は、RTVJRNEコマンドを使用します。
SQLを使う方法: IBM i サービスDISPLAY_JORNALテーブル関数
割と近年追加になった機能でIBM i 7.2以降で利用可能です。
DISPLAY_JOURNAL テーブル関数 をSQLから実行してジャーナルを検索できます。
SELECT *FROM TABLE (QSYS2.DISPLAY_JOURNAL( 'DEMOLIB', 'JRN01'))
のように実行します。
*ACSのSQLスクリプト実行画面などではコマンドの末尾にセパレーターの意味の ; セミコロンを付けてください。 (以下の2つ目のサンプル以降はセミコロン付きです)
例:TOKMASP2に対して、ユーザーQSECOFRが実行したすべての変更をリストする。
SELECT journal_code, journal_entry_type, object, object_type, X.*
FROM TABLE (
QSYS2.Display_Journal(
'DEMOLIB', 'JRN01', -- ジャーナル名
OBJECT_LIBRARY=>'DEMOLIB', OBJECT_NAME=>'TOKMASP2',
OBJECT_OBJTYPE=>'*FILE', OBJECT_MEMBER=>'TOKMASP2'
) ) AS X
WHERE journal_entry_type in ('DL', 'PT', 'PX', 'UP') AND "CURRENT_USER" = 'QSECOFR'
ORDER BY entry_timestamp DESC;
例:現行ジャーナルID(JID)で、TOKMASP2の過去1時間の更新処理をリストする。なお、D データベース・ファイル操作 F データベース・ファイル・メンバー操作 R 特定レコードの操作
SELECT journal_code, journal_entry_type, object, object_type, X.*
FROM TABLE (QSYS2.Display_Journal('DEMOLIB', 'JRN01',
JOURNAL_CODES => 'D,F,R',
STARTING_RECEIVER_NAME => '*CURCHAIN',
OBJECT_OBJTYPE=>'*FILE',
OBJECT_LIBRARY=>'DEMOLIB',
OBJECT_NAME=>'TOKMASP2',
OBJECT_MEMBER=>'*ALL'
) ) AS X
WHERE entry_timestamp > CURRENT TIMESTAMP - 1 HOUR
ORDER BY entry_timestamp DESC ;
例)ジャーナルIDが現行以外も含めてTOKMASP2の過去1時間以内のすべての更新をリストする
SELECT journal_code, journal_entry_type, hex( journal_identifier ),
object, object_type, X.*
FROM TABLE (QSYS2.Display_Journal('DEMOLIB', 'JRN01',
JOURNAL_CODES => 'D,F,R',
STARTING_RECEIVER_NAME => '*CURCHAIN'
) ) AS X
WHERE LEFT(OBJECT,20) = CHAR('TOKMASP2', 10) CONCAT CHAR('DEMOLIB', 10)
and entry_timestamp > CURRENT TIMESTAMP - 1 HOUR
ORDER BY entry_timestamp DESC ;
参考マニュアルページ:
IBM i 7.5 https://www.ibm.com/docs/ja/i/7.5?topic=services-display-journal-table-function