Многопоточность и блокировки записи БД - PullRequest
0 голосов
/ 31 июля 2009

Нужна помощь большое время ....

Мне нужно создать приложение .net, которое будет выполнять некоторые массовые операции, скажем, около 2 000 000 записей в таблице. Существует окно возможностей, в котором приложение должно запускаться и пытаться обработать как можно больше строк. Я думаю, что если у меня может быть несколько потоков приложения, берущих по 2000 записей за раз и обрабатывающих их, оно сможет обрабатывать больше. Однако это будет довольно дорого на сервере базы данных. Из того, что мне сказали, сервер БД - сложная машина, которая должна справляться с давлением.

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

Итак, я думаю, что я спрашиваю ...

1) Как я могу заставить приложение подбирать строки и блокировать их, чтобы они не были назначены другому потоку?

2) Какие интеллектуальные функции можно запрограммировать в приложении, чтобы оно могло обрабатывать то, с чего оно в последний раз остановилось?

Спасибо

KP

Ответы [ 3 ]

1 голос
/ 31 июля 2009

Я согласен с Джоном в том, что в SSIS есть много встроенного интеллекта для таких сценариев, и, вероятно, это лучшая ставка для того, чтобы тратить свое время.

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

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

with cte as (
   select top (@batchSize) *
   from myTable with (rowlock, updlock, readpast)
   where <record is ready to be processed>)
update cte
   set <mark record processing>
output inserted.*

Хитрость заключается в подсказках по блокировке, используемых в select: путем принудительной и повторной блокировки записи блокируются для обработки текущим процессором. При добавлении подсказки readpast каждый процессор будет пропускать записи, которые уже заблокированы другими процессорами. Таким образом, каждый процессор получает свою собственную серию записей @batchSize для обработки независимо от того, какая обработка выполняется.

Важно понимать, что все эти комментарии относятся к обработке, которая включает в себя что-то вне базы данных, например, выполнение вызова веб-службы, печать бумажного бланка или что-то подобное. Если вся обработка выполняется в базе данных, вы должны просто выразить ее как отдельное обновление T-SQL и позволить оптимизатору запросов использовать параллельные запросы по своему усмотрению.

1 голос
/ 31 июля 2009

Вместо того, чтобы изобретать велосипед, вы должны сделать это с помощью SQL Server Integration Services (SSIS). Он сильно оптимизирован для этих сценариев, особенно в выпуске 2008 года.

0 голосов
/ 09 августа 2013

Я бы сделал это:

  • настроить одну таблицу (изначально пустую) для хранения PK ваших основных строк. Назовите это PKs_Done_Table
  • Одна нить "выбрать бла из таблицы, в которой нет pk (выберите pk из PKs_done_Table)
  • тот же поток захватывает строки (или блоки строк - используйте NTILE или несколько операций чтения) из этого выбора и передает их другим потокам для фактической обработки.

Обработка потоков:

  • принимает строки / блоки строк
  • начать транзакцию
  • делает работу
  • вставляет pks готовой работы в PKs_done_table
  • совершает транзакцию.

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

...