C# 多表事务的死锁

C# 多表事务的死锁,c#,sql,sql-server,transactions,sql-server-2008-r2,C#,Sql,Sql Server,Transactions,Sql Server 2008 R2,我的情况很常见: 我有一个需要更新多个表的存储过程。 如果其中一个更新失败-应回滚所有更新。 向前的答案是在一个事务中包含所有更新,然后回滚。然而,在我们这样的系统中,这将导致并发问题。 当我们将更新分解为多个短事务时,在死锁问题开始出现之前,我们每秒可以获得约30次并发执行的吞吐量。 如果我们把它放在一个跨所有事务的事务中,我们会在死锁出现之前每秒并发2次 在我们的例子中,我们在每个短事务之后放置一个try-catch块,并手动删除/更新以前的更改。因此,本质上我们以一种非常昂贵的方式模拟事务

我的情况很常见: 我有一个需要更新多个表的存储过程。 如果其中一个更新失败-应回滚所有更新。 向前的答案是在一个事务中包含所有更新,然后回滚。然而,在我们这样的系统中,这将导致并发问题。 当我们将更新分解为多个短事务时,在死锁问题开始出现之前,我们每秒可以获得约30次并发执行的吞吐量。 如果我们把它放在一个跨所有事务的事务中,我们会在死锁出现之前每秒并发2次

在我们的例子中,我们在每个短事务之后放置一个try-catch块,并手动删除/更新以前的更改。因此,本质上我们以一种非常昂贵的方式模拟事务行为。。。 它工作正常,因为它写得很好,没有得到很多“回滚”。。。 这种方法根本无法解决的一个问题是来自web服务器/客户端的命令超时

我已经阅读了大量的表格和博客,并通过MSDN进行了扫描,但找不到好的解决方案。许多人提出了这个问题,但我还没有看到一个好的解决办法

问题是:是否有任何解决方案可以允许对多个表进行稳定的更新回滚,而无需在整个长事务期间对所有行建立排他锁

假设这不是一个优化问题。这些表几乎处于最大优化状态,只要死锁不发生,就可以提供非常高的吞吐量。没有表锁/页锁等。更新时的所有行锁-但是当您有这么多并发会话时,其中一些需要更新同一行

它可以通过SQL、客户端C#、服务器端C#(扩展SQL server?)实现。 在我没有找到的任何书籍/博客中有这样的解决方案吗

我们使用的是SQLServer2008R2,与.NET客户端/web服务器连接。 代码示例:

创建过程sptest 开始交易 更新表1 更新表2 提交事务

在这种情况下,如果sptest运行两次,则在实例1提交之前,第二个实例无法更新表1。 与此相比,

创建sptest2 更新表1 更新表2

Sptest2的吞吐量要高得多,但它有可能损坏数据。 这就是我们正在努力解决的问题。有理论上的解决办法吗

谢谢,
JS

对于大多数是静态的或概率很高的所有内部联接表,如果不使用脏数据影响查询,则可以应用:

INNER JOIN LookupTable (with NOLOCK) lut on lut.ID=SomeOtherTableID
这将告诉查询我不关心对其他表的更新


在大多数情况下,这可以减少您的问题。对于更困难的死锁,我已经实现了一个死锁图,它在死锁发生时生成并通过电子邮件发送,包含死锁的所有详细信息。

我想说,您应该深入挖掘,以找出死锁发生的原因。您可能应该更改更新的顺序以避免它们。也许有些指数是“有罪的”


如果其他事务可以更改数据,则不能返回更改。所以你需要对它们进行更新锁定。但您可以使用快照隔离级别在更新提交之前允许一致读取。

谢谢您的回答。我们实际上使用(nolock)。更进一步,我们试图将所有选择完全排除在事务之外。我知道有管理死锁的解决方案,我们正在使用一些,我的问题是任何可以解决问题的编程解决方案,而不是管理它。您是否有任何长时间运行的进程与您的更新同时运行,可能会对您的资源(如报表、服务代理、批量更新等)设置独占锁。,等等。尝试实现应用程序维护的事务将失败(我曾经在一个尝试过的系统上工作)。数据库级别的好处在于它能够经受突然断电和服务器崩溃等情况的影响——您能对您的应用程序说同样的话吗?DB one经过了预先测试,非常好,可能比应用程序中可以实现的任何整体系统都要快。我们能得到更多的细节吗?为什么有多个线程更新同一行?事务旨在防止错误,但最好首先避免争用。。。