选择查询的事务死锁

pea*_*nut 25 sql t-sql concurrency deadlock

有时,我对存储过程只有一个Select查询有以下错误: Transaction (Process ID 91) was deadlocked on lock

我最初的理解是,一个select查询不会锁定一个表,或者即使它试图查询的表被另一个进程更新/锁定也不会导致死锁,但是看起来select查询会导致死锁好.

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

Rem*_*anu 45

我的初步理解是,Select查询不会锁定表,也不会导致死锁

这种理解是错误的.SELECT查询对它们分析的行执行共享锁定.共享锁可能会与update/delete/insert语句中的排它锁冲突.两个SELECT语句不会死锁,但SELECT可以使用UPDATE死锁.当发生这样的死锁时,SELECT通常是受害者,因为它没有执行任何更新,因此总是会失去绘制.

与任何死锁一样,您需要发布所涉及的表的确切模式,确切的T-SQL语句和死锁图.请参见如何:保存死锁图(SQL Server Profiler).有了这些信息,您可以获得如何解决死锁的指导.

  • @Remus Rusanu 实际上,两个选择语句可能会死锁。请参阅 https://dba.stackexchange.com/questions/152768/seeing-2-exclusive-locks-on-the-same-index-is-this-possible 。你能解释一下吗? (2认同)

Ghl*_*ouw 6

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

有关如何创建覆盖索引及其如何影响死锁的详细教程,请参阅以下链接.

  • 链接现在不可用。但我创立了这篇笔记/文章:https://sqlundercover.com/2019/03/05/using-indexing-to-solve-blocking-and-deadlocking-issues/。我希望,它会对某人有所帮助。 (2认同)

RC_*_*and 5

如果您使用的是 SQL Server 2008,您可以将隔离级别设置为未提交读取以防止死锁。请参阅此链接。当读取未提交或 WITH (NOLOCK) 时,必须意识到查询返回的数据可能不是真实的!