У меня есть таблица в MySQL, которая представляет очередь ссылок для обработки. Ссылки обрабатываются внешним приложением, одно за другим, и в конце удаляются. Это очередь большого объема, и у меня есть несколько экземпляров приложения обработки, которые распределены по нескольким серверам.
Как я могу гарантировать, что каждая запись выбирается только одним приложением? Есть ли способ пометить / заблокировать запись?
Прямо сейчас, чтобы избежать двух или более перехватов одной и той же ссылки, я разрешаю каждому экземпляру собирать только определенный набор записей (основанный на MOD их идентификатора), но это не прозрачный способ увеличить обработку очереди. скорость, просто добавляя новые экземпляры.
Ответы:
Во-первых: MySQL является одним из худших компонентов программного обеспечения для реализации, особенно если он очень динамичный. Причина в том, что механизмы, такие как MEMORY и MyISAM, имеют только блокировки полной таблицы, в то время как более подходящие механизмы, такие как InnoDB, имеют более высокий штраф на запись (для предоставления свойств ACID) и оптимизированы для доступа к записям, которые пространственно и временно закрыты (те, которые установлены в памяти). ). Также нет хорошей системы уведомлений об изменениях для MySQL - она должна быть реализована как опрос. Существуют десятки программ, более оптимизированных для этой задачи .
Сказав это, я видел успешную реализацию такого рода доступа, если требования к производительности / эффективности не очень высоки. Многие люди не могут позволить себе внедрить и поддерживать отдельный отдельный элемент технологии только для небольшой части бизнес-логики.
SELECT FOR UPDATE
это то, что вы ищете - читайте сериализацию. Хотя UPDATE / DELETE всегда блокирует строку во время выполняющейся транзакции MYSQL, вы можете избежать большой транзакции во время процесса, поэтому:MySQL позаботится о блокировке всех одновременных выборок, кроме одной, при выборе строк. Поскольку это может привести к большому количеству заблокированных соединений одновременно, сделайте начальную транзакцию как можно меньше и попытайтесь обрабатывать больше одной строки за раз.
источник
Как я объяснил в этой статье , в MySQL 8 появилась поддержка SKIP LOCKED и NO WAIT.
SKIP LOCKED полезен для реализации очередей заданий (так называемых пакетных очередей), так что вы можете пропустить блокировки, которые уже заблокированы другими параллельными транзакциями.
NO WAIT полезен для избежания ожидания, пока параллельная транзакция не снимет блокировки, которые мы также заинтересованы в блокировке. Без НИКАКОГО ПОДОЖДЕНИЯ мы должны либо дождаться снятия блокировок (во время фиксации или разблокирования транзакцией, которая в данный момент удерживает блокировки), либо истечения времени ожидания получения блокировок. Следовательно, NO WAIT действует как тайм-аут блокировки со значением
0
.Для более подробной информации о SKIP LOCK и NO WAIT, ознакомьтесь с этой статьей .
источник
Я сделал что-то подобное с автономными проверками DBCC (два сервера делают резервные копии, а затем проверяют DBCC). Один сервер собирает все резервные копии 31 сервера вчера и помещает их в очередь, а затем этот сервер, а другой получает из этой очереди. Хотя не так много серверов, метод должен оставаться прежним: сервер приложений должен выполнить запрос обновления для очереди, обновляющей поле даты / времени и поле «сервер приложений» с именем этого сервера приложений или, что еще лучше, с числовым идентификатором. Это приведет к блокировке или, если блокировка уже получена от другого сервера, получающего следующую строку, она будет заблокирована и будет ждать, пока другое приложение завершит получение следующей строки. Затем вы захотите, чтобы приложение извлекало самую последнюю запись из очереди для своего поля приложения и получало из нее любую информацию, которую вы хотите. Используя MySQL '
источник