Состояние очереди очереди процессов 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
Ответы
Ответ 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