このSPでUpdlockヒントが必要ですか?データキューの行を複数回読みます
-
30-10-2019 - |
質問
私のDBスキーマはヨブです - >(多くの)jobdata->(多くの)結果。ジョブは複数のJobData行に分かれているため、複数のスレッドがジョブの「チャンク」を処理できるようになります(各jobData行)。次に、処理スレッドは、処理するJobData行ごとに結果行を挿入します。
単一のスレッドは、すべての結果が読み取られるまでループで結果を読み取ろうとします。 同時に、スレッドはまだ(すべてが処理されるまで)JobData行を処理し、結果を挿入できることに注意してください。 したがって、ループでは、このSPへの各呼び出しはJobKeyに渡されます...しかし、このコードでは、結果は複数回読み取られます(非常に低い頻度...つまり、結果の8000行あたり3行<3行)が、ランダムに再現できます。
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 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
数日間成功しているので、うまくいけば問題を招きました。これがテーブルの適切な使用のように見えない場合は、お気軽にお知らせください。
正しい解決策はありません
所属していません StackOverflow