Нужна ли подсказка UPDLOCK в этом SP?Чтение строки данных более одного раза - PullRequest
1 голос
/ 19 января 2012

Моя схема БД - 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

Успешно работает уже несколько дней, так что, надеюсь, я исправил проблему.Если это не похоже на правильное использование табличных подсказок, дайте мне знать.

1 Ответ

1 голос
/ 19 января 2012

Ваше ОБНОВЛЕНИЕ на самом деле ВЫБРАТЬ, а затем ОБНОВЛЕНИЕ, потому что у вас есть СОЕДИНЕНИЯ и ГДЕ .

Вам нужны дополнительные подсказки в соответствии с другим ответом, который вы отметили (который являетсямой ответ)

  1. Блокировка только строк: ROWLOCK
  2. Пропуск заблокированных строк: READPAST
  3. Увеличение длительности и изоляция блокировок: UPDLOCK
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...