Pourquoi cette requête provoque-t-elle un blocage?


11

Pourquoi cette requête provoque-t-elle un blocage?

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)

Graphique de blocage ajouté:

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

AJOUTÉE:

Merci Sankar pour cet article qui propose des solutions pour éviter ce type de blocage:

  • éliminer les colonnes inutiles de la projection du lecteur pour qu'il n'ait pas à rechercher l'index clusterisé
  • ajouter les colonnes requises en tant que colonnes contenues à l'index non clusterisé pour couvrir l'index, encore une fois afin que le lecteur n'ait pas à rechercher l'index clusterisé
  • éviter les mises à jour qui doivent maintenir l'index non clusterisé

quelle version de quelle plateforme db utilisez-vous? quel est le niveau d'isolement trx (ou simultanéité) par défaut? Quels index existent actuellement sur la table system_Queue?
SQLRockstar

Ajout d'une partie @SQLRockstar du graphique de blocage, SQL Server 2008
Garik

@SQLRockstar IX_system_Queue_DirectionByStatus index par IsOutGoing et StatusID.
garik

Réponses:


13

Il me semble que vous essayez de faire un SELECT et un UPDATE dans la même instruction et sur la même table.

Le SELECT détient un verrou partagé sur les valeurs à l'intérieur de l'index IX_system_Queue_DirectionByStatus, et l'UPDATE a besoin que ces verrous soient libérés avant qu'il puisse obtenir son verrou exclusif qui mettra à jour la clé primaire (qui, je suppose, est en cluster et fait également partie de la Valeur de la clé IX_system_Queue_DirectionByStatus).

Quoi qu'il en soit, je suppose que cette requête ne réussirait que dans les rares cas où les valeurs d'index qu'elle sélectionne et met à jour ne sont pas en conflit. Est-ce un blocage à chaque fois que vous exécutez (je suppose que ce le serait).

Voici un lien qui explique les blocages plus en détail: http://sqlblog.com/blogs/jonathan_kehayias/archive/2008/07/30/the-anatomy-of-a-deadlock.aspx


Bingo! Je vous remercie. C'était une situation vraiment étrange pour une impasse que j'ai jamais vue. Merci de votre réponse.
garik

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.