RPGに READE
という命令があるのは、みなさんご存知かと思いますが、実はキーが一致しない場合、期待していないレコードがロックされている と知っている方は、どれ位いるだろうか?当たり前の話という方は、この回はスルーして下さい。m(_ _)m
再現用データベース
事象再現用のデータベース「ITEM」が以下の状況で存在したとする。
READE ロック再現コード
READE
で期待していないレコード(商品コード:99999)をロックしてしまう側のコード
H DATEDIT(*YMD)
H*- ***************************************************************
H*- * F仕様書 **
H*- ***************************************************************
F*- ---<< ファイル定義 >>-----*
FITEM UF E K DISK
D*- ---<< 変数定義 >>-----*
D MSG S 40A
C*- ***************************************************************
C*- * KLIST **
C*- ***************************************************************
C ITEMKEY1 KLIST
C KFLD K@CODE 5 0 商品コード
C*- ***************************************************************
C*- * メインロジック **
C*- ***************************************************************
C*
C*---------------
C*- READE
C*---------------
C Z-ADD 00125 K@CODE 商品コード
C ITEMKEY1 SETLL ITEMR
C ITEMKEY1 READE ITEMR
C IF %EOF
C EVAL MSG = '[READE]-'
C + ' 商品 125 は存在しません '
C MSG DSPLY
C ENDIF
C*
C*---------------
C*- CHAIN
C*---------------
C Z-ADD 00125 K@CODE 商品コード
C ITEMKEY1 CHAIN ITEMR
C IF NOT %FOUND
C EVAL MSG = '[CHAIN]-'
C + ' 商品 125 は存在しません '
C MSG DSPLY
C ENDIF
C*
C SETON LR
C RETURN
期待していないレコード(商品コード:99999)をワザとロックしているコード
H DATEDIT(*YMD)
H*- ***************************************************************
H*- * F仕様書 **
H*- ***************************************************************
F*- ---<< ファイル定義 >>-----*
FITEM UF E K DISK
D*- ---<< 変数定義 >>-----*
D MSG S 40A
C*- ***************************************************************
C*- * KLIST **
C*- ***************************************************************
C ITEMKEY1 KLIST
C KFLD K@CODE 5 0 商品コード
C*- ***************************************************************
C*- * メインロジック **
C*- ***************************************************************
C*
C*---------------
C*- CHAIN
C*---------------
C Z-ADD 99999 K@CODE 商品コード
C ITEMKEY1 CHAIN ITEMR
C IF %FOUND
C EVAL MSG = '[CHAIN]-'
C + ' 商品 99999 をロック! '
C MSG DSPLY
C ENDIF
C*
C SETON LR
C RETURN
上記①のREADE
とCHAIN
は、共に存在しないキー 商品コード:00125 を更新読み取りを行う処理。
しかし、この2つの命令は、結果的に「同じ様な処理をしたいだけ」だとしても大きな違いが生じる。
②の処理を実行し、商品コード:99999 がレコード・ロックされいてる場合、①READE
でレコードロック解放待になり、CHAIN
ではそれが発生しない。
つまり、READE
の対象は 商品コード:00125 だとしても、それが存在しない場合、実際にレコード・ロックされるのは 商品コード:99999 だという事だ。
これは、CHAIN
はランダムアクセス、READE
は、順次アクセスだと言うこと証で、READE
という命令は、内部的には、次の実装がされているだけだという事がわかる。
- 位置づけされたキーで
READ
(※ここで期待したレコードが存在しない場合、次のレコードロックされる) - キーとフィールド値を比較
- 「2」の結果で、EOF か否かを判定する
C READ ITEMR
C IF NOT %EOF AND
C K@CODE <> CODE
C >>>>> EOFだよ
C ENDIF
結論
明確に更新したいキーがある場合は、意図しないレコードを「ロックさせてしまったり、ロック待ち」しないためには、ランダムアクセスである CHAIN
を使用しましょうという事。SETLL
でキーの位置づけを判定する方法もあるが、クリティカルに考えると「SETLL
時点では存在したが READE
したら無かった」があり得るので、やはり個人的には最適解ではないと思います。
C Z-ADD 00125 K@CODE 商品コード
C ITEMKEY1 SETLL ITEMR
C IF NOT %EQUAL
C EVAL MSG = '[SETLL]-'
C + ' 商品 125 は存在しません '
C MSG DSPLY
C ELSE
C*- // ここでクリティカルに考えると結局NG
C ITEMKEY1 READE ITEMR
C IF NOT %EOF
C EVAL MSG = '[READE]-'
C + ' 商品 125 は存在しません '
C MSG DSPLY
C ENDIF
C ENDIF