SQL Server тупик между двумя операторами обновления

У меня есть веб-сайт, на котором есть очень популярный форум, и иногда в течение дня я вижу несколько тупиковых ситуаций, возникающих между двумя одинаковыми (за исключением данных внутри них) обновлениями на одном и том же форуме. Я не совсем уверен, почему это происходит с этим запросом, так как на сайте есть много других запросов, которые работают с высокой степенью параллелизма без проблем.

Обновление графика тупиковой ситуации

Полное изображение

Запрос между двумя процессами почти идентичен, график показывает его как:

update [Forum] set [DateModified] = @DateModified, [LatestLocalThreadID] = @LatestLocalThreadID where ID = 310     

Может кто-нибудь пролить свет на то, что может быть причиной этого?

2 ответа

Это потому, что есть внешний ключ к ForumThreads который генерирует S-замок при установке LatestLocalThreadID (чтобы убедиться, что строка еще существует, когда инструкция завершается). Возможное исправление будет состоять в том, чтобы префикс оператора обновления

SELECT *
FROM ForumThreads WITH (XLOCK, ROWLOCK, HOLDLOCK)
WHERE ID = @LatestLocalThreadID 

для того, чтобы X-Lock на это. Вы также можете попробовать UPDLOCK как менее агрессивный режим. Это, конечно, может вызвать взаимные блокировки в других местах, но это лучшая первая попытка.

По сути, взаимоблокировки предотвращаются путем доступа к объектам (таблицам, страницам, строкам) всегда в том же порядке. В вашем примере есть один доступ к процессу forum первый и forumThread второй и другой поток делают это наоборот. update обычно сначала ищет строки для обновления и использует S-блокировки во время поиска. Строки, которые он определил как подлежащие изменению, блокируются X-замками, и тогда происходит реальное изменение.

Быстрые и грязные решения могут быть сделать begin Tran затем lock объекты в нужном вам порядке и выполните обновление с последующим commit это освободит замки снова. Но это приведет к снижению общей производительности вашего сайта из-за блокировки блокировок.

Лучшим способом является определение двух утверждений (вы можете отредактировать свой вопрос и дать нам другой, когда вы его нашли) и план их выполнения. Должна быть возможность как-то переписать транзакции, чтобы получить доступ ко всем объектам в том же порядке - и предотвратить взаимоблокировку.

Другие вопросы по тегам