Лучший способ реализовать очередь заданий в системе реляционной базы данных - использовать SKIP LOCKED .
SKIP LOCKED - это опция получения блокировки, которая применяется как к блокировкам чтения / обмена (FOR SHARE), так и блокировки записи / эксклюзива (FOR UPDATE) и широко поддерживается в настоящее время:
- Oracle 10g и более поздние версии
- PostgreSQL 9.5 и более поздние версии
- SQL Server 2005 и более поздние версии
- MySQL 8.0 и более поздние версии
Теперь рассмотрим следующую таблицу post
, которая используется в качестве очереди заданий:
CREATE TABLE post (
id int8 NOT NULL,
body varchar(255),
status int4,
title varchar(255),
PRIMARY KEY (id)
)
Столбец status
используется в качестве Enum и имеет значения PENDING (0), APPROVED (1) или SPAM (2).
Если у нас есть несколько одновременно работающих пользователей, пытающихся модерировать записи post
, нам нужен способ координировать их усилия, чтобы два модератора не просматривали одну и ту же строку post
.
Итак, SKIP LOCKED - это именно то, что нам нужно. Если два одновременно работающих пользователя, Алиса и Боб, выполняют следующие запросы SELECT, которые блокируют только записи записей, одновременно добавляя параметр SKIP LOCKED:
[Alice]:
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
[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
Мы видим, что Алиса может выбирать первые две записи, а Боб выбирает следующие две записи. Без SKIP LOCKED запрос на получение блокировки Боба будет блокироваться, пока Алиса не снимет блокировку с первых 2 записей.
Подробнее о SKIP LOCKED читайте в этой статье .