Причина того, що процес є жертвою тупикової ситуації


105

У мене є процес із Select, який потребує тривалого часу, на замовлення від 5 до 10 хвилин.
Наразі я не використовую NOLOCK як підказку до двигуна бази даних MS SQL.
У той же час у нас є ще один процес, який здійснює оновлення та вставки в ту саму базу даних і ті самі таблиці.
Перший процес розпочався, нещодавно передчасно закінчившись повідомленням

SQLEXCEPTION: трансакція зайшла в тупик на ресурсах блокування з іншим процесом і була обрана в якості жертви тупикового кута.

Цей перший процес працює на інших сайтах в однакових умовах, але з меншими базами даних, і, таким чином, відповідний оператор select займає набагато коротший проміжок часу (приблизно 30 секунд). На цих інших сайтах я не отримую повідомлення про тупик на цих інших сайтах. Я також не отримав цього повідомлення на сайті, який спочатку має проблеми, але, я припускаю, що база даних зросла, я вважаю, що, мабуть, переступив якийсь поріг. Ось мої запитання:

  1. Чи може час, який потрібен для здійснення транзакції, зробить пов’язаний процес більш імовірним, що він буде позначений як жертва тупикової ситуації.
  2. Якщо я виконаю виділення з підказкою NOLOCK, чи усуне це проблема?
  3. Я підозрюю, що поле дати, яке перевіряється як частина пункту WHERE в операторі select, викликає повільний час пошуку. Чи можна створити індекс на основі цього поля? Це доцільно?

Часткова відповідь на пункт 1: Не плутайте тупик із тайм-аутом. Якщо ви зазнали тайм-ауту, то час, пов'язаний з закінченням однієї транзакції, може бути відповідальним за інший, який закінчується. Крім того, було б корисно знати, на якому ресурсі ви забуваєте (це індекс чи таблиця?).
NealB

1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow

Відповіді:


128

Q1: Чи може час, який потрібен для здійснення транзакції, зробить пов’язаний процес більш імовірним позначенням жертви тупикового кута.

Ні. SELECT є жертвою, оскільки вона мала лише прочитані дані, тому транзакція пов'язана з меншою вартістю, тому вона вибирається як жертва:

За замовчуванням Database Engine вибирає в якості жертви тупик сеанс, який виконує транзакцію, яка є найменш дорогою для повернення назад . Крім того, користувач може вказати пріоритет сеансів у ситуації тупикового зв'язку, використовуючи SET DEADLOCK_PRIORITYоператор. DEADLOCK_PRIORITY може бути встановлено як LOW, NORMAL або HIGH, або ж можна встановити будь-яке ціле значення в діапазоні (-10 до 10).

Q2. Якщо я виконаю виділення з підказкою NOLOCK, чи усуне це проблема?

Ні. З кількох причин:

Q3. Я підозрюю, що поле дати, яке перевіряється як частина пункту WHERE в операторі select, викликає повільний час пошуку. Чи можна створити індекс на основі цього поля? Це доцільно?

Ймовірно. Причиною тупикової ситуації є майже ймовірність погано індексованої бази даних. 10 хвилин запити прийнятні в таких вузьких умовах, що я на 100% впевнений, що у вашому випадку не є прийнятним.

З 99% впевненістю заявляю, що ваш глухий кут вирішується великим скануванням таблиці, що суперечить оновленням. Почніть із захоплення графіка тупикового кута, щоб проаналізувати причину. Вам, швидше за все, доведеться оптимізувати схему вашої бази даних. Перш ніж робити будь-які модифікації, прочитайте цю тему Проектування індексів та підрозділів.


Дякую за ретельну відповідь. Я думаю, я все ще маю одне питання. Чому б я опинився в тупиковій ситуації лише в одному середовищі, а не в іншому. Хоча програмне забезпечення те саме. Ваша відповідь говорить про те, що тривалість виконання запиту Select не має значення, і саме факт вибору запиту сам по собі викликає збій. Але тоді, чому лише тоді, коли запит вибору потребує тривалого часу?
Елліотт

4
Тривалість запиту не має значення для вибору жертви тупикової ситуації . Це робить різницю в спричиненні тупикової ситуації принаймні двома факторами: 1) прості ймовірності. Чим довше запит, тим більша ймовірність перекриття одночасних оновлень та попадання в тупикові місця. 2) більша таблиця може використовувати зовсім інший план запитів, який може сприйняти тупикові місця.
Рем Русану

12

Ось як насправді виникла ця конкретна проблема з тупиком та як вона насправді була вирішена. Це досить активна база даних з 130K транзакцій, що відбуваються щодня. Індекси в таблицях цієї бази спочатку були кластеризовані. Клієнт просив нас зробити індекси некластеризованими. Як тільки ми це зробили, починався тупик. Коли ми відновили індекси як кластеризовані, тупик зупинився.


34
Хтось може пояснити, чому? (Чарівні рішення не дуже корисні)
OGrandeDiEnne

1
Цей хлопець пояснює це у своєму дописі: mssqltips.com/sqlservertip/2517/…
siga0984

6

Відповіді тут варто спробувати, але ви також повинні переглянути свій код. Зокрема, прочитайте відповідь Polyfun тут: Як позбутися тупикової ситуації в додатках SQL Server 2005 та C #?

Це пояснює проблему одночасності та те, як використання "з (updlock)" у ваших запитах може виправити ситуацію з тупиком - залежно від того, що саме робиться у вашому коді. Якщо ваш код відповідає цій схемі, це, швидше за все, краще зробити виправлення, перш ніж вдаватися до брудних читань тощо.


0

Хоча @ Ремус Русану вже є чудовою відповіддю, у випадку, якщо хтось з нетерпінням чекає кращого розуміння причин тупикової ситуації SQL Server та стратегій відстеження, я б запропонував вам прочитати " Бреда МакГіхі " Як відстежувати тупики за допомогою Profiler SQL Server 2005

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.