Подтвердить что ты не робот

Состояние очереди очереди процессов SQL Server

У меня есть очередь заказов, к которой обращаются несколько процессоров заказов через хранимую процедуру. Каждый процессор передает уникальный идентификатор, который используется для блокировки следующих 20 заказов для собственного использования. Хранимая процедура затем возвращает эти записи в процессор заказов, чтобы действовать.

Бывают случаи, когда несколько процессоров могут извлекать одну и ту же запись "OrderTable" , после чего они пытаются одновременно работать с ней. Это в конечном итоге приводит к ошибкам, возникающим позже в процессе.

Мой следующий курс действий - позволить каждому процессору захватить все доступные заказы и просто обойти процессоры, но я надеялся просто сделать этот раздел потока кода безопасным и позволить процессорам захватывать записи, когда захочет.

Так явно - любая идея, почему я испытываю это состояние гонки и как я могу решить проблему.

BEGIN TRAN
    UPDATE  OrderTable WITH ( ROWLOCK )
    SET     ProcessorID = @PROCID
    WHERE   OrderID IN ( SELECT TOP ( 20 )
                                        OrderID
                                FROM    OrderTable WITH ( ROWLOCK )
                                WHERE   ProcessorID = 0)
COMMIT TRAN


SELECT  OrderID, ProcessorID, etc...
FROM    OrderTable
WHERE   ProcessorID = @PROCID
4b9b3361

Ответ 1

Изменить:

Я просмотрел свой ответ: "Обработка очередей данных в SQL Server с помощью READPAST и UPDLOCK" . Прошло много лет с тех пор, как я читал и играл с этим решением.

Оригинал:

Если вы используете подсказку READPAST, то заблокированные строки пропускаются. Вы использовали ROWLOCK, чтобы избежать эскалации блокировки. Вам также потребуется UPDLOCK, как я узнал.

Итак, процесс 1 блокирует 20 строк, процесс 2 будет принимать следующие 20, процесс 3 принимает строки с 41 по 60 и т.д.

Обновление также можно записать следующим образом:

UPDATE TOP (20)
    foo
SET
    ProcessorID = @PROCID
FROM
    OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE
    ProcessorID = 0

Обновить, октябрь 2011

Это можно сделать более элегантно с помощью предложения OUTPUT, если вам нужен SELECT и UPDATE за один раз.

Ответ 2

Вы можете использовать Service Broker. Также вы можете использовать sp_getapplock для сериализации доступа к вашим строкам - это устранит условия гонки:

"Помощь Concurrency путем создания собственных Locks (Mutexs в SQL)" http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx