【发布时间】:2017-03-31 02:25:38
【问题描述】:
我有一个 C#/.NET 应用程序,它在多个线程(即并发,6 个线程)中尝试执行以下更新:
UPDATE cWrh SET
[Options] = cStg.[Options] -- byte array
FROM
[wrh].[Cars] cWrh
INNER JOIN [stg].[Cars] cStg ON
cWrh.[Id] = cStg.[Id]
AND cWrh.[Manufacturer_Id] = @ManufactuerId -- each thread gets different id here
AND cWrh.[Options] <> cStg.[Options]
这是在事务中运行的一段代码。两个表都有 3+mio 记录。聚集键在 [Id] 字段上,还有一些非聚集索引。
有趣的是,我手动检查并在我的特定示例中使用 3+mio 记录 cWrh.[Options] 和 cStg.[Options] 始终相同,因此最终不需要更新。
我附上了死日志图,编辑值说 DB.wrh.Cars: Deadlock graph
是的,在这个特定的示例中,并发实际上并没有添加任何值,但这是“重置”查询;在 C# 中执行一些 [Options] 计算的“重新计算”查询、批量插入回 SQL 并稍后在并发模式下更新显着加快了处理速度。
如果可能的话,无论任务如何(简单重置与 CPU 密集型工作),我都希望坚持这种并发方法。
感谢任何关于如何解决死锁的建议。
【问题讨论】:
-
不知道,但想知道
readpast提示是否合适?由于每个线程都有不同的@ManufactuerId,它们不应该 互相践踏(对吗?)也许还值得检查一下rowlock是否有用。再说一次,我真的不知道,所以把这个和一粒盐放在一起。 -
这个问题的答案可能会有所帮助。它建议使用隔离快照。 stackoverflow.com/questions/27206244/…
-
@David 你是对的,ManufacturerId 每个线程总是唯一的。我尝试了 readpas 和 rowlock 但仍然出现死锁
-
@KamranFarzami:感谢您提到隔离快照。他们似乎是正确的方法。但是,我不能一直使用它们,因为我的一些事务(除了上面提到的“重置”事务)使用临时表并在这些临时表之上创建索引;这似乎是一个已知的限制,因为无论是在本地临时表还是数据库表上,您都不能在具有快照隔离级别的事务中执行 DDL
标签: c# sql-server multithreading tsql deadlock