Игнорирование заблокированной строки в запросе MySQL - PullRequest
6 голосов
/ 05 ноября 2010

У меня есть одна таблица, которая читается одновременно разными потоками.

Каждый поток должен выбрать 100 строк, выполнить некоторые задачи в каждой строке (не связанные с базой данных), а затем удалить выбранную строку из таблицы.

строки выбираются с помощью этого запроса:

SELECT id FROM table_name FOR UPDATE;

Мой вопрос: как я могу игнорировать (или пропустить) строки, которые были ранее заблокированы с помощью оператора select в MySQL?

Ответы [ 2 ]

15 голосов
/ 06 ноября 2010

Обычно я создаю столбец process_id со значением NULL по умолчанию, а затем каждый поток использует уникальный идентификатор для выполнения следующих действий:

UPDATE table_name SET process_id = #{process.id} WHERE process_id IS NULL LIMIT 100;

SELECT id FROM table_name WHERE process_id = #{process.id} FOR UPDATE;

Это гарантирует, что каждый поток выбирает уникальный набор строк из таблицы.

Надеюсь, это поможет.

0 голосов
/ 06 июля 2017

Несмотря на то, что это не лучшее решение, поскольку я не знаю, как игнорировать заблокированные строки, я выбираю случайную и пытаюсь получить блокировку.

START TRANSACTION;
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1);
SELECT * FROM tests.table WHERE myId=@v1 FOR UPDATE; #<- lock

Установка небольшого тайм-аута для транзакции, если эта строка заблокирована, транзакция прерывается, и я пробую другую. Если я получу блокировку, я обработаю ее. Если (неудача) эта строка была заблокирована, она обрабатывается, и блокировка снимается до истечения моего тайм-аута, тогда я выбираю строку, которая уже была «обработана»! Однако я проверяю поле, которое установили мои процессы (например, статус): если другая транзакция процесса завершилась нормально, это поле говорит мне, что работа уже выполнена, и я не обрабатываю эту строку снова.

Любое другое возможное решение без транзакций (например, установка другого поля, если строка не имеет статуса и ... и т. Д.) Может легко обеспечить условия гонки и пропущенные процессы (например, один поток внезапно умирает, выделенные данные все еще помечены, а срок действия транзакции истекает, см. комментарий здесь

Надеюсь, это поможет

...