Во-первых, я не очень разбираюсь в многопоточном и параллельном программировании.Parallel.ForEach используется с NHibernate, что приводит к блокировкам SQL Server
Я пытаюсь оптимизировать работу устаревшего приложения (.Net 4
, NHibernate 2.1
).
** До сих пор обновление NHibernate
не является приоритетом, но находится в стадии разработки.
Со временем производительность стала кошмаром с ростом данных. Один элемент, который я видел, - это оператор Parallel.ForEach
, который вызывает метод, который извлекает и обновляет сложную сущность (с несколькими отношениями - пропозиции &).
Кусок кода имеет следующий форма (упрощенный для ясности):
void SomeMethod(ICollection<TheClass> itemsToProcess)
{
Parallel.ForEach(itemsToProcess, item => ProcessItem(item);
}
TheClass ProcessItem(TheClass i)
{
var temp = NHibernateRepository.SomeFetchMethod(i);
var result = NHibernateRepository.Update(temp);
return result;
}
SQL Server периодически сообщает об ошибках блокировки базы данных со следующей ошибкой:
Transaction (Process ID 20) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction
Я подозреваю, это связано с некоторыми состояниями гонки, ведущими к тупиковой ситуации, даже если ISessions
являются отдельными.
ICollection<TheClass>
может иметь до 1000 пунктов, и каждый со свойствами и суб-коллекции, которые обрабатываются, порождающих множество SELECT
и UPDATE
заявления (подтверждено с помощью «NHibernate Profiler»)
Есть ли лучший способ справиться с это параллельно, или я должен реорганизовать код в традиционный цикл?
Я знаю, что я могу в качестве альтернативы реализовать свой код с помощью:
foreach
петли в том жеISession
контексте- С сессионного
- С
Environment.BatchSize
набором разумного значением
OR
- Использование SQL BulkCopy
Я также прочитал совсем немного хорошей информации о тупиков SQL Server и Parallel.ForEach
будучи простой ловушкой:
- SQL Transaction was deadlocked
- Using SQL Bulk Copy as an alternative
- Potential Pitfalls in Data and Task Parallelism
- Multi threading C# application with SQL Server database calls
Спасибо за ваш вклад. Это действительно сложно, и возможные решения многоцелевы. Попробуете свою стратегию Retry. Другая сложность, которая добавляет больше гаечных ключей к работам, - это несколько «SELECTS» и «UPDATES», которые происходят для некоторых объектов из-за стратегии генерации ключей NHibernate. В потоках нет общего доступа к одному сеансу, как я уже говорил – user919426
Генерация ключей hilo должна выполняться в отдельной транзакции, если NHibernate делает это правильно. В этом не должно быть взаимоблокировок. Вы можете проверить это с помощью SQL Profiler. – usr