外部キーなカラムに対するFOR UPDATE

前提

 => SELECT * FROM t1;
  t1_id | n  | t2_id
 -------+----+-------
      1 | 10 |     1
      2 | 20 |     2
 
 => SELECT * FROM t2;
  t2_id |  n
 -------+-----
      1 | 100
      2 | 200
  • t1テーブルのt2_idカラムは外部キー制約が設定されている

SQL

 Session A                       | Session B                       |
 =======================================================================================================
 => BEGIN; SELECT * FROM t1 WHER | =>                              | 1. Aでt2_id=1なカラムがロックすると
 E t1_id = 1 FOR UPDATE;         | =>                              |    t1テーブルだけでなく、
  t1_id | n  | t2_id             | =>                              |    t2テーブルも影響を受ける
 -------+----+-------            | =>                              | 
      1 | 10 |     1             | =>                              | 
                                 | =>                              | 
 =*>                             | => UPDATE t2 SET n = 1 WHERE t2 | 2. Bでt2テーブルのnカラムをUPDATEす
 =*>                             | _id = 1;                        |    るのはブロックされず即実行される
 =*>                             | =>                              |    
 =*>                             | => UPDATE t2 SET t2_id = 10 WHE | 3. しかし、Bでt2テーブルのt2_idを
 =*>                             | RE t2_id = 1;                   |    UPDATEしようとすると
 =*>                             |                                 |    ブロックされる
 =*>                             |                                 | 
 =*> COMMIT;                     |                                 | 4. AでCOMMITすると、
                                 | ERROR:  update or delete on tab |    BでブロックされていたUPDATEが実行
 =>                              | le "t2" violates foreign key co |    される
 =>                              | nstraint "t1_t2_id_fkey" on tab | 
                                 | le "t1"                         | 
                                 | DETAIL:  Key (t2_id)=(1) is sti | 
                                 | ll referenced from table "t1".  | 
                                 |                                 | 
                                 | => SELECT * FROM t2;            | 
                                 |  t2_id |  n                     | 
                                 | -------+-----                   | 
                                 |      2 | 200                    | 
                                 |      1 |   1                    | 
                                 |                                 |

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS

Last-modified: 2021-06-17 (木) 15:14:35