Вам нужно захватить график тупиковой ситуации. Подключите Profiler и запишите событие Граф тупиковых событий . Сохраните график .XDL и добавьте эту информацию в свой пост.
До тех пор, вполне очевидно, что для вашего запроса DB.Users.SingleOrDefault требуется индекс по крайней мере для имени, если не для имени и пароля:
CREATE INDEX idxUsersNamePassword on Users(Name,Password);
Я ожидаю, что у Пользователей уже есть индекс по ID, а у Статей есть индекс по ArticleID, который также охватывает AuthorID. Предполагая, что Users.ID и Articles.ArticleID являются PK в соответствующих таблицах, они, вероятно, являются кластеризованным ключом соответствующего, так что это правда. Стоит, однако, дважды проверить.
И, как я уже ответил вам однажды в предыдущем посте, вы решили двигаться дальше и оставить без ответа, вам следует рассмотреть возможность включения Изоляция снимков :
ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON
Кроме того, сохранение пароля в виде открытого текста является основной ошибкой.
Обновление после информации о взаимоблокировке
Существует три процесса (запроса):
- A) ... F048, на котором запущен
SELECT ... FROM Users WHERE Password = ... and Name = ...
- B) ... 0988, на котором запущен
SELECT ... FROM Users WHERE Password = ... and Name = ...
- C) ... FB88 под управлением
UPDATE ...
Цикл тупика:
- C ожидает блокировки страницы IX, блокируется S-блокировкой A
- B ожидает блокировки страницы S, блокируется блокировкой IX's C
- A ожидает на параллельных ресурсах обмена, блокируется B
Цикл поэтому C-> A-> B-> C.
Из того факта, что два задействованных SELECT решили: 1) использовать параллельный план и 2) использовать блокировки страниц, очевидно, что они выполняют сквозное сканирование всей таблицы Users. поэтому, как я и предполагал, проблема заключается в отсутствии индекса (имя, пароль) для пользователей, что приводит к тому, что запрос сканирует слишком много данных. Добавление индекса превратило бы SELECT в прямую SEEK для индекса Nc и поиска для кластеризованного индекса, и это значительно уменьшило бы окно наложения с UPDATE. В настоящее время UPDATE гарантированно конфликтует с всеми SELECT, поскольку каждый SELECT гарантированно читает каждую строку.
Добавление индекса облегчит насущную проблему. Использование изоляции моментальных снимков замаскирует проблему, поскольку сквозное сканирование будет продолжаться до тех пор, пока не будет добавлен индекс (имя, пароль). Или только (Имя), вероятно, тоже будет работать.
Для будущей масштабируемости обновление столбца Представления при каждом просмотре страницы не будет работать. Отложенное обновление, обновление количества агрегатных пакетов, вертикальное разбиение таблицы Users и удаление столбца Views являются приемлемыми альтернативами.