The best way to implement a job queue in a relational database system is to use SKIP LOCKED
.
SKIP LOCKED
is a lock acquisition option that applies to both read/share (FOR SHARE
) or write/exclusive (FOR UPDATE
) locks and is widely supported nowadays:
- Oracle 10g and later
- PostgreSQL 9.5 and later
- SQL Server 2005 and later
- MySQL 8.0 and later
Now, consider we have the following post
table:
The status
column is used as an Enum
, having the values of:
PENDING
(0),
APPROVED
(1),
SPAM
(2).
If we have multiple concurrent users trying to moderate the post
records, we need a way to coordinate their efforts to avoid having two moderators review the same post
row.
So, SKIP LOCKED
is exactly what we need. If two concurrent users, Alice and Bob, execute the following SELECT queries which lock the post records exclusively while also adding the SKIP LOCKED
option:
[Alice]:
SELECT
p.id AS id1_0_,1
p.body AS body2_0_,
p.status AS status3_0_,
p.title AS title4_0_
FROM
post p
WHERE
p.status = 0
ORDER BY
p.id
LIMIT 2
FOR UPDATE OF p SKIP LOCKED
[Bob]:
SELECT
p.id AS id1_0_,
p.body AS body2_0_,
p.status AS status3_0_,
p.title AS title4_0_
FROM
post p
WHERE
p.status = 0
ORDER BY
p.id
LIMIT 2
FOR UPDATE OF p SKIP LOCKED
We can see that Alice can select the first two entries while Bob selects the next 2 records. Without SKIP LOCKED
, Bob lock acquisition request would block until Alice releases the lock on the first 2 records.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…