1

我的数据库架构是 Job -> (Many) JobData -> (Many) Results。一个 Job 被分成多个 JobData 行,以便多个线程可以处理 Job 的“块”(每个 JobData 行)。然后,处理线程为其处理的每个 JobData 行插入 Result 行。

单个线程尝试循环读取结果,直到读取所有结果。 请注意,同时线程仍然可以处理 JobData 行(直到所有行都被处理)并插入结果。 因此,在循环中,对这个 SP 的每次调用都会传入一个 JobKey……但不知何故,使用此代码会多次读取结果(频率非常低……即每 8000 行结果 < 3 行),但只能随机重现。

我在关于 UPDLOCK 的 UPDATE TOP 语句旁边的代码中添加了以下注释。提前致谢。

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

您的 UPDATE 实际上是SELECT 后跟 UPDATE 因为您有 JOINs 和 WHEREs

根据您提到的其他答案,您需要额外的提示(这是我的答案)

  1. 仅锁定行:ROWLOCK
  2. 跳过锁定的行:READPAST
  3. 增加锁的持续时间和隔离:UPDLOCK
于 2012-01-19T10:30:41.397 回答