如何通过慢查询避免死锁

时间:2011-09-11 23:26:21

标签: c# sql entity-framework

我有一个偶尔会导致数据库死锁的WCF服务。我的服务允许您向理事会提交申请,也允许您再次加载申请,因为理事会可以更新申请。每个应用程序都有许多与之相关的文档。

因此,如果我的服务上发生了一系列类似的事件

1) Application #1 is submitted
2) A document is uploaded for application #1
3) Application #1 is loaded
4) Part 2 above finishes

第3部分的死锁。我认为原因是第2部分中的文档需要一段时间才能从WCF服务提交到SQL服务器,并且在此期间它会锁定表。

因此,如果我们从数据库应用程序#1加载,那么相关文档就会出现问题。

我正在使用实体框架。我怎么解决这个问题?我真正想做的就是在完全提交的情况下加载文档,而不是在被锁定的表格或任何东西中运行。

顺便说一下,这是我得到的具体错误,

Message: Transaction (Process ID 93) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

更新:我有几条评论可以改变操作顺序。我实际上无法做到这一点,因为第2部分和第3部分来自对WCF服务的不同调用。因此,服务的用户可以订购操作。 “请他们改变它”你说,但它也不是那么简单。操作的顺序实际上取决于最终用户恰好在适当的时候“刷新”他们的浏览器。

更新#2:我需要一些关于如何复制此问题的建议。我已经编写了一个测试应用程序,上面的第2部分确实阻止了第3部分中的操作,但是对我来说后果是操作3只是阻塞直到操作2完成,然后操作3结束。

这意味着第3部分需要1分50秒而不是3分。任何想法为什么它会阻止我,而不是造成死锁?它是否与该服务器上的整体数据库流量相关,因为我正在使用测试服务器,或者某些数据库设置是否会影响它?

2 个答案:

答案 0 :(得分:1)

通常有几种方法可以避免死锁(SQL Server和其他数据库):

1)仅在交易结束时调用saveChanges(),以便一起执行所有查询。

2)更改顺序以执行数据库更新,首先执行所有读取(SELECT)并最后执行所有更新。

3)执行未在交易中修改的数据交易的读数。

4)如果应用程序逻辑允许,将事务的隔离级别更改为SERIALIZABLE(性能不佳)或SNAPSHOT或其他没有锁定的中间件,如READ UNCOMMITTED。

5)使用lock(lock_object)创建同步代码块,以避免两个线程并行执行相同的事务或执行两个锁定自身的不同事务。

答案 1 :(得分:1)

一些解决方案:

  • 如果您不介意在步骤3中显示可能有未提交的行,则使用READ UNCOMMITTED的隔离级别(这取决于您的情况)。

OR

  • 更有效地批量更改您的EF上下文并确保它们一次执行(没有看到您的代码我不确定您是否这样做)

修改

以下链接也可能有助于排查和解决您的问题:

http://blogs.msdn.com/b/bartd/archive/2006/09/09/deadlock-troubleshooting_2c00_-part-1.aspx