2016-11-16 107 views
2

我有一个C#/ NET应用程序,在多个线程中(即同时,6个线程),尝试执行以下更新:UPDATE FROM死锁

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]始终相同,因此最终不需要更新。

我附加了deadlog图,删节值说DB.wrh.Cars: Deadlock graph

是的,在这个特殊的例子并发是不是真的增加任何价值,但这是“复位”查询;在C#中执行一些[Options]计算的“重新计算”查询,批量插入SQL并稍后以并发模式更新,显着加速了这一事情。

如果可能的话,我只想坚持这种并发方法,无论任务如何(简单复位与CPU密集型工作)。

任何建议如何解决僵局是值得赞赏的。

+0

不知道,但想知道'readpast'提示可能是合适的?由于每个线程都有不同的'@ ManufactuerId',它们*不应该*彼此践踏(对吗?)也许值得检查'rowlock'是否有帮助。再一次,我真的不知道,所以拿一点盐来吧。 – David

+0

这个问题的答案可能会有所帮助。它建议使用隔离快照。 http://stackoverflow.com/questions/27206244/sql-server-prevent-lost-update-and-deadlocks –

+0

@大卫你是对的,ManufacturerId总是唯一的每个线程。我尝试使用readpas以及rowlock,但仍然出现死锁 – mpfx

回答

0

正如@KamranFarzami所建议的,@通过@Grantly解决了我的问题。回答这个问题的要点在于他们。

事务隔离级别的SNAPSHOT可防止发生死锁。