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/