MySQL / немного о SELECT… FOR UPDATE и GET_LOCK

в 19:09, , рубрики: mysql, базы данных, метки: ,

MySQL / немного о SELECT… FOR UPDATE и GET_LOCK
Для примера рассмотрим такой случай.
У нас есть MySQL база, в которой есть таблица queue. В эту таблицу поступают задания для выполнения.
Задания должны распределяться между процессами. Одна и та же задача не должна попасть к разным процессам.
Для решения задачи можно воспользоваться SELECT … FOR UPDATE.
Каждый процесс для получения задачи будет выполнять вот такой запрос.SELECT id FROM queue WHERE is_run = 0 ORDER BY date_task ASC LIMIT 1 FOR UPDATE
И помечать эту полученную задачу как занятую.UPDATE queue SET is_run = 1 WHERE id = ?
Теперь рассмотрим диаграмму работы процессов.
Процессы выполняются последовательно. Получается, что FOR UPDATE блокирует всю таблицу?
Но на самом деле, все не так как кажется на первый взгляд. FOR UPDATE блокирует выбранные записи, а не всю таблицу. А остальные запросы зависли в ожидании только потому, что, они хотят выбрать туже запись, что и первый процесс.
Правильнее здесь будет не блокировать запись на длительное время. Или можно выбирать случайные записи. Это уже зависит от задачи, главное это то, что разные процессы не получат одну задачу.
А что если время блокировки будет очень большим? Как сделать так, чтобы процесс не завис в ожидании на долгое время?
Для этого есть GET_LOCK, который работает как mutex и позволяет задать время ожидания.
Тогда запросы будут примерно такие.SELECT GET_LOCK('lock1', 3);
Если получили 1SELECT id FROM queue WHERE is_run = 0 ORDER BY date_task ASC LIMIT 1
UPDATE queue SET is_run = 1 WHERE id = ?
SELECT RELEASE_LOCK('lock1')

  1. iphone:

    можно наверно еще вот так сделать

    http://habrahabr.ru/post/54176/

    тогда записи с определенной долей вероятности будут выбираться

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js