Я создаю «систему обслуживания бедных людей» с использованием MySQL. Это отдельная таблица, содержащая задания, которые необходимо выполнить (имя таблицы - queue
). У меня есть несколько процессов на нескольких машинах, чья задача заключается в вызове fetch_next2
sproc, чтобы получить элемент из очереди.Блокировка строк в строке и атомные обновления
Весь смысл этой процедуры заключается в том, чтобы мы никогда не позволяли двум клиентам получать ту же работу. Я думал, что с помощью SELECT .. LIMIT 1 FOR UPDATE
я бы заблокировал одну строку, чтобы я мог убедиться, что она была обновлена только одним вызывающим абонентом (обновлено так, что оно больше не соответствует критериям SELECT
, используемым для фильтрации заданий, которые являются «ГОТОВЫ «для обработки»).
Может ли кто-нибудь сказать мне, что я делаю неправильно? У меня просто были случаи, когда одна и та же работа была отдана двум различным процессам, поэтому я знаю, что она не работает должным образом. :)
CREATE DEFINER=`masteruser`@`%` PROCEDURE `fetch_next2`()
BEGIN
SET @id = (SELECT q.Id FROM queue q WHERE q.State = 'READY' LIMIT 1 FOR UPDATE);
UPDATE queue
SET State = 'PROCESSING', Attempts = Attempts + 1
WHERE Id = @id;
SELECT Id, Payload
FROM queue
WHERE Id = @id;
END
Почему так у меня проблемы с построением очереди бедных? Почему бы не использовать настоящую очередь. Лот меньше пота – middlestump
@middlestump: Но это меньше 10 строк кода. :) Кроме того, мне бы очень хотелось понять, как эта строка-блокировка работает в MySQL для других проектов. – skb