Por que essa consulta causa um impasse?
UPDATE TOP(1) system_Queue SET
[StatusID] = 2,
@ID = InternalID
WHERE InternalID IN (
SELECT TOP 1
InternalID FROM system_Queue
WHERE IsOutGoing = @IsOutGoing AND StatusID = 1
ORDER BY MessageID ASC, InternalID ASC)
Gráfico de impasse adicionado:
<keylock hobtid="72057594236436480" dbid="9" objectname="Z.dbo.system_Queue" indexname="PK_system_Queue" id="lock5b25cc80" mode="X" associatedObjectId="72057594236436480">
<owner-list>
<owner id="processc6fe40" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="processc7b8e8" mode="S" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594405453824" dbid="9" objectname="Z.dbo.system_Queue" indexname="IX_system_Queue_DirectionByStatus" id="lock48cf3180" mode="S" associatedObjectId="72057594405453824">
<owner-list>
<owner id="processc7b8e8" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="processc6fe40" mode="X" requestType="wait"/>
</waiter-list>
</keylock>
ADICIONADO:
Obrigado Sankar pelo artigo que tem soluções para evitar esse tipo de impasse:
- elimine colunas desnecessárias da projeção do leitor para que ele não precise consultar o índice agrupado
- adicione as colunas necessárias como colunas contidas ao índice não clusterizado para fazer a cobertura do índice, novamente para que o leitor não precise procurar o índice clusterizado
- evitar atualizações que precisam manter o índice não clusterizado
Parece-me que você está tentando fazer um SELECT e um UPDATE na mesma instrução e na mesma tabela.
O SELECT está mantendo um bloqueio compartilhado nos valores dentro do índice IX_system_Queue_DirectionByStatus, e o UPDATE precisa que esses bloqueios sejam liberados antes que ele possa obter seu bloqueio exclusivo que atualizará a chave primária (que eu acho que está agrupada e também faz parte do Valor da chave IX_system_Queue_DirectionByStatus).
De qualquer forma, meu palpite é que essa consulta só seria bem-sucedida na rara chance de que os valores de índice que ela está selecionando e atualizando não sejam conflitantes. É um impasse cada vez que você executa (suponho que seria).
Aqui está um link que explica os impasses com mais detalhes: http://sqlblog.com/blogs/jonathan_kehayias/archive/2008/07/30/the-anatomy-of-a-deadlock.aspx
Não espero que você marque esta postagem como uma resposta, mas compartilhe mais informações aqui por outros especialistas do SQL Server neste tópico.
http://web.archive.org/web/20111222024618/http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx
http://rusanu.com/2009/05/16/readwrite-deadlock/