Как правильно блокировать записи в MySQL?

Есть таблица с данными. Приложение в многопоточном режиме обращается в таблице и берет строки из нее для обработки, после обработки строка должна быть обновлена.

  1. Как избежать того что 2 потока возьмут в работу одну и ту же строку?
  2. Что будет если приложение прервется с ошибкой во время обработки строк? Взятые в работу строки будут заблокированы СУБД? Как избежать проблем с этим на случай вылета приложения?

Ответы (1 шт):

Автор решения: Roman-Stop RU aggression in UA

Используйте SELECT ... FOR UPDATE SKIP LOCKED. В транзакции делайте запрос типа такого, чтоб выбрать какое-то количество записей для обработки

SELECT * 
FROM job_queue FOR UPDATE SKIP LOCKED
ORDER BY some_field
LIMIT <batch_size>

Обработав записи делайте обычный UPDATE записей которые выбрал запрос ранее, ну там помечайте статус, что они уже обработаны или вообще удаляйте их (главное чтоб новый SELECT запрос их не получал), и фиксируйте транзакцию (делайте commit).

Тут SKIP LOCKED как раз избегает проблемы #1, т.е. того, что два обработчика возьмут одну и ту же запись.

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

→ Ссылка