Hitachi

ノンストップデータベース HiRDB Version 10 UAP開発ガイド


3.4.14 複数トランザクションで検索と更新をする場合

複数トランザクションで同一の表を検索及び更新する場合の一般的な処理方法と注意事項について説明します。

〈この項の構成〉

(1) 一般的な処理方法

SELECT文で更新対象行を特定し,UPDATE文で更新するトランザクションを実行する場合,SELECT文を実行する前に同一トランザクション中で,LOCK文を用いて排他モードで表に対して排他制御を行うか,又はSELECT文の排他制御のモードを次のどちらかの方法で排他モード(EX:Exclusive)にするかしてください。

SELECT文の排他制御のモードを排他モードにする場合の例を次に示します。

(例)

次の表「在庫テーブル」から「在庫状態」が「在庫確保中」の行を検索します。該当する行があった場合は,「在庫状態」を「在庫あり」に変更します。

表3‒26 例・在庫テーブル

在庫ID(主キー)

在庫名

在庫状態

20345678

ネクタイ

在庫確保中

20345679

シャツ

在庫あり

20345680

靴下

在庫なし

20345681

ズボン

在庫確保中

20345682

スカート

在庫あり

20345683

パンツ

在庫確保中

DECLARE CUR1 CURSOR FOR SELECT 在庫状態 FROM 在庫テーブル
  WHERE 在庫状態='在庫確保中'
    WITH EXCLUSIVE LOCK FOR UPDATE OF 在庫状態
OPEN CUR1
WHILE(SQLCODE == 0){
    FETCH CUR1 INTO :在庫状態
    UPDATE 在庫テーブル SET 在庫状態='在庫あり'
      WHERE CURRENT OF CUR1
}
CLOSE CUR1

(2) 検索する行に対して更新する行が非常に少ない場合

SELECT文でヒットする行に対してUPDATE文で更新する行が少ない場合,SELECT文の排他オプションにSHARE LOCKを指定することで,他トランザクションからも参照できるようになるため,同時実行性を向上できます。ただし,他トランザクションと更新する行が重なり,排他制御のモードが共有モードから排他モードに遷移することによってデッドロックが起こるおそれがあるため,注意してください。

(3) 排他の掛かる行を減らすために事前に無排他で検索する場合

SELECT文を無排他検索にすることで,「検索する行に対して更新する行が非常に少ない場合」よりもさらに同時実行性を向上できます。ただし,無排他検索をしてからUPDATE文を実行するまでの間に検索した行がほかのトランザクションによって更新される可能性があります。この場合,データの取り出しで読み込む値が,探索条件に合致しない値になることがあります。UPDATE文を正しく実行するため,無排他にしたSELECT文の探索条件を,UPDATE文又は排他制御のモードが排他モードのSELECT文で再評価してください。

無排他にしたSELECT文の探索条件を,排他制御のモードが排他モードのSELECT文で再評価する場合の例を次に示します。

(例)

無排他のSELECT文に指定した探索条件「在庫状態='在庫確保中'」をWITH EXCLUSIVE LOCKの指定があるSELECT文で再評価して,他トランザクションによる変更がないことを確認します。他トランザクションによる変更がなければ更新をします。

DECLARE CUR1 CURSOR FOR SELECT 在庫ID FROM 在庫テーブル
  WHERE 在庫状態='在庫確保中' WITHOUT LOCK
OPEN CUR1
WHILE(SQLCODE == 0){
    FETCH CUR1 INTO :在庫ID_WITHOUTLCK
    /* 行を絞り込むためのUAP側の処理 */
        ・
        ・
        ・
    DECLARE CUR2 CURSOR FOR SELECT 在庫状態 FROM 在庫テーブル
      WHERE 在庫ID=:在庫ID_WITHOUTLCK AND 在庫状態='在庫確保中'
        WITH EXCLUSIVE LOCK FOR UPDATE OF 在庫状態
    OPEN CUR2
    FETCH CUR2 INTO :在庫状態_WITHLCK
    IF(SQLCODE == 0){
        UPDATE 在庫テーブル SET 在庫状態='在庫あり'
          WHERE CURRENT OF CUR2
    }
    CLOSE CUR2
}
CLOSE CUR1