Трябва да проучите това от страна на сървъра, за да разберете защо изтича времето за изпълнение. Имайте предвид, че сървърът няма изчакване, изчакването е причинено от 30 секунди по подразбиране на SqlCommand.CommandTimeout
.
Добър ресурс е Чакания и опашки , което е методология за диагностициране на тесни места в производителността със SQL Server. Въз основа на действителната причина за изчакването могат да бъдат предприети подходящи действия. Трябва да установите преди всичко дали имате работа с бавно изпълнение (лош план) или с блокиране.
Ако се осмелявам да предположа, бих казал, че нездравословният модел на IF EXISTS... UPDATE
е първопричината. Този модел е неправилен и ще доведе до неуспехи при паралелност. Две едновременни транзакции, изпълняващи IF EXISTS
едновременно ще достигнат до едно и също заключение и и двете опит за INSERT
или UPDATE
. В зависимост от съществуващите ограничения в базата данни, може да се окажете в безизходица (щастливият случай) или със загубено записване (нещастният случай). Само правилното разследване обаче ще разкрие истинската първопричина. Може да е нещо съвсем различно, като събития за автоматично нарастване
.
Вашата процедура също неправилно обработва блока CATCH. Трябва винаги проверете XACT_STATE()
тъй като транзакцията може вече да е отменена до момента, в който се изпълни вашият блок CATCH. Също така не е ясно какво очаквате от именуването на транзакцията, това е често срещана грешка, която виждам, често свързана с объркване на наименувани транзакции с точки за запис. За правилен модел вижте Обработка на изключения и вложени транзакции .
Редактиране
Ето възможен начин да проучите това:
- Променете съответния
CommandTimeout
до 0 (т.е. безкрайно). - Активирайте
blocked process threshold
, задайте го на 30 секунди (предишното CommandTimeout) - Наблюдавайте в Profiler за Събитие за отчитане на блокиран процес
- Започнете работното си натоварване
- Вижте дали Profiler генерира някакви отчетни събития. Ако е така, те ще определят причината.
Тези действия ще предизвикат събитие „отчет за блокиран процес“ всеки път, когато ще получите изчакване, ако изчакването е било причинено от блокиране. Приложението ви ще продължи да чака, докато блокирането бъде премахнато, ако блокирането е причинено от заключване на живо тогава ще чака вечно.