我有一个VB6应用程序通过ADO访问MSSQL2000服务器上的单个表。我正在使用只读访问权限(adOpenStatic,adLockReadOnly)网络中还有其他应用程序可以对表进行更改。
出于某种原因,我收到的错误是我的应用程序被选为死锁受害者。
我真的很困惑:为什么当我从单个表中读时会出现死锁?我期待超时,因为其他应用程序的编写,但不是死锁......
有人可以对此有所了解吗?
更新:2009-06-15 我仍然对此问题的解决方案感兴趣。所以我提供了更多信息:
答案 0 :(得分:13)
由于存在非聚集索引,单个SELECT语句可能会针对单个UPDATE或DELETE语句发生死锁,请考虑以下情况:
读者(您的应用)首先获取非聚集索引上的共享锁以执行查找,然后尝试在页面上获取共享锁,以便返回数据本身。 / p>
编写器(其他应用程序)首先在包含数据的数据库页面上获得一个exlusive锁,然后尝试获取索引的独占锁,以便更新索引。
您可以在Microsoft知识库文章Q169960(http://support.microsoft.com/kb/q169960/)中找到有关此(及其他)此类死锁的更多信息
此外,您可能希望了解一下如何获取死锁跟踪信息(跟踪标志1222) - 这将报告发生死锁时究竟哪些SQL语句与哪些对象发生冲突。这是一篇相当不错的文章 - http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx
答案 1 :(得分:3)
我认为这里已经提供的答案有很多可能性。由于您只使用共享锁,因此死锁不能归因于锁升级,并且必须只是获取与在另一个进程中获取的锁不兼容的锁,并以不同的顺序获取这些锁...
您的共享锁与另一个采用独占锁的进程不兼容。场景可能会运行这样......
N.B。僵局可以拥有更多的玩家,而不仅仅是2.有时会出现一系列交织活动导致僵局,但原则是相同的。
通常,如果多个应用程序访问同一个数据库,则有一个DBA通过存储过程管理所有访问,因此他可以确保资源始终以相同的顺序锁定。如果您不处于这种情况,并且其他应用程序使用临时SQL语句,则必须检查其代码,以确定它们是否可能以我所描述的方式与您的应用程序冲突。这听起来不是很有趣。
实用的解决方案可能是在您的事务作为死锁受害者被杀死时捕获错误,并且只是多次重试该事务。根据其他应用程序生成的活动量,您可以通过这种方式获得可接受的结果。
答案 2 :(得分:1)
这里描述了几个案例:
答案 3 :(得分:0)
读取仍然会产生锁定,以便DB确保在非atmic读取过程中完成写入操作。换句话说,读锁定可确保您获得正在选择的任何数据的准确一致快照。
答案 4 :(得分:0)
您对adOpenForwardOnly
的行为是否相同?
您可能想要检查您的SQL Server统计信息是否是最新的。或者您可以让DBA重建所有索引。许多锁定问题都是由于过时的统计信息/索引造成的。
答案 5 :(得分:-1)
这取决于应用程序的行为。 你的应用程序肯定会在另一方面等待释放资源。
答案 6 :(得分:-1)
死锁是指两个或多个进程正在等待彼此释放资源,或者两个以上的进程正在等待循环链中的资源时的情况。当然,您可以使用只读访问权限创建死锁,因为读取不会等待。
的死锁条件有一个很好的解释答案 7 :(得分:-2)
这不是这样的吗?
其他应用程序:写入表(获取表上的写锁定)
您的应用程序:从表中读取(获取表上的读锁定,因写入锁定而无法读取)。