是否所有死锁都是由错误查询引起的

Posted

技术标签:

【中文标题】是否所有死锁都是由错误查询引起的【英文标题】:Are all deadlocks caused by a bad query 【发布时间】:2010-03-23 16:05:36 【问题描述】:

“事务(进程 ID 63)在锁上死锁 | 与另一个进程的通信缓冲区资源已被选为死锁牺牲品。重新运行事务。”。可能的失败原因:查询有问题,“ResultSet”属性设置不正确,参数设置不正确,或者连接没有正确建立。”

这种死锁可能是由存储过程使用的东西(如 SQL 邮件)引起的吗?还是它总是导致我的两个应用程序同时访问同一个表?

【问题讨论】:

【参考方案1】:

同时访问同一个表的两个表在一个应用程序中总是发生。一般不会导致死锁。当您说进程“A”尝试更新表 1、表 2 和表 3,而进程“B”尝试更新表 3、表 2 和表 1 时,通常会发生死锁。进程“ A' 将锁定进程'B' 需要的资源,并且进程'B' 具有进程'A' 需要的资源。 SQL Server 将此检测为死锁并将其中一个进程作为失败的事务回滚。

底线是您有两个进程试图同时更新相同的表,但顺序不同。这通常会导致死锁。

在您的应用程序中处理此问题的一种简单方法是处理失败的事务并简单地重新执行事务。它几乎总是会成功执行。更好的解决方案是确保您的流程尽可能以相同的顺序更新表。

【讨论】:

【参考方案2】:

缺少索引是死锁的另一个常见原因。如果选择查询可以从索引而不是基表中获取所需的信息,那么它不会被表本身的任何更新/插入阻塞。

要确定,请使用 SQL 分析器跟踪“死锁图”事件,这将向您显示死锁本身的详细信息。

【讨论】:

【参考方案3】:

基于this,我认为SQL Mail 本身不会直接 成为罪魁祸首。我说“直接”是因为我不知道你在用它做什么。但是,我假设 SQL Mail 与您的其他 SQL 操作相比可能很慢,所以如果您在这方面做了很多事情,它可能会间接造成瓶颈,从而导致死锁。在发送 SQL 邮件时重新持有表。

如果没有太多关于你正在做什么的细节,很难推荐一个具体的策略。简而言之,您应该考虑是否有一种方法可以在您执行此操作时打破对持有表的依赖,例如使用 NOLOCK、使用临时表或非临时“持有”表或只是重构 SP那是在打电话。

【讨论】:

以上是关于是否所有死锁都是由错误查询引起的的主要内容,如果未能解决你的问题,请参考以下文章

导致死锁错误的 SQL 查询

分区会防止数据库死锁,当它们是由否则会进入两个分区的行引起的?

Process的Waitfor() 引起代码死锁

经典 ASP - 捕获 500 错误

为啥分段错误是由类变量顺序引起的?

java多线程13 : 死锁