У меня была такая ситуация.
Добавить в таблицу столбец InProcess
, по умолчанию = 0. В потребительском процессе:
UPDATE tbl SET Inprocess = @myMachineID WHERE rowID =
(SELECT MIN(rowID) WHERE InProcess = 0)
Теперь эта машина владеет строкой, и вы можете без опасений запрашивать ее данные. Обычно ваша следующая строка будет выглядеть примерно так:
SELECT * FROM tbl WHERE rowID =
(SELECT MAX(rowID) FROM tbl WHERE ProcessID = @myMachineID)
Вам также нужно будет добавить в строку какой-нибудь флаг Done
, чтобы вы могли определить, была ли заявлена строка, но обработка была неполной.
Редактировать
UPDATE
получает эксклюзивную блокировку (см. MSDN ). Я не уверен, разрешено ли разделение SELECT
в подзапросе от UPDATE
; если это так, вам придется поместить их в транзакцию.
@ Will A публикует ссылку, которая предполагает, что начало партии с этим будет гарантировать:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
... но я не пробовал.
@ Ссылка Мартина Смита также дает хорошие результаты, если взглянуть на предложение OUTPUT
(добавлено в SQL 2005).
Последнее редактирование
Очень интересный обмен в комментариях, я определенно узнал здесь несколько вещей. И вот для чего ТАК, верно?
Только для цвета: когда я использовал этот подход еще в 2004 году, у меня было несколько веб-сканеров, которые сбрасывали URL-адреса для поиска в таблицу, а затем извлекали следующий URL-адрес для сканирования из этой же таблицы. Поскольку сканеры пытались привлечь вредоносное ПО, они могли в любой момент потерпеть крах.