LoginSignup
1
0

More than 1 year has passed since last update.

READE ってのはキーが一致しない場合、次のレコードをロックする

Last updated at Posted at 2022-12-09

RPGに READE という命令があるのは、みなさんご存知かと思いますが、実はキーが一致しない場合、期待していないレコードがロックされている と知っている方は、どれ位いるだろうか?当たり前の話という方は、この回はスルーして下さい。m(_ _)m

再現用データベース

事象再現用のデータベース「ITEM」が以下の状況で存在したとする。

  • キー:商品コード(CODE)
  • レコードの並び: 商品コード[00124] → 商品コード[99999]
    2022-11-16_184654.png

READE ロック再現コード

READE で期待していないレコード(商品コード:99999)をロックしてしまう側のコード
①QII0100R(ロック解放待ち側)
     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)をワザとロックしているコード
②QII0101R(ロック側)
     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

上記①のREADECHAINは、共に存在しないキー 商品コード:00125 を更新読み取りを行う処理。
しかし、この2つの命令は、結果的に「同じ様な処理をしたいだけ」だとしても大きな違いが生じる。
②の処理を実行し、商品コード:99999 がレコード・ロックされいてる場合、①READEでレコードロック解放待になり、CHAINではそれが発生しない。
つまり、READE の対象は 商品コード:00125 だとしても、それが存在しない場合、実際にレコード・ロックされるのは 商品コード:99999 だという事だ。
これは、CHAIN はランダムアクセス、READE は、順次アクセスだと言うこと証で、READEという命令は、内部的には、次の実装がされているだけだという事がわかる。

  1. 位置づけされたキーで READ(※ここで期待したレコードが存在しない場合、次のレコードロックされる)
  2. キーとフィールド値を比較
  3. 「2」の結果で、EOF か否かを判定する
READEの実態
C                   READ      ITEMR
C                   IF        NOT %EOF                 AND
C                             K@CODE     <> CODE
C                   >>>>> EOFだよ
C                   ENDIF

結論

明確に更新したいキーがある場合は、意図しないレコードを「ロックさせてしまったり、ロック待ち」しないためには、ランダムアクセスである CHAINを使用しましょうという事。SETLLでキーの位置づけを判定する方法もあるが、クリティカルに考えると「SETLL 時点では存在したが READE したら無かった」があり得るので、やはり個人的には最適解ではないと思います。

SETLL 判定実装例
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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0