¿Por qué esta consulta causa un punto muerto?

11

¿Por qué esta consulta causa un punto muerto?

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 punto muerto agregado:

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

ADICIONAL:

Gracias Sankar por el artículo que tiene soluciones para evitar este tipo de punto muerto:

  • eliminar columnas innecesarias de la proyección del lector para que no tenga que buscar el índice agrupado
  • agregue las columnas requeridas como columnas contenidas al índice no agrupado para hacer que el índice cubra, nuevamente para que el lector no tenga que buscar el índice agrupado
  • evitar actualizaciones que tengan que mantener el índice no agrupado
Garik
fuente
¿Qué versión de qué plataforma db estás usando? ¿Cuál es el nivel predeterminado de aislamiento trx (o concurrencia)? ¿Qué índices existen actualmente en la tabla system_Queue?
SQLRockstar
@SQLRockstar parte del gráfico de punto muerto agregado, servidor SQL 2008
garik
@SQLRockstar IX_system_Queue_DirectionByStatus indexado por IsOutGoing y StatusID.
garik

Respuestas:

13

Me parece que está intentando hacer una SELECCIÓN y una ACTUALIZACIÓN en la misma declaración y en la misma tabla.

SELECT mantiene un bloqueo compartido en los valores dentro del índice IX_system_Queue_DirectionByStatus, y la ACTUALIZACIÓN necesita que esos bloqueos se liberen antes de que pueda obtener su bloqueo exclusivo que actualizará la clave principal (que supongo que está agrupada y también es parte del IX_system_Queue_DirectionByStatus valor clave).

De todos modos, supongo que esta consulta solo tendrá éxito en la rara posibilidad de que los valores de índice que está seleccionando y actualizando no entren en conflicto. ¿Es un punto muerto cada vez que ejecutas (supongo que lo sería).

Aquí hay un enlace que explica los puntos muertos con más detalle: http://sqlblog.com/blogs/jonathan_kehayias/archive/2008/07/30/the-anatomy-of-a-deadlock.aspx

SQLRockstar
fuente
¡Bingo! Gracias. Fue una situación realmente extraña para el punto muerto que he visto. Gracias por su respuesta.
garik