#sql-server
Вопрос:
По мере увеличения трафика на наш веб-сайт мы начинаем получать тупиковые ошибки. Я потратил бесчисленное количество часов, пытаясь понять, почему, поскольку это происходит только в запросах на ОБНОВЛЕНИЕ, и они очень просты — всегда обновляют одну строку в одной и той же таблице (разные строки по каждому запросу).
Мы извлекли информацию о взаимоблокировке из файла расширенных событий в разделе Управление в среде SQL Server Management Studio.
Вот пример:
EXEC upd_root_step1 '44F57855-74B6-4746-B615-69BCCA721BDA', '0', '0', '0', '0', '0', '0', '1', '0', '0'
Этот запрос выполняет следующее обновление:
BEGIN TRANSACTION;
UPDATE Roots SET Q1 = @Q1, Q2 = @Q2, Q3 = @Q3, Q4 = @Q4, Q5 = @Q5, Q6 = @Q6, Q7 = @Q7, Q8 = @Q8, Q9 = @Q9 WHERE RootGUID = @RootGUID
COMMIT TRANSACTION;
Второй запрос как часть ошибки взаимоблокировки является:
EXEC upd_root_card '2f2cc09b-9240-43c5-83c5-d34be93c6533',1
Это относится к:
BEGIN TRANSACTION;
UPDATE Roots SET RootOnFile = @Status WHERE RootGUID = @RootGUID
COMMIT TRANSACTION;
Больше ничего не происходит в Сохраненных вызовах Proc. Это оно. ОЧЕНЬ просто.
Насколько я понимаю, запросы одновременно блокируют таблицу, но почему?? Запросы НЕ обращаются и не обновляют одни и те же строки. В поле RootGUID нет индекса, но это uniqueindentfier
поле, я не думал, что они нужны для типов полей UID. Я завернул запросы с помощью BEGIN TRANSACTION и COMMIT TRANSACTION, но это ничего не изменило.
Я читал это о тупиках, не уверен, что это относится ко мне полностью, так как я не попадаю в тупик с ВЫБОРОМ. (READ_COMMITTED) https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms191242(v=sql.105)?redirectedfrom=MSDN
График взаимоблокировки из другой таблицы с взаимоблокировкой, которую я проследил.
Любая помощь была бы ОЧЕНЬ признательна, заранее большое вам спасибо.
Комментарии:
1. Какова структура вашей таблицы и какие индексы, ограничения, FK, зависимости и т. Д.? Все, что нужно проверить, может быть проблемой. У вас есть план выполнения, которым вы можете поделиться?
2. @Brad — ни один из запросов не обновляет ничего, что индексируется или FK. ГДЕ-это просто GUID. Это не то же самое для всех моих таблиц, но я думаю, что если я исправлю проблемы с этим, я буду знать проблемы с другими запросами, с которыми это происходит. Что касается плана выполнения, он сказал мне, что у меня должен быть индекс GUID, поэтому я добавил. Я хочу посмотреть, поможет ли это. Это очень просто — Обновление кластеризованного индекса, Параллелизм, Сканирование кластеризованного индекса (в этом случае 99,9%).
3. В предоставленных вами фрагментах блоки транзакций бесполезны. В операторе транзакции содержится только один оператор, и фиксация неявна, если вы избавляетесь от транзакции begin/commit. Я действительно не вижу смысла использовать хранимые процедуры для чего-то такого простого. Возможно, вы могли бы объединить все свои инструкции в один SP, и тогда транзакция имела бы смысл для обеспечения целостности данных. Также возможно, что ошибка вызвана другим процессом, пытающимся обновить таблицу корней.
4. Нам нужно увидеть график взаимоблокировки, чтобы помочь.
5. @Anonymous Да, я знаю о блоках. Я потратил так много времени на устранение неполадок, что пытался чем-нибудь помочь. Дейл, я опубликовал график выше из-за еще одной ошибки взаимоблокировки, которую мы получили. Я получил SP от расширенных событий — это были два звонка, которые вызвали тупик. Да, это очень простые запросы, но они повторно используются в нескольких местах, поэтому просто проще вносить изменения в SP против 10 разных страниц в коде…. спасибо всем за помощь, очень признателен.
Ответ №1:
Мы перешли от 50-100 таких ошибок в день к нулю за ночь после того, как я добавил индекс в одну таблицу для RootGUID. Похоже, проблема заключалась в индексе.
Может кто-нибудь, пожалуйста, объяснить, почему это так, чтобы я понимал движение вперед? Был ли запрос просто слишком долгим, так как не было индекса, даже если была обновлена одна запись?
Спасибо.