@QPrincess

Как временно скрыть строку из таблицы?

Несколько скриптов одновременно делают запросы каждую секунду:
SELECT id FROM `post` WHERE `data` = '1' LIMIT 1;
Каждый скрипт выполняет работу и после делает UPDATE `data` = '2'

Как временно скрыть выбранную строку из таблицы, чтобы другие скрипты не наткнулись на этот же id и не выполняли работу повторно?
  • Вопрос задан
  • 718 просмотров
Решения вопроса 1
FanatPHP
@FanatPHP
Чебуратор тега РНР
Если отвечать на вопрос, который вынесен в заголовок, то это возможно только в mysql 8, при блокировке с использованием опции SKIP LOCKED.

Если же версия другая (и если решать проблему, которая стоит перед автором), то возможны варианты.

Например добавить третий статус, "обработка".
То есть скрипт выбирает строку, ставит статус 3, завершает обработку, и потом стиавит 2.
Только в этом случае будут иметь смысл блокировки, хотя я все равно не очень вижу, что тут блокировать, кроме всей таблицы целиком, а это как бы не замедлило весь процесс еще больше. В общем, все зависит от времени, которое требуется на обработку строки.
Если обработка быстрая, то пусть выполняют работу повторно.
Если долгая, то лочить строки со статусом 2 на чтение, выбирать строку, сразу ставить ей статус 3, анлочить все строки, обрабатывать полученную, ставить статус 2.
Плюс добавить еще поле время смены статуса и периодически собирать зависшие в 3 статусе

Более жизненный вариант (опять же, для решения проблемы, а не вопроса) - это каждый воркер работает со своим блоком данных . например, один выбирает только id, которые кончаются на 1, второй - на 2 - и так далее. можно придумать более-менее равномерный алгоритм, чтобы воркеры не мешали друг другу, на тех же принципах, на которых делается шардирование.

Ну а самый простой и надёжный - это ставить строке уникальный идентификатор, UUID вполне подойдет.
Тогда вместо селект+апдейт можно делать сразу апдейт (с условием, которое раньше шло в селект)

update table set guid = {$UUID} where ... limit 1;
... много кода ...
update table set .... guid = null where guid = {$UUID};
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы