Не могли бы вы попробовать некоторые альтернативные критерии? Я играл с этим методом в последнее время (только я использую NULL не 0 для обозначения всех значений):
SET @yId = NullIf(@yId, 0);
SET @xId = NullIf(@xId, 0);
...
WHERE
@yId BETWEEN Coalesce(@yId, 0) AND Coalesce(@yId, 2147483647)
AND @xId BETWEEN Coalesce(@xId, 0) AND Coalesce(@xId, 2147483647)
Или вы можете использовать ваши нули без изменений:
WHERE
@yId BETWEEN @yId AND Coalesce(NullIf(@yId, 0), 2147483647)
AND @xId BETWEEN @xId AND Coalesce(NullIf(@xId, 0), 2147483647)
Подумав немного об этом ... просто для обзора, взаимоблокировки возникают только из-за противоречивого порядка получения ресурсов. Ресурс - это не просто таблица, а строки, экстенты, страницы и т. Д. Если одновременно отправляются два запроса, которые первоначально приобретают меньшую блокировку гранулярности, затем увеличивают их блокировки до чего-то, что перекрывает меньшую блокировку, которую имеет другой процесс, затем Вы зашли в тупик.
Итак, есть ли способ, которым вы можете либо получить более крупную блокировку раньше, избежать получения более крупной конфликтующей блокировки или изменить порядок получения ресурса?
Вы можете поэкспериментировать с использованием WITH (TABLOCKX)
, что звучит ужасно, но если ваш @yId или @xId равен 0, что заставляет вас выбирать все строки, вам все равно понадобится вся таблица.
Рассматривали ли вы также попытку OPTION (MAXDOP 1)
, просто чтобы посмотреть, поможет ли это? Теоретически наличие нескольких потоков для одного и того же запроса данных может увеличить вероятность одновременного получения конфликтующих блокировок.
Есть ли в таблице кластеризованный индекс? Если нет, добавьте его, и если да, то он используется или вы можете заставить его использовать? Это может привести к тому, что запросы получат доступ к таблице по-другому, что предотвратит взаимоблокировку.
Опубликуйте ваши комментарии, и я посмотрю, появятся ли еще какие-либо идеи на основе ваших ответов.