Чи є спосіб запобігти тупиковість, зберігаючи ті самі запити?
Графік тупикового кута показує, що саме цей тупик був тупиком конверсії, пов’язаним з пошуком закладок (у цьому випадку пошук RID):

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