Deadlocks de bloqueios nas mesmas tabelas temporárias em diferentes processos

17

Eu encontrei um impasse que parece mostrar algo que eu achava impossível. Existem dois processos envolvidos no conflito:

1. process8cf948 SPID 63

  • Executando um ALTER TABLE na tabela temporária #PB_Cost_Excp_Process_Invoices_Work.

  • Possui o bloqueio IX na tabela #PB_Cost_Excp_Process_Invoices_Work com o ID do objeto 455743580

2. process4cb3708 SPID 72

  • Executando UPDATE na tabela temporária #PB_Cost_Excp_Process_Invoices_Work, que deveria ser sua própria cópia exclusiva da tabela.

  • Possui o bloqueio Sch-M em #PB_Cost_Excp_Process_Invoices_Work com o mesmo ID de objeto 455743580 !

Isso deveria ser impossível. Estou esquecendo de algo? Uma tabela #Temporary realmente foi reutilizada entre esses dois SPIDs?

Isso está no SQL Server 2008 R2 Service Pack 2 com atualização cumulativa 1 (versão 10.50.4260).

O rastreamento completo do impasse inalterado está abaixo. Observe como os dois processos estão operando no mesmo ID de objeto com o mesmo nome de tabela # PB_Cost_Excp_Process_Invoices_Work_SNIP_0000000D8519:

12/14/2012 13:46:03,spid23s,Unknown,waiter id=process8cf948 mode=X requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process4cb3708 mode=Sch-M
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=0 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock371705d00 mode=Sch-M associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,waiter id=process4cb3708 mode=Sch-M requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process8cf948 mode=IX
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=3 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock3139b4780 mode=IX associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,resource-list
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Create_SP

    -- Clean up work table
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=138 stmtstart=11890 stmtend=12012 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,UPDATE #PB_Cost_Excp_Process_Invoices_Work
    SET PBCEPrcInv_RtlPkg_Item_Quantity = RtlPkg_Item_Quantity
    FROM #PB_Cost_Excp_Process_Invoices_Work
        INNER JOIN Item_Packages (NOLOCK)
            ON PBCEPrcInv_ItemPkg_Key = ItemPkg_Key
        INNER JOIN Retail_Packages (NOLOCK)
            ON ItemPkg_RtlPkg_Key = RtlPkg_Key

    -- Lookup pricebook cost
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Create_SP line=25 stmtstart=2394 stmtend=3050 sqlhandle=0x030008003a082846321f46018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process8cf948 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:0  waittime=3739 ownerId=707053534 transactionname=UPDATE lasttranstarted=2012-12-14T13:45:59.327 XDES=0x3c4502930 lockMode=X schedulerid=4 kpid=7276 status=suspended spid=72 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2012-12-14T13:45:58.337 lastbatchcompleted=2012-12-14T13:45:58.337 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707053534 currentdb=8 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=58 stmtstart=5782 stmtend=5894 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,ALTER TABLE #PB_Cost_Excp_Process_Invoices_Work DROP COLUMN PBCEPrcInv_Filler
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP line=50 stmtstart=5382 stmtend=5538 sqlhandle=0x0300080025d75a14ffff4701969f00000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process4cb3708 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:3  waittime=3739 ownerId=707052778 transactionname=ALTER TABLE lasttranstarted=2012-12-14T13:45:58.517 XDES=0x5f48bce80 lockMode=Sch-M schedulerid=6 kpid=7212 status=suspended spid=63 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2012-12-14T13:45:58.513 lastbatchcompleted=2012-12-14T13:45:58.513 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707052778 currentdb=2 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,process-list
12/14/2012 13:46:03,spid23s,Unknown,deadlock victim=process4cb3708
12/14/2012 13:46:03,spid23s,Unknown,deadlock-list

ATUALIZAR

A máquina em questão mostra 16 processadores no Gerenciador de Tarefas e no Gerenciador de Dispositivos; portanto, o particionamento de bloqueio está ativado e os dois bloqueios estão em diferentes partições de bloqueio. Não sei se o particionamento de bloqueio é uma causa contribuinte aqui ou não.

Eu também encontrei esta postagem intrigante no blog CSS SQL Server Engineers .

ATUALIZAÇÃO 2

As tabelas temporárias são descartadas no final de cada procedimento armazenado. Eles são criados com o padrão create #table, modificam esquema, inserem, atualizam, selecionam e soltam. Existem vários pontos de entrada para um procedimento comum que usa essa tabela temporária; portanto, temos um processo central que configura as colunas necessárias para chamar o processo comum. Caso contrário, teríamos de replicar a mesma definição #table em todos os procs do ponto de entrada.

O processo é chamado frequentemente de vários aplicativos clientes. Alguns dos aplicativos clientes chamam esse processo de vários threads. Outros o executam um de cada vez. Pense no software de inventário / contabilidade em que o escritório doméstico está processando dados para milhares de lojas em paralelo, enquanto as lojas também executam o mesmo processo. Portanto, se esse for um problema raro quando o particionamento de bloqueio estiver ativado, não será tão raro em nossos bancos de dados maiores de clientes.

ATUALIZAÇÃO 3 - 19/12/2012

Outro cliente está tendo o mesmo problema no SQL Server 2012, versão 11.0.2100. Não vi nenhuma menção de uma correção para esse problema nas descrições de atualização cumulativa. Pesquisando.

ATUALIZAÇÃO 4 - 13-02-2013

A Microsoft lançou a correção para esse bug nas seguintes atualizações:

Paul Williams
fonte
@AaronBertrand: Não, não queremos o cache da tabela #temp. Isso já seria ruim o suficiente na mesma conexão - e muito menos sendo reutilizado entre processos. Eu não tenho um arquivo .xdl, apenas as informações de sinalizador de rastreamento 1222.
Paul Williams
Nós eliminamos explicitamente essas tabelas #temp quando concluídas.
Paul Williams
2
Eu ainda sugeriria capturar e postar o arquivo .xdl em algum lugar para que outras pessoas possam olhar mais de perto - ele terá detalhes muito melhores.
Aaron Bertrand
2
Posso confirmar que o particionamento de bloqueio está envolvido aqui. Essas postagens têm alguns detalhes sobre a análise de conflitos envolvendo e devido a partições de bloqueio. bit.ly/Ruzmym bit.ly/W7yuRK Mas não sei por que ambas as sessões postaram o mesmo ObjectID.
Roji P Thomas
@SQLKiwi Obrigado por analisar o problema! Eu não pensei sobre o hashing de recursos de bloqueio. Dado que está no ID de um objeto, suspeito que não seja esse o caso, mas estou apenas supondo. O cliente tem relatado os bloqueios por vários dias. Eu tenho apenas 1 dia de rastreamento de impasse, mas aposto que esse é o impasse que eles estão enfrentando. Estamos abrindo um tíquete de suporte com a Microsoft para nos ajudar a descobrir. Vou atualizar esta pergunta à medida que aprender mais.
Paul Williams

Respostas:

4

Abrimos um caso com a Microsoft sobre esse problema. A Microsoft confirmou que esse bug também afeta o SQL Server 2012. Eles planejam lançar a correção no SQL Server 2012 Service Pack 2 (não lançado no momento em que escrevi esta resposta).

Até a Microsoft lançar este service pack, os usuários do SQL Server 2012 podem contornar o problema desabilitando o particionamento de bloqueios por meio do sinalizador de rastreamento 1229 .

Observe que esse problema se aplica apenas a máquinas que possuem 16 ou mais processadores.

Mais informações sobre o particionamento de bloqueio

Meus agradecimentos ao suporte da Microsoft! Eles foram muito rápidos e prestativos.

ATUALIZAR

O bug foi corrigido na Atualização Cumulativa 2 do SQL Server 2012 para o SQL Server 2012 SP 1 .

Paul Williams
fonte