2011-04-29 96 views
20

偶尔交易的僵局,我有一个存储过程以下错误这是只有一个选择查询:Transaction (Process ID 91) was deadlocked on lock为select查询

我最初的理解是一个选择查询将不会锁定表,或将不即使它试图查询的表正被另一个进程更新/锁定,也会导致死锁,但似乎选择查询也会导致死锁。

如果我将查询的隔离级别设置为未提交读取,是否解决问题?

+0

请显示查询。 – 2011-04-29 00:32:14

回答

38

我的init的理解是,一个选择 查询将不会锁定表,或不会 导致死锁

这种认识是错误的。 SELECT查询对他们分析的行使用共享锁。共享锁可能与来自update/delete/insert语句的排它锁冲突。两个SELECT语句不会发生死锁,但是SELECT可以用UPDATE进行死锁。当发生这种死锁时,SELECT通常是受害者,因为它没有执行任何更新,所以总是会失去平局。

与任何死锁一样,您需要发布所涉及表的确切模式,确切的T-SQL语句和死锁图。请参阅How to: Save Deadlock Graphs (SQL Server Profiler)。有了这些信息,您可以得到如何解决死锁的指导。

+0

谢谢,这是有道理的。 – peanut 2011-04-29 02:30:57

+0

@Remus Rusanu其实,两个select语句可能会死锁。请参阅https://dba.stackexchange.com/questions/152768/seeing-2-exclusive-locks-on-the-same-index-is-this-possible。你能解释一下吗? – kolobok 2018-02-20 15:46:51

+0

@kolobok请将问题作为单独问题而不是评论。在这里发布问题的链接。 – 2018-02-20 17:22:12

4

如果您使用的是SQL Server 2008,则可以将隔离级别设置为未提交读取以防止死锁。看到这个link。当读取未提交或WITH(NOLOCK)时,必须知道查询重新构造的数据可能不是真正的!

5

就像Remus所说的那样,你正在得到死锁,因为SELECT和UPDATE(或其他)操作相互死锁,而不是SELECT和SELECT。您必须查看所有涉及该表的查询,并为这些查询创建适当的覆盖索引,这将解决您的问题。良好的覆盖索引是首选解决方案,而不是使用WITH(NOLOCK)表提示。

关于如何创建覆盖索引及其如何影响死锁,请参阅以下link