Как атомарно выбирать строки в Mysql?

#mysql #ruby-on-rails #system.transactions

#mysql #ruby-on-rails #система.транзакции

Вопрос:

У меня более 5 одновременных процессов выбора строк из одной и той же таблицы mysql. Каждый процесс ВЫБИРАЕТ 100 строк, ОБРАБАТЫВАЕТ ИХ и УДАЛЯЕТ выбранные строки.

Но я выбираю и обрабатываю одну и ту же строку 2 или более раз.

Как я могу избежать этого на стороне MYSQL или Ruby на стороне Rails?

Приложение построено на Ruby On Rails…

Ответ №1:

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

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

И да, вернитесь к своим старым вопросам и одобрите некоторые ответы. Я видел по крайней мере один, который вы определенно пропустили.

Ответ №2:

Ответ Эрика хороший, но я думаю, что мне следует немного уточнить…

У вас есть несколько дополнительных столбцов в вашей таблице, скажем:

 lockhost VARCHAR(60),
lockpid INT,
locktime INT, -- Or your favourite timestamp.
  

По умолчанию все они равны нулю.

Затем у вас есть рабочие процессы, которые «утверждают» строки, выполняя:

 UPDATE tbl SET lockhost='myhostname', lockpid=12345,
 locktime=UNIX_TIMESTAMP() WHERE lockhost IS NULL ORDER BY id
 LIMIT 100
  

Затем вы обрабатываете заявленные строки с помощью SELECT … ГДЕ lockhost=’myhostname’ и lockpid=12345

После завершения обработки строки вы вносите все необходимые обновления и возвращаете lockhost, lockpid и locktime в значение NULL (или удаляете их).

Это останавливает обработку одной и той же строки более чем одним процессом одновременно. Вам нужно имя хоста, потому что у вас может быть несколько хостов, выполняющих обработку.

Если процесс выходит из строя во время обработки пакета, вы можете проверить, является ли столбец «время блокировки» очень старым (намного старше, чем обработка может занять, скажем, несколько часов). Тогда вы можете просто восстановить некоторые строки, которые имеют старое «время блокировки», даже если их lockhost не равен null.

Это довольно распространенный «шаблон очереди» в базах данных; он не очень эффективен. Если у вас очень высокий процент элементов, входящих / выходящих из очереди, рассмотрите возможность использования вместо этого надлежащего сервера очередей.

Ответ №3: