Perché questa query provoca un deadlock?


11

Perché questa query provoca un deadlock?

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)

Grafico deadlock aggiunto:

<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>

AGGIUNTO:

Grazie Sankar per l'articolo che ha soluzioni su come evitare questo tipo di deadlock:

  • elimina le colonne non necessarie dalla proiezione del lettore in modo che non debba cercare l'indice cluster
  • aggiungere le colonne richieste come colonne contenute all'indice non cluster per rendere la copertura dell'indice, di nuovo in modo che il lettore non abbia cercato l'indice cluster
  • evitare gli aggiornamenti che devono mantenere l'indice non cluster

quale versione di quale piattaforma db stai usando? qual è il livello predefinito di isolamento trx (o concorrenza)? Quali indici esistono attualmente nella tabella system_Queue?
SQLRockstar

Aggiunta la parte @SQLRockstar del grafico deadlock, sql server 2008
garik

@SQLRockstar IX_system_Queue_DirectionByStatus indice di IsOutGoing e StatusID.
garik

Risposte:


13

Mi sembra che tu stia provando a fare un SELECT e un UPDATE nella stessa istruzione e sulla stessa tabella.

SELEZIONA tiene un blocco condiviso sui valori all'interno dell'indice IX_system_Queue_DirectionByStatus e l'UPDATE ha bisogno che questi blocchi vengano rilasciati prima di poter ottenere il blocco esclusivo che aggiornerà la chiave primaria (che immagino sia raggruppata e anche parte del Valore chiave IX_system_Queue_DirectionByStatus).

Ad ogni modo, la mia ipotesi è che questa query avrà successo solo nella rara possibilità che i valori dell'indice che sta selezionando e aggiornando non siano in conflitto. Si blocca ogni volta che esegui (suppongo che sarebbe).

Ecco un link che spiega in dettaglio i deadlock: http://sqlblog.com/blogs/jonathan_kehayias/archive/2008/07/30/the-anatomy-of-a-deadlock.aspx


Bingo! Grazie. È stata una situazione davvero strana per deadlock che abbia mai visto. Grazie per la risposta.
garik,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.