Eu recomendo que você consulte Usando tabelas como filas. As filas implementadas corretamente podem lidar com milhares de usuários simultâneos e atender até 1/2 milhão de operações de enfileiramento/desenfileiramento por minuto. Até o SQL Server 2005, a solução era complicada e envolvia uma mistura de um
SELECT
e um UPDATE
em uma única transação e fornecer a combinação certa de dicas de bloqueio, como no artigo vinculado por gbn. Felizmente, desde o SQL Server 2005 com o advento da cláusula OUTPUT, uma solução muito mais elegante está disponível e agora o MSDN recomenda o uso da cláusula OUTPUT:
Você pode usar OUTPUT em aplicativos que usam tabelas como filas ou para manter conjuntos de resultados intermediários. Ou seja, o aplicativo está constantemente adicionando ou removendo linhas da tabela
Basicamente, existem 3 partes do quebra-cabeça que você precisa acertar para que isso funcione de maneira altamente simultânea:
- Você precisa desenfileirar automaticamente. Você precisa encontrar a linha, pular todas as linhas bloqueadas e marcá-la como 'retirada da fila' em uma única operação atômica, e é aí que a
OUTPUT
cláusula entra em jogo:
with CTE as (
SELECT TOP(1) COMMAND, PROCESSED
FROM TABLE WITH (READPAST)
WHERE PROCESSED = 0)
UPDATE CTE
SET PROCESSED = 1
OUTPUT INSERTED.*;
- Você deve estruture sua tabela com a chave de índice clusterizado mais à esquerda no
PROCESSED
coluna. Se oID
foi usada uma chave primária e, em seguida, mova-a como a segunda coluna na chave clusterizada. O debate sobre manter uma chave não agrupada noID
coluna está aberta, mas eu sou fortemente a favor de não tendo quaisquer índices secundários não agrupados em filas:
CREATE CLUSTERED INDEX cdxTable on TABLE(PROCESSED, ID);
- Você não deve consultar esta tabela por nenhum outro meio, exceto por Dequeue. Tentando fazer operações Peek ou tentando usar a tabela como uma fila e como uma loja irá muito provavelmente levar a impasses e diminuirá drasticamente a taxa de transferência.
A combinação de desenfileiramento atômico, dica READPAST na busca de elementos para desenfileiramento e chave mais à esquerda no índice clusterizado com base no bit de processamento garante uma taxa de transferência muito alta sob uma carga altamente simultânea.