Tengo un procedimiento almacenado que consulta una tabla de cola ocupada que se utiliza para distribuir el trabajo en nuestro sistema. La tabla en cuestión tiene una clave principal en WorkID y no tiene duplicados.
Una versión simplificada de la consulta es:
INSERT INTO #TempWorkIDs (WorkID)
SELECT
W.WorkID
FROM
dbo.WorkTable W
WHERE
(@bool_param = 0 AND
((W.InProgress = 0
AND ISNULL(W.UserID, -1) != @userid_param
AND (@bool_filtered = 0
OR W.TypeID IN (SELECT TypeID FROM #Types AS t)))
OR
(@bool_param = 1
AND W.InProgress = 1
AND W.UserID != @userid_param)
OR
(@Auto_Param = 0
AND W.UserID = @userid_param)))
OR
(@bool_param = 1 AND W.UserID = @userid_param)
OPTION
(RECOMPILE)
La #Typestabla se rellena anteriormente en el procedimiento.
Como dije, WorkTableestá ocupado y, a veces, mientras se ejecuta esta consulta, SUSPECTO que uno de los registros se mueve de un conjunto de filtros en el WHEREotro. Específicamente, esto sucede cuando alguien comienza a trabajar en un elemento y los W.InProgresscambios de 0 a 1. Cuando esto sucede, obtengo una violación de clave duplicada cuando intento agregar una clave principal a la tabla temporal en la que se inserta esta consulta.
He confirmado en el plan de consulta generado cuando ocurre el error que no hay paralelismo, el nivel de aislamiento es READ COMMITTED, y no hay registros duplicados en la tabla de origen. También puede ver que no hay JOINotra forma de obtener productos cartesianos aquí.
Este es el plan de consulta anónimo:
La pregunta es, ¿qué está causando los duplicados y cómo puedo hacer que se detenga?
Creo que READ COMMITTEDdebería funcionar aquí, necesito un bloqueo. Estoy casi seguro de que los engaños ocurren cuando el InProgressbit en un registro cambia mientras estoy consultando. Sé esto porque la tabla almacena el tiempo de ese cambio y está dentro de milisegundos de cuando consulto y obtengo el error.


