我的数据库架构是 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
现在已经成功运行了几天,所以希望我解决了问题。如果这看起来不像正确使用表格提示,请随时告诉我。