【问题标题】:Multi threaded application DeadLock issue with Database数据库的多线程应用程序死锁问题
【发布时间】:2012-08-29 16:54:15
【问题描述】:

我正在使用多线程控制台应用程序,其中每个线程基本上都尝试获取满足某些条件的 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”。 我对如何诊断这个问题感到非常困惑。什么可能导致这两个查询之间的死锁? 如果有人能引导我朝着正确的方向前进,我将非常感激。提前非常感谢:)

【问题讨论】:

  • 了解更多信息会很有帮助。 - 您使用的是哪个数据库服务器和引擎(如果适用)? - 你在使用交易吗?附言SQL 代表结构化查询语言。有许多使用 SQL 的数据库。
  • 这里的隔离级别是多少?
  • 另外,我能看到的唯一争论是在 Docs.Files 上 - 读写可能会变得混乱......选项:使读取工作以更少(零)隔离,所以它不需要读锁;或使读取 more 隔离,因此它需要一个写入锁(导致阻塞而不是死锁)。哪个听起来更可取?
  • @MarcGravell 我确实将事务用于有问题的第二个查询。我使用的隔离级别是“ReadCommited”。不过,“SELECT”查询中没有事务/隔离。
  • @Paul 这是一个 SQL 服务器数据库。请参阅我上面的评论以获取其他信息。如果你还需要什么,请告诉我。

标签: c# multithreading console-application deadlock database-deadlocks


【解决方案1】:

嗯...自从我对 SQL Server 做任何事情以来已经有一段时间了。不过让我们试试吧。

您提到“两个线程将永远不会处理相同的“FileID””,您如何确定这一点? ID 是从线程外的来源提供的吗?

【讨论】:

  • 因为该行将被前一个线程锁定,而下一个线程只会拾取“未锁定”和“unStale”行。
  • 那里好像有问题。线程是否在数据库中设置这些?如果是这样,那么线程启动和完成更新之间的差距又如何呢?其他线程是否已运行并收到相同的文件 ID?
  • 嗨。您是否设法找到解决问题的方法,我的问题是否为您指明了正确的方向?
  • 嗨@Paul 感谢您回来查看。我认为这更多的是 SQL 服务器问题,而不是导致死锁的代码问题。服务器因请求而过载并且内存不足。我们的 DBA 进行了一些 IO 调整,并且工作正常。再次感谢您的检查。
  • 哎哟!好吧,我很高兴发现并解决了问题。 :)
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 2018-11-09
  • 1970-01-01
相关资源
最近更新 更多