Рекомендации по многопоточной обработке записей базы данных

у меня есть один процесс, который запрашивает таблицу для записи, где PROCESS_IND = 'N', выполняет некоторую обработку, а затем обновляет PROCESS_IND до 'Y'.

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

С чего начать?

5 ответов


шаблон, который я бы использовал, выглядит следующим образом:

  • создайте столбцы "lockedby " и" locktime", которые являются идентификатором потока/процесса/машины и меткой времени соответственно (вам понадобится идентификатор машины, когда вы разделите обработку между несколькими машинами)
  • каждая задача будет выполнять запрос, такой как:

    обновить TASKSTABLE SET lockedby=(my id), locktime=now (), где lockedby-нулевой порядок по ID LIMIT 10

где 10-это " партия размер."

  • затем каждая задача делает выбор, чтобы узнать, какие строки он "заблокирован" для обработки, и обрабатывает эти
  • после завершения каждой строки вы устанавливаете lockedby и locktime обратно в NULL
  • все это делается в цикле для всех существующих пакетов.
  • задание cron или запланированная задача периодически сбрасывает "lockedby" любой строки, время блокировки которой слишком давно, поскольку они, по-видимому, были сделаны задачей, которая зависла или разбилась. Кто-то else затем забрать их

предел 10 специфичен для MySQL, но я думаю, что другие базы данных имеют эквиваленты. ORDER BY-это импорт, чтобы избежать недетерминированности запроса.


хотя я понимаю намерение, Я бы не согласился на немедленную блокировку уровня строки. Это сократит время вашего ответа и может фактически ухудшить вашу ситуацию. Если после тестирования вы видите проблемы параллелизма с APL, вы должны сначала сделать итеративный переход к блокировке "datapage"!

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

DOL, блокировка datarow использует намного больше блокировок, чем блокировка уровня allpage/страницы. Накладные расходы на управление всеми блокировками и, следовательно, уменьшение доступной памяти из-за запросов на дополнительные структуры блокировки в кэше уменьшат производительность и противодействуют любым преимуществам, которые могут возникнуть при переходе к более параллельному подходу.

проверьте свой подход без перемещения сначала на APL (блокировка всех страниц "по умолчанию"), затем, если проблемы замечены, переместитесь в DOL (datapage first then datarow). Имейте в виду, когда вы переключение таблицы на DOL все ответы на этой таблице становятся немного хуже, таблица использует больше места, и таблица становится более склонной к фрагментации, которая требует регулярного обслуживания.

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


вы должны включить row level locking на столе с:

CREATE TABLE mytable (...) LOCK DATAROWS

затем:

  • начать транзакцию
  • выберите строку с FOR UPDATE опция (которая будет блокировать его)
  • делай, что хочешь.

никакой другой процесс не может ничего сделать с этой строкой, пока транзакция не закончится.

П. С. некоторые упоминают накладные расходы, которые могут возникнуть в результате использования LOCK DATAROWS.

Да, есть накладные расходы, хотя я бы не назвал это проблемой для такого стола.

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

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

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


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

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


преобразуйте процедуру в один оператор SQL и обработайте несколько строк как один пакет. Так должны работать базы данных.