Предотвращение взаимоблокировки при использовании блокировки строк без столкновения - PullRequest
0 голосов
/ 10 июля 2019

У меня есть простая таблица Item с парой дюжин столбцов, а первичный ключ - 2 столбца, ItemId nvarchar(20) и Tag nvarchar(200).

Мы уже переключили все операторы select на использование WITH (NOLOCK) просточтобы убедиться в следующем:

SELECT ItemId, Tag, Description FROM Item WITH (NOLOCK) WHERE Tag LIKE 'PART_00%'

Теперь у меня есть главный сервер, который получает задание, и он должен удалять и воссоздавать каждый полученный элемент.Этот сервер берет список всего, что нужно сделать (без дублирования), затем разбивает этот список на множество частей и отправляет каждый из этих подсписков на другие серверы.Эти другие серверы делают простые вещи:

  1. Удалить деталь из базы данных
  2. Сделайте некоторую работу с файлами и тому подобным
  3. Создайте новую запись в базе данных

Теперь для реальной проблемы у меня был PageLock тупик, поскольку SQL увеличивал RowLock до PageLock из-за ресурса.На самом деле нас это не волнует, поэтому я отключил повышение блокировки таблицы и изменил запрос на удаление, чтобы убедиться, что мы используем RowLock, так что это запрос

DELETE FROM Item WITH (ROWLOCK) WHERE Tag LIKE 'PART_0010C'

Теперь мы получаем KeyLock на первичных ключах для этой таблицы, хотя мы делаем все, чтобы использовать RowLock.На основании System_health:event_file я получаю столкновение с 2 совершенно разными значениями pk.Как это вообще возможно ?Запросы также НЕ находятся в транзакции, чтобы гарантировать отсутствие циклической блокировки любого типа.

Здесь ниже вы ясно видите, что 2 совершенно отдельных соединения, pId 109 и 111, которые выполняют только оператор удаления, показанный выше, создаютKeyLock даже при том, что фактический запрос находится на 2 различных конкретных значениях pk.

enter image description here Пробовал разные запросы ради него и теперь вместо использования LIKE для удаленияя использую =.Причина, по которой мне нужно использовать LIKE, заключается в том, что какой-то другой процесс, который выполняется в нерабочее время, удалит с помощью LIKE, так как необходимо удалить много записей, и они начинаются с определенного Tag, поэтому массовое удаление происходит намного быстрее.Во всяком случае, использование = не решило проблему.У меня еще много KeyLock.

...