Deadlock on Delete Statement


11

Eu recebo um impasse quando um trabalho do SQL Server é executado. O impasse ocorre em uma instrução DELETE simples. Eu teria pensado que teria que haver uma consulta SELECT / UPDATE em execução para causar o impasse? Mas parece que é um bloqueio DELETE / DELETE ...

O que estou procurando é por que estou recebendo um impasse DELETE / DELETE. É (que eu saiba) passando em diferentes parâmetros.

Alguma ideia? Obrigado.

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2

5
Não, um conflito pode ocorrer em outros cenários fora de SELECT / UPDATE. Tudo o que você realmente precisa são de dois processos, cada um precisando de um recurso que o outro esteja mantendo. (1) As instruções DELETE fazem parte de uma transação maior? (2) Você pode postar o XML do deadlock em algum lugar, em vez do texto de log de erro de baixa qualidade?
Aaron Bertrand

Você poderia postar o esquema da tabela dbo.UserDetailsDataincluindo todos os índices? Além disso, você sabe se essas instruções estão sendo chamadas com os mesmos parâmetros? Dado que ambos têm zero log usado, estou me perguntando se tudo o que você precisa fazer é serializar as chamadas porque elas estão pisando uma na outra.
Jon Seigel

Como obtenho o XML? Obteve o erro nos logs de erro do SQL Server. As instruções são chamadas com parâmetros diferentes. Recentemente, adicionamos vários índices filtrados que filtram no campo DataDoUsuário.
K09

Capture o evento gráfico de deadlock no Profiler. Depois de capturá-lo, clique com o botão direito do mouse na linha -> extrair dados do evento -> salve-o como um .xdl em algum lugar e poste seu conteúdo (é um xml) no Pastebin (ou em algum lugar semelhante).
Marian

1
Olá, XML publicado aqui ... espero que ajude! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

Respostas:


14

O que estou procurando é por que estou recebendo um impasse DELETE / DELETE.

Parece que o conflito ocorre porque:

  1. spid 54 ecid 0adquire um Ubloqueio de página update ( ) emPAGE: 12:1:5147422
  2. spid 166 ecid 3solicita um Ubloqueio de página de atualização ( ) na mesma página e é bloqueado
  3. spid 54 ecid 2solicita um Ubloqueio de página update ( ) na mesma página ...

As páginas estão sendo pré-buscadas para a consulta, com bloqueios de atualização adquiridos por ecid 0. Essa é a etapa 1 acima. Na etapa 3, um thread filho da mesma consulta paralela ( ecid 2) solicita o mesmo bloqueio. Normalmente isso não seria um problema. O SQL Server conhece ecid 0e ecid 2é um encadeamento do mesmo processo pai. Infelizmente, a etapa 2 atrapalha isso e ocorre um impasse.

Dito isto, você realmente não deve se preocupar muito com o motivo do impasse, a questão importante é como evitá-lo. A resposta é fornecer um caminho de acesso eficiente para o DELETE. A instrução precisa encontrar linhas WHERE Username = @P1 AND UserDate = @P2, portanto, você deve ter um índice digitado nessas colunas.

E é claro que você tem esse índice. A verdadeira questão é por que seus problemas começaram a ocorrer após a adição de índices filtrados.

A resposta para isso é informação extra da coluna é necessária para localizar as linhas de índice filtradas a serem excluídas (e para verificar seus predicados). Se a consulta usar um plano de execução estreito / por linha , o mecanismo de execução não poderá buscar as colunas extras no operador Exclusão de Índice em Cluster, como faria em um plano amplo / por índice.

Você pode encontrar mais detalhes sobre isso e um exemplo bem trabalhado nesta postagem no blog .

Nesse caso, as informações da coluna precisam vir da parte do plano à direita da Exclusão de índice em cluster e, portanto, uma varredura de índice em cluster paralelo é usada, e você obtém uma consulta lenta com alto potencial de conflito.

A resposta é fazer um dos seguintes:

  1. Remova os índices filtrados
  2. Adicione colunas de chave de índice / inclusão / predicado filtradas ao índice de nome / data existente
  3. Forçar um amplo plano de atualização (nenhuma maneira suportada de fazer isso)
  4. Execute a consulta sob isolamento de instantâneo (não RCSI)

A opção 2 seria minha forte preferência.

A opção 4 (obrigado Jack Douglas) tem a vantagem de remover deadlocks e não deve causar "conflitos de atualização", dada a natureza disjunta das alterações, mas exige a habilitação do isolamento de instantâneo no nível do banco de dados, alterando explicitamente o nível de isolamento, e não corrigirá o problema subjacente : você ainda terminará com uma verificação de tabela paralela, onde uma boa busca de índice é o que você realmente deseja.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.