I означает «намеренную» блокировку, и они всегда связаны с иерархиями. Поскольку менеджер блокировок не понимает физическую структуру, он не может соблюдать иерархические блокировки, поэтому иерархия воссоздается в намеренных блокировках.
В вашем случае INSERT имеет намеренную блокировку на странице. Это означает, что он также получил блокировку X для строки на странице, что является нормальным поведением. Теперь он пытается получить новую блокировку IX, поэтому ему, вероятно, нужно вставить строку на другой странице. Это было бы нормальным поведением вставки в таблицу с несколькими индексами: первый IX находится на одном из индексов (возможно, кластеризованных), а второй IX - на некластеризованном индексе.
SELECT, как вы говорите, возвращается через 12 секунд, поэтому это длинный запрос для большого набора данных, и план, вероятно, выбрал высокую степень детализации блокировки, блокировки страницы. У SELECT есть S-блокировка на странице, для которой INSERT требуется блокировка IX, и требуется еще одна S-блокировка на странице, для которой INSERT имеет блокировку IX.
Это тривиальный тупик, и его очень легко исправить: убедитесь, что ваш SELECT не нуждается в этих S-блокировках страницы. Это не ошибка вставки здесь. Не зная, что делает SELECt, я не могу точно сказать, является ли это оптимальным или нет. По моему опыту, почти всегда у SELECT, подобного этому, есть много, много и гораздо больше возможностей для совершенствования (например, сам SELECT или схема под ним).
Но при условии, что SELECT является оптимальным, ваша самая простая карта выхода из тюрьмы - это включить управление версиями строк :
ALTER DATABASE <dbname> SET ALLOW_SNAPSHOT_ISOLATION ON;
ALTER DATABASE <dbname> SET READ_COMMITTED_SNAPSHOT ON;
Обновление:
На самом деле при втором чтении очевидно, что INSERT имеет блокировки для разных таблиц (если только вы не изменили XML, который выглядит отредактированным здесь и там), поэтому ваше объяснение того, как действует вставка , должно быть ошибочным , INSERT является частью транзакции, которая, по крайней мере, сделала две записи: одну в Table1 и одну в Table2. Но это не сильно меняет проблему или решение. Это правда, что у вас есть возможность разделить две записи в транзакции на отдельные транзакции, но это, очевидно, худший путь.