Моя схема БД - Job -> (Many) JobData -> (Many) Results.Задание разбивается на несколько строк JobData, поэтому несколько потоков могут обрабатывать «куски» задания (каждая строка JobData).Затем потоки обработки вставляют строки результата для каждой строки JobData, которую он обрабатывает.
Один поток пытается прочитать результаты в цикле, пока все результаты не будут прочитаны. Обратите внимание, что в то же время потоки могут по-прежнему обрабатывать строки JobData (пока все не будут обработаны) и вставлять результаты. Так что в цикле каждый вызов этого SP проходит в JobKey ... но как-то с этимкод, результаты читаются несколько раз (очень низкая частота ... т.е. <3 строки на 8000 строк результатов), но воспроизводятся только случайным образом. </p>
Я добавил комментарий ниже в коде рядом с моим оператором UPDATE TOPотносительно UPDLOCK.Заранее спасибо.
BEGIN TRANSACTION
-- Create a temp table TO store the select results
DECLARE @UnReadResults TABLE
(
ResultKey uniqueidentifier
)
-- Wouldn't expect a UPDLOCK is needed since UPDATE statements create exclusive lock anyway? Do I need to SELECT WITH UPDLOCK first, then do the UPDATE statement?
UPDATE TOP ( @pageSize ) Result
SET rResultRead = 1
OUTPUT INSERTED.rKey INTO @UnReadResults
FROM Result r INNER JOIN JobData AS jd ON jd.jdKey = r.rJobDataKey
WHERE jd.jdJobKey = @jobKey AND rResultRead = 0
-- Just return Job (always the same), JobData (could vary if chunk of result rows
-- spans multiple JobDatas) and Results that I successfully 'grabbed' by joining
-- to my temp table
SELECT j.jKey, j.jStatus, j.jResultsRead,
jd.jdKey, jd.jdJobKey, jd.jdDateStart, jd.jdDateComplete, jd.jdStatus,
r.rKey, r.rProfileKey, r.rProfileAuthID, r.rResult, r.rReadLock, r.rReadAttempts
FROM Job j
INNER JOIN JobData jd
ON jKey = jdJobKey
INNER JOIN Result r
ON jdKey = rJobDataKey
INNER JOIN @UnReadResults urr
on rKey = urr.ResultKey
COMMIT TRANSACTION
РЕДАКТИРОВАТЬ: Просто хотел положить то, что у меня есть сейчас, на основе ответа @gbn.Исключая весь SP, но оператор UPDATE теперь отформатирован так:
UPDATE TOP ( @pageSize ) Result
SET rResultRead = 1, rReadLock = @lock, rReadAttempts = rReadAttempts + 1
OUTPUT INSERTED.rKey INTO @UnReadResults
FROM Result r WITH ( ROWLOCK, READPAST, UPDLOCK ) INNER JOIN JobData AS jd ON jd.jdKey = r.rJobDataKey
WHERE jd.jdJobKey = @jobKey AND rResultRead = 0
Успешно работает уже несколько дней, так что, надеюсь, я исправил проблему.Если это не похоже на правильное использование табличных подсказок, дайте мне знать.