并发问题

时间:2010-02-12 05:04:17

标签: sql-server nhibernate concurrency

这是我的情况(SQL Server):

我有一个利用nHibernate进行数据访问的Web应用程序,以及另外3个桌面应用程序。 All访问同一个数据库,并且可能在任何时候都使用相同的表。

现在,在NH的帮助下,我正在批量选择以加载具有其所有层次结构的聚合 - 所以我会看到一次发出4到7个选项(不确定是否重要)。

每隔几天,其中一个应用程序就会得到:“交易被选为死锁受害者。” (这通常出现在选择中)

我尝试更改数据库上的快照隔离,但这没有帮助 - 我最终得到了:

  

快照隔离事务已中止   由于更新冲突。你不能使用   快照隔离访问表   '...'直接或间接地   数据库'...'要更新,   删除或插入具有的行   被他人修改或删除   交易。重试交易或   改变隔离级别   更新/删除声明。

对于这种情况,您有什么建议?我应该尝试什么,或者我应该阅读什么才能找到解决方案?

修改

实际上那里没有突袭:)。每天的用户数量很少(我说每天100个 - 忙碌的一天有数百个小订单),数据库有点大,大约2GB,每天都在增长。

这是一个商业应用程序,可以处理订单,电子邮件,报告,发票和类似的东西。

在这种情况下,延迟加载不是一个选项。

我认为对这些指数进行非常接近的观察是我最好的选择。

3 个答案:

答案 0 :(得分:1)

您的硬件配置是否正确(特别是RAID配置)?它能够匹配您的工作量吗?

如果硬件都很好并且嗡嗡作响,那么您应该确保拥有与您的查询工作负载相匹配的“正确”索引。

使用正确的索引可以消除许多锁定/死锁问题(在插入过程中覆盖索引可以减少聚集索引的压力)。

BTW:打开快照隔离会给你的 tempDB 带来更大的压力。 tempDB是如何配置的? RAID 0是首选(如果tempDB是瓶颈,则更好地使用SSD)。

答案 1 :(得分:1)

死锁很复杂。死锁意味着至少有两个会话具有锁定并且正在等待彼此释放不同的锁定;因为两者都在等待,所以锁永远不会被释放,会话都不会继续,并且会发生死锁。

换句话说,A锁定XB锁定Y,现在A想要Y和{{1}想要B。在他们完成交易之前,他们都不会放弃锁定。两者都会无限期地等待,直到他们得到另一把锁。 SQL Server发现这种情况正在发生并杀死其中一个事务以防止死锁。快照隔离对您没有帮助 - 数据库仍然需要保留事务的原子性。

没有任何人可以简单回答为什么会发生僵局。您需要对应用程序进行概要分析才能找到答案。

从这里开始:How to debug SQL deadlocks。这是一个很好的介绍。

接下来,查看MSDN上的Detecting and Ending Deadlocks。这将为您提供有关死锁发生原因的大量背景信息,并帮助您了解您正在寻找的内容。

您可能还想看一些以前的SO问题:

或者,如果死锁非常罕见,只需在应用程序中编写一些异常处理代码,以便在发生死锁时重试事务。有时,防止某些死锁可能非常困难(如果不是几乎不可能)。只要您编写事务安全代码,它就不是世界末日;再次尝试交易是完全安全的。

答案 2 :(得分:0)

虽然在具有大量用户的NHibernate会话中发现此错误并不罕见,但在您的情况下似乎经常发生这种情况。

也许你的对象非常大,导致长时间选择?如果您的选择花费的时间过长,则可能表明您的索引存在问题(正如Mitch Wheat所解释的那样)

如果一切正常,您还可以尝试Lazy Loading推迟选择,直到您确实需要数据为止。这可能不适合您的具体情况,因此您必须确定它是否有效。