スケーラブルデータベースサーバ HiRDB Version 8 UAP開発ガイド

[目次][索引][前へ][次へ]

3.4.12 複数トランザクションで参照と更新をする場合

<この項の構成>
(1) 複数トランザクションで同一の表を検索・更新する一般的な処理方法
(2) 検索する行に対して更新行が非常に少ない場合
(3) 排他のかかる行を減らすために事前に無排他で検索する場合

(1) 複数トランザクションで同一の表を検索・更新する一般的な処理方法

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

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

 
例
表 在庫テーブル
在庫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文を無排他検索にすることで,(2)よりもさらに同時実行性を向上できます。ただし,無排他検索してからUPDATE文を実行するまでの間に検索した行が他のトランザクションによって更新される可能性があり,SELECT文の探索条件に他のトランザクションで更新される可能性がある列を含む場合には,データの取り出しで読み込む値が,探索条件に合致しない値になることもあります。UPDATE文を正しく行うため,無排他にしたSELECT文の探索条件を,UPDATE文または排他制御のモードが排他モードのSELECT文でもう一度再評価してください。

 

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

 
例
無排他のSELECT文に指定した探索条件「在庫状態='在庫確保中'」をWITHEXCLUSIVE 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