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
это освободит замки снова. Но это приведет к снижению общей производительности вашего сайта из-за блокировки блокировок.
Лучшим способом является определение двух утверждений (вы можете отредактировать свой вопрос и дать нам другой, когда вы его нашли) и план их выполнения. Должна быть возможность как-то переписать транзакции, чтобы получить доступ ко всем объектам в том же порядке - и предотвратить взаимоблокировку.