我正在使用多线程控制台应用程序,其中每个线程基本上都尝试获取符合某些条件的TOP 1“文件”行并将其锁定。(当发生这种情况时,会有一个LockID列填充,以便下一个线程选择下一个可用的'未锁定''文件'行)
我们在SQL Server数据库上放置一个监视器,每次在2次查询时发生死锁。
SELECT TOP 1 F.Id, F.ContentTypeId, F.ManufacturerId, F.DocumentTypeId, F.Name, F.Description, F.VersionId, F.LastChangedVersionOn, F.ReferenceCount, F.LastChangedReferencesOn, F.LastChangedImageOn, F.ImageSize, F.IsStale, F.InvalidFile, CT.Id, CT.Name, CT.MimeType, CT.IsMimeAttachment, CT.Extensions, CT.CanTrackVersions, CT.UseRemoteSource, CT.FullTextFilter, CT.ContentHandler, V.Id, V.Size, V.Hash, V.Title, DT.Id, DT.Code, DT.Ordinal, DT.Name, DT.PluralName, DT.UrlPart
FROM Docs.Files F
INNER JOIN Docs.ContentTypes CT ON CT.Id = F.ContentTypeId
LEFT JOIN Docs.Versions V ON V.Id = F.VersionId
LEFT JOIN Docs.DocumentTypes DT ON DT.Id = F.DocumentTypeId
WHERE (F.LockId IS NULL OR F.LockedOn < DATEADD(hh,-1,GETUTCDATE()))
AND F.IsStale = 1 AND F.InvalidFile = 0
和
(@Id int)UPDATE Docs.Files
SET LastChangedImageOn = GETUTCDATE(), ImageSize = (
SELECT DATALENGTH(FileImage)
FROM Docs.FileImages
WHERE FileId = @Id)
WHERE Id = @Id;
SELECT TOP 1 LastChangedImageOn FROM Docs.Files WHERE Id = @Id
第一个查询在创建新线程时运行,我们尝试获取一个新的“文件”行。
当线程(可能是先前创建的线程)几乎完成处理“文件”记录时,运行第二个查询。对此查询使用的事务。隔离级别为“ReadCommitted”。 我很确定这两个查询都没有尝试访问相同的“FileID”,因为两个线程后来永远不会处理相同的“FileID”。 我对如何诊断这个问题感到十分困惑。什么可能导致这两个查询之间的僵局? 如果有人能指导我朝着正确的方向前进,我真的很感激。非常感谢提前:)
答案 0 :(得分:1)
嗯......自从我对SQL Server做了什么以来,已经有一段时间了。但是试试吧。
你提到“两个线程永远不会处理相同的”FileID“随后”,你怎么能确定这个? ID是从线程外部的源提供的吗?