Чи є спосіб запобігти тупиковість, зберігаючи ті самі запити?
Графік тупикового кута показує, що саме цей тупик був тупиком конверсії, пов’язаним з пошуком закладок (у цьому випадку пошук RID):
Як зазначається в запитанні, загальний ризик тупикової ситуації виникає через те, що запити можуть отримувати несумісні блокування на одних і тих же ресурсах у різних замовленнях. SELECT
Запит необхідно отримати доступ до індексу перед таблицею в зв'язку з RID пошуку, в той час як UPDATE
модифікує запит таблиці, а потім індекс.
Усунення глухого кута вимагає видалення одного з інгредієнтів тупикового зв'язку. Нижче наведено основні варіанти:
- Уникайте пошуку RID, роблячи некластеризоване покриття індексу. Це, мабуть, у Вашому випадку не практично, оскільки
SELECT
запит повертає 26 стовпців.
- Уникайте пошуку RID, створюючи кластерний індекс. Це передбачає створення кластерного індексу на стовпчику
Proposal
. Це варто врахувати, хоча, здається, цей стовпець має тип uniqueidentifier
, який може бути, а може і не бути хорошим вибором для кластерного індексу, залежно від ширших питань.
- Під час читання уникайте спільних блокувань, вмикаючи параметри бази даних
READ_COMMITTED_SNAPSHOT
або SNAPSHOT
бази даних. Це вимагає ретельного тестування, особливо стосовно будь-яких розроблених блокуючих дій. Тригер-код також потребує тестування, щоб переконатися, що логіка працює належним чином.
- Уникайте брати спільні блокування під час читання, використовуючи рівень
READ UNCOMMITTED
ізоляції для SELECT
запиту. Застосовуються всі звичні застереження.
- Уникайте одночасного виконання двох запитуваних питань, використовуючи ексклюзивне блокування програми (див. Sp_getapplock ).
- Використовуйте підказки блокування таблиці, щоб уникнути одночасності. Це більший молот, ніж варіант 5, оскільки він може вплинути на інші запити, а не лише на два, визначені у питанні.
Чи можу я якось взяти X-Lock на індекс в транзакції оновлення перед оновленням, щоб переконатися, що таблиця та доступ до індексу в одному порядку
Ви можете спробувати це, обгортання поновлення в явній транзакції і виконанні SELECT
з XLOCK
натяком на некластерізованний значенні індексу перед оновленням. Це покладається на те, що ви точно знаєте, що таке поточне значення в некластеризованому індексі, правильний план виконання та правильне передбачення всіх побічних ефектів зняття цього додаткового блокування. Він також покладається на те, що двигун блокування не є достатньо розумним, щоб уникнути зняття блокування, якщо він вважається зайвим .
Коротше кажучи, хоча це в принципі можливо, я не рекомендую його. Занадто легко щось пропустити або перехитрити себе творчо. Якщо ви справді повинні уникати цих тупиків (а не просто їх виявляти та повторювати), я б радив вам заглянути більш загальні рішення, перелічені вище.