SKIP LOCKEDを使ったジョブキューイング

1. 最初にAが1行取得する

 Session A                                            │Session B
 =====================================================│===================================================
 PG=> BEGIN; SELECT * FROM jobs WHERE status = 'p     │PG=>
 ending' LIMIT 1 FOR UPDATE SKIP LOCKED;              │PG=>
 BEGIN                                                │PG=>
  id | status                                         │PG=>
 ----+---------                                       │PG=>
   1 | pending                                        │PG=>
 (1 rows)                                             │PG=>
                                                      │PG=>
 PG=*>                                                │PG=> BEGIN; SELECT * FROM jobs FOR UPDATE SKIP L
 PG=*>                                                │OCKED;
 PG=*>                                                │BEGIN
 PG=*>                                                │ id | status
 PG=*>                                                │----+---------
 PG=*>                                                │  2 | pending
 PG=*>                                                │  3 | pending
 PG=*>                                                │(2 rows)
  • AがFOR UPDATE SKIP LOCKEDを指定してjobsテーブルからSELECTして1行取得(上の通りID:1の行)
  • BはjobsテーブルからID:1を除いたID:2とID:3の行しかSELECTできなくなる

2. 次にAが取得した行をUPDATEしてCOMMITする

 PG=*> UPDATE jobs SET status = 'runnnig' WHERE i     │PG=*>
 d = 1;                                               │PG=*>
 UPDATE 1                                             │PG=*>
 PG=*>                                                │PG=*> SELECT * FROM jobs FOR UPDATE SKIP LOCKED;
                                                      │ id | status
                                                      │----+---------
                                                      │  2 | pending
                                                      │  3 | pending
                                                      │(2 rows)
                                                      │
                                                      │PG=*> 
 PG=*> COMMIT;                                        │PG=*>
 COMMIT                                               │PG=*>
 PG=>                                                 │PG=*> SELECT * FROM jobs FOR UPDATE SKIP LOCKED;
                                                      │ id | status
                                                      │----+---------
                                                      │  2 | pending
                                                      │  3 | pending
                                                      │  1 | runnnig
                                                      │(3 rows)
  • Aは1.で取得した行をUPDATEするが、この時点でもBはID:1の行を取得できない
  • AがCOMMIT実行した後に、BはID:1の行を取得できるようになるが、この時にはstatusはrunningに更新済み

参考

https://spin.atomicobject.com/2021/02/04/redis-postgresql/


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

Last-modified: 2021-06-13 (日) 12:43:24