Eu sei que o parâmetro de saída não garante lógica de paralelismo. E a lógica que quero implementar está falhando em um ambiente multi-thread.
Para testar isso, basta abrir 2 janelas e executá-las lado a lado o mais rápido possível. Em seguida, compare os Ids, alguns serão duplicados.
declare @id int
select @id = 1
while @id >=1 and @id <= 100
begin
UPDATE sys_QueueJob
SET StartedOn = GETDATE()
OUTPUT DELETED.Id as Result
WHERE Id = (select top 1 qj.Id
from sys_QueueJob qj
where qj.ProcessedOn is null AND qj.StartedOn is null
order by CreatedOn asc)
print 'Count: ' + convert(nvarchar(max), @id)
select @id = @id + 1
end
Eu só quero pegar a entrada mais antiga da tabela qeueJob que ainda não foi iniciada e ao mesmo tempo dizer que agora ela foi iniciada. E o mesmo código precisa me fornecer 100% de certeza de que a próxima execução me dará o próximo ID correto.
Como posso fazer isso?
Embora eu concorde que "a abordagem sp_getapplock/sp_releaseapplock [é] a maneira mais direta e menos suja de gerenciar a lógica de semáforo explícita".
Há um motivo que não está funcionando e uma maneira de corrigi-lo diretamente e permitir que várias transações simultâneas busquem simultaneamente linhas disjuntas:
Isso deve corrigi-lo:
Consulte Usando tabelas como filas