У меня есть простая реализация очереди в MS Sql Server 2008 R2. Вот суть очереди:
CREATE TABLE ToBeProcessed
(
Id BIGINT IDENTITY(1,1) PRIMARY KEY NOT NULL,
[Priority] INT DEFAULT(100) NOT NULL,
IsBeingProcessed BIT default (0) NOT NULL,
SomeData nvarchar(MAX) NOT null
)
Я хочу атомарно выбрать первые n строк, упорядоченных по приоритету и идентификатору, где IsBeingProcessed имеет значение false, и обновить эти строки, чтобы сообщить, что они обрабатываются. Я думал, что буду использовать комбинацию Update, Top, Output и Order By, но, к сожалению, вы не можете использовать top и order by в операторе Update.
Поэтому я сделал предложение in, чтобы ограничить обновление, и что подзапрос упорядочивает (см. ниже). У меня вопрос, атомарен ли весь этот оператор или мне нужно обернуть его в транзакцию?
DECLARE @numberToProcess INT = 2
CREATE TABLE #IdsToProcess
(
Id BIGINT NOT null
)
UPDATE
ToBeProcessed
SET
ToBeProcessed.IsBeingProcessed = 1
OUTPUT
INSERTED.Id
INTO
#IdsToProcess
WHERE
ToBeProcessed.Id IN
(
SELECT TOP(@numberToProcess)
ToBeProcessed.Id
FROM
ToBeProcessed
WHERE
ToBeProcessed.IsBeingProcessed = 0
ORDER BY
ToBeProcessed.Id,
ToBeProcessed.Priority DESC)
SELECT
*
FROM
#IdsToProcess
DROP TABLE #IdsToProcess
Вот какой sql для вставки фиктивных строк:
INSERT INTO ToBeProcessed (SomeData) VALUES (N'');
INSERT INTO ToBeProcessed (SomeData) VALUES (N'');
INSERT INTO ToBeProcessed (SomeData) VALUES (N'');
INSERT INTO ToBeProcessed (SomeData) VALUES (N'');
INSERT INTO ToBeProcessed (SomeData) VALUES (N'');