1

私のDBスキーマはJob->(Many)JobData->(Many)Resultsです。ジョブは複数のJobData行に分割されるため、複数のスレッドがジョブの「チャンク」(各JobData行)を処理できます。次に、処理スレッドは、処理するJobData行ごとに結果行を挿入します。

単一のスレッドは、すべての結果が読み取られるまで、ループで結果を読み取ろうとします。 同時に、スレッドはJobData行を処理し(すべてが処理されるまで)、結果を挿入できることに注意してください。 したがって、ループでは、このSPへの各呼び出しはJobKeyを渡します...しかし、どういうわけかこのコードを使用すると、結果は複数回読み取られます(非常に低い頻度...つまり、結果の8000行あたり3行未満)が、ランダムにしか再現できません。

UPDLOCKに関するUPDATETOPステートメントの横のコードに以下のコメントを追加しました。前もって感謝します。

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

数日間正常に実行されているので、うまくいけば問題を解決しました。これがテーブルヒントの適切な使用に見えない場合は、遠慮なくお知らせください。

4

1 に答える 1

1

JOINとWHEREがあるため、実際にはUPDATEの後にUPDATEが続きます。

あなたが指摘した他の答え(私の答えです)に従って、追加のヒントが必要です

  1. 行のみをロックする:ROWLOCK
  2. ロックされた行をスキップする:READPAST
  3. ロックの期間と分離を増やす:UPDLOCK
于 2012-01-19T10:30:41.397 に答える