Eu estava inserindo dois conjuntos de dados, usando o mínimo de log, em uma tabela de heap vazia usando duas tarefas SQL de execução em execução paralela e com o SQL do seguinte formulário.
INSERT INTO Table (TABLOCK) SELECT FROM ...
Depois que o trabalho é interrompido um pouco, uma das tarefas do SQL se tornou uma vítima de conflito. Abaixo está a saída XML do gráfico de deadlock.
Alguém pode explicar o que estava acontecendo sob o capô?
<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>
As coisas ficam muito mais complicadas porque descobri que, na maioria dos casos, as duas tarefas Executar SQL podem ser executadas em paralelo com êxito. Tente abaixo:
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
Como a única diferença é a instrução SELECT ... FROM ..., parece que a instrução SELECT ... FROM ... pode afetar o modo de bloqueio aqui?
sql-server
sql-server-2008-r2
ssis
deadlock
bulk-insert
SqlWhale
fonte
fonte
Respostas:
O Guia de Desempenho de Carregamento de Dados foi escrito para o SQL Server 2008, mas, até onde posso dizer, a Microsoft não fez nenhum aprimoramento nesta área para montes. Aqui está uma cotação para o seu cenário de carregamento:
A parte importante é que você não recebe um bloqueio de BU
INSERT ... SELECT
. Você sempre terá um bloqueio exclusivo sobre a mesa, para que apenas umINSERT
possa ser executado por vez.Nos comentários, você disse que inserirá 100k linhas ou menos e que outros processos não serão executados nas tabelas durante as inserções. Ao enviar duas consultas INSERT para o banco de dados, esperaria que uma das três coisas acontecesse:
Em todos os casos, você se beneficia ou não se machuca adicionando uma
TABLOCKX
dica à consulta, de modo que é minha recomendação de solucionar o impasse. Se você quiser saber por que o impasse às vezes acontece, precisará procurar outra resposta para isso.Para um cenário diferente em que você realmente precisa de inserção paralela, duas maneiras de solucionar o problema da BU são particionar seu heap e inserir cada sessão em uma partição separada ou carregar seus dados através do BCP, BULK INSERT ou Integration Services .
fonte
Você está inserindo
dbo.TargetTable
a partir de duas sessões e ambos usandoTABLOCK
hint.Bothprocess9609dc8
eprocess5e13048
detenção processoSch-S
eIX
fechaduras que são compatíveis uns com os outros para que ambos processo pode realizar ao mesmo tempo. Mas ambos querem converterIX
bloqueio emExclusive X
tipo.X
bloqueios não são compatíveis entre si. Portanto, o SQL Server escolheu uma das sessões como vítima de impasse em vez de esperar infinitamente uma pela outra.Informações básicas de conflito.
Gráfico de Compatibilidade de Bloqueios (Mecanismo de Banco de Dados).
Detectando e encerrando impasses.
fonte