Я вставлял два набора данных, используя минимальное ведение журнала, в пустую таблицу кучи с помощью двух параллельно выполняемых задач SQL и с помощью SQL следующей формы.
INSERT INTO Table (TABLOCK) SELECT FROM ...
После того, как задание немного зависло, одна из задач SQL стала жертвой тупика. Ниже приведен XML-вывод графа взаимоблокировки.
Может кто-нибудь объяснить, что происходило под капотом?
<resource-list>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process9609dc8" mode="Sch-S"/>
<owner id="process9609dc8" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process5e13048" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process5e13048" mode="Sch-S"/>
<owner id="process5e13048" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process9609dc8" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
</resource-list>
Все становится намного сложнее, потому что я обнаружил, что в большинстве случаев две задачи «Выполнение SQL» могут успешно выполняться параллельно. Попробуйте ниже:
Create table dbo.TablockInsert (c1 int, c2 int, c3 int)
--then issue the script in two Execute Sql Task in parallel you won't fail:
insert into dbo.TablockInsert(TABLOCK) SELECT 1, 1, 1
Поскольку единственным отличием является оператор SELECT ... FROM ..., похоже, что оператор SELECT ... FROM ... может повлиять на режим блокировки здесь?
Ответы:
Руководство по производительности загрузки данных было написано для SQL Server 2008, но, насколько я могу судить, Microsoft не внесла никаких улучшений в этой области для куч. Вот цитата для вашего сценария загрузки:
Важной частью является то, что вы не получите блокировку BU с
INSERT ... SELECT
. Вы всегда получите эксклюзивную блокировку на столе, так что только однаINSERT
может работать одновременно.В комментариях вы сказали, что вы вставите 100 000 строк или меньше, и что другие процессы не будут выполняться в таблицах во время вставок. При отправке двух запросов INSERT в базу данных я ожидаю, что произойдет одно из трех:
Во всех случаях вы либо получаете пользу, либо не получаете вреда, добавляя
TABLOCKX
подсказку к запросу, поэтому я рекомендую обходить тупик. Если вы хотите знать, почему иногда возникает тупик, вам нужно искать другой ответ для этого.В другом сценарии, в котором вам действительно требуется параллельная вставка, два способа решения проблемы BU состоят в том, чтобы разделить кучу и каждый сеанс вставить в отдельный раздел или загрузить данные через BCP, BULK INSERT или Integration Services. ,
источник
Вы вставляете данные
dbo.TargetTable
из двух сессий, и оба используютTABLOCK
hint.Both,process9609dc8
иprocess5e13048
удержание процессаSch-S
иIX
блокировки, которые совместимы друг с другом, поэтому оба процесса могут удерживаться одновременно. Но оба хотят преобразоватьIX
блокировку вExclusive X
тип.X
замки не совместимы друг с другом. Таким образом, SQL-сервер выбрал один из сеансов в качестве жертвы тупика, вместо того чтобы бесконечно ждать друг друга.Основная тупиковая информация.
Диаграмма совместимости блокировки (Database Engine).
Обнаружение и устранение тупиков.
источник