Вы встретили более эзотерического зверя: тупик ресурса. Имеется поток, который не может порождать дочерние задачи (sys.dm_os_tasks
) для выполнения своей работы, поскольку все рабочие (sys.dm_os_workers
) заняты. В свою очередь, занятые работники выполняют задачи, которые, вероятно, заблокированы, вероятно, обычными замками, жертвой.
Есть два урока, которые я вижу здесь, чтобы взять их домой:
1) ОБНОВЛЕНИЕ, которое вы опубликовали, пытается идти параллельно. Если обновление точно такое, как вы опубликовали, это означает одно и только одно: нет индекса на rowId
.
2) Вы отскочили от верхнего потолка, установленного настройкой max worker threads
. Неудивительно, учитывая, что вы злоупотребляете потоками в клиенте (hundreds of concurrent threads to execute thousands of task
) и умножаете это на сервере из-за нежелательного параллелизма.
Разумный дизайн будет использовать асинхронное выполнение (BeginExecuteNonQuery
) на истинно асинхронном соединении (AsynchronousProcessing=true
) и использовать пул ожидающих запросов, чтобы он не шел выше определенный порог. Еще более вероятно, что вы передадите весь пакет значений обновления с помощью табличного параметра *1027*, а затем обновите весь набор или строки в виде пакета в одном выражении. Я понимаю, что все мои ссылки предназначены для .Net, а не для Java, мне все равно, вы можете сами найти эквивалентную функциональность Java.
Так что, хотя интересно, что вы обнаружили такой эзотерический тупик, он появляется только потому, что ваш дизайн, ну ... отстой.