Редактировать: Решено, в таблице был триггер с петлей (читайте мой собственный ответ ниже).
У нас есть простой оператор удаления, который выглядит так:
DELETE FROM tablename WHERE pk = 12345
Это просто зависает, нет тайм-аута, ничего.
Мы рассмотрели план выполнения, и он состоит из множества поисков по связанным таблицам, чтобы гарантировать, что никакие внешние ключи не вызовут ошибку при удалении, но мы убедились, что ни в одной из этих других таблиц нет строк, относящихся к этой конкретной строке.
В настоящее время к базе данных не подключен другой пользователь.
Мы запустили DBCC CHECKDB против него, и он выдает 0 ошибок.
Глядя на результаты sp_who и sp_lock во время зависания запроса, я заметил, что мой spid имеет множество блокировок PAG и KEY, а также периодическую блокировку TAB.
Таблица имеет 1.777.621 строк, и да, pk - это первичный ключ, поэтому это удаление одной строки на основе индекса. В плане выполнения нет сканирования таблицы, хотя я заметил, что он содержит что-то, что говорит Катушка стола (Стремительная катушка), но говорит «Приблизительное количество строк» 1. Может ли это быть действительно замаскированное сканирование таблицы? Он только говорит, что смотрит на столбец первичного ключа.
Пробовал DBCC DBREINDEX и UPDATE STATISTICS на таблице. Оба завершены в разумные сроки.
К сожалению, в этой конкретной таблице содержится большое количество индексов. Это основная таблица в нашей системе с множеством столбцов и ссылок, как исходящих, так и входящих. Точное количество: 48 индексов + кластеризованный индекс по первичному ключу.
На что еще посмотреть?
Также обратите внимание, что в этой таблице раньше не было этой проблемы, эта проблема возникла внезапно сегодня. У нас также есть много баз данных с одинаковыми настройками таблиц (копии клиентских баз данных), и они ведут себя так, как ожидалось, только эта проблема проблематична.


Попробуйте воссоздать индекс для этой таблицы и попробуйте восстановить статистику.
Отсутствует одна часть информации - это количество индексов в таблице, из которой вы удаляете данные. Поскольку SQL Server использует первичный ключ в качестве указателя в каждом индексе, любое изменение первичного индекса требует обновления каждого индекса. Хотя, если мы не говорим о большом количестве, это не должно быть проблемой.
Из вашего описания я предполагаю, что это основная таблица в базе данных, на которую ссылаются многие другие таблицы в отношениях FK. Это объясняет большое количество блокировок, поскольку он проверяет остальные таблицы на наличие ссылок. И, если у вас включено каскадное удаление, это может привести к удалению в таблице, что потребует проверки нескольких таблиц в глубину.
Хорошо, это неловко.
Некоторое время назад коллега добавил в эту таблицу триггер, и в триггере была ошибка. Хотя он исправил ошибку, триггер для этой таблицы так и не был воссоздан.
Таким образом, сервер фактически ничего не делал, он просто делал это огромное количество раз.
Ну что ж...
Спасибо за внимание всем, кто прочитал это и задумался над проблемой.
Я собираюсь принять ответ Йозефа, поскольку он был наиболее близким и косвенно затрагивал проблему каскадных удалений.
Вы исправили триггер, чтобы не использовать цикл, не так ли? Триггер почти никогда не должен содержать курсора или цикла.