Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

    UPDATE taskstable SET lockedby = (мой id), locktime = now() ГДЕ заблокировано IS NULL ORDER BY ID LIMIT 10

Где 10 - "размер партии".

  • Затем каждая задача выполняет SELECT, чтобы выяснить, какие строки она "заблокирована" для обработки, и обрабатывает эти
  • После того, как каждая строка будет завершена, вы установите блокировку и время блокировки обратно на NULL
  • Все это делается в цикле для как можно большего количества пакетов.
  • Задача cron или запланированное задание периодически сбрасывает "заблокированную" любую строку, время блокировки которой слишком давно, так как они предположительно выполнялись заданием, которое зависало или разбилось. Затем кто-то другой подберет их.

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

Ответ 2

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

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

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

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

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

Ответ 3

Вы должны включить row level locking в таблице с помощью:

CREATE TABLE mytable (...) LOCK DATAROWS

Затем вы:

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

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

Р. S. Некоторые из них касаются служебных задач, которые могут возникнуть в результате использования LOCK DATAROWS.

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

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

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

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

Ответ 4

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

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

Ответ 5

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