Eu tenho um procedimento armazenado que consulta uma tabela de fila ocupada que é usada para distribuir o trabalho em nosso sistema. A tabela em questão possui uma chave primária no WorkID e nenhuma duplicata.
Uma versão simplificada da consulta é:
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)
A #Typestabela é preenchida anteriormente no procedimento.
Como eu disse, WorkTableestá ocupado e, às vezes, enquanto essa consulta está sendo executada, suspeito que um dos registros esteja se movendo de um conjunto de filtros WHEREpara outro. Especificamente, isso acontece quando alguém começa a trabalhar em um item e as W.InProgressalterações de 0 para 1. Quando isso acontece, recebo uma violação de chave duplicada quando tento adicionar uma chave primária à tabela temporária na qual esta consulta está inserida.
Confirmei no plano de consulta gerado quando ocorre o erro que não há paralelismo, o nível de isolamento é READ COMMITTEDe não há registros duplicados na tabela de origem. Você também pode ver que não há JOINoutra maneira de obter produtos cartesianos aqui.
Este é o plano de consulta anonimizado:
A questão é: o que está causando as duplicatas e como posso parar?
Eu acho que READ COMMITTEDdeveria funcionar aqui, preciso travar. Estou quase certo de que as bobagens ocorrem quando o InProgressbit em um registro muda enquanto estou consultando. Eu sei disso porque a tabela armazena o tempo dessa alteração e está dentro de milissegundos após a consulta e o erro.

