如何消除 SQL Server 2005 中的死锁?

Posted

技术标签:

【中文标题】如何消除 SQL Server 2005 中的死锁?【英文标题】:How to remove deadlocks in SQL Server 2005? 【发布时间】:2012-05-03 10:07:01 【问题描述】:

首先我想知道SQL Server 2005死锁的真正根本原因是什么。是因为当两个进程访问表中的同一行时?

无论如何,请考虑两个表 _Table_Now__Table_History_,它们的结构相同。

假设有一列名为NAME

因此,当一个进程尝试在_Table_Now_ 中更新带有NAME='BLUE' 的记录时,首先需要将带有NAME='BLUE' 的当前行放入_Table_History_ 然后更新 _Table_Now_,并从 _Table_History_ 中删除先前存在的行。

删除时发生死锁。我不明白为什么?

请指导我!

【问题讨论】:

死锁通常涉及多个并发事务。您已经描述了一笔交易。死锁还涉及哪些其他事务? 好的做法是通过为每个查询提供提示(例如 with (NOLOCK)with (ROWLOCK))来避免死锁,要删除锁,您可以使用 kill N 杀死其中一个 spid,其中 n 是 spid id 允许对方继续 没有更多信息将很难提供帮助。这是一个关于如何使用 SQL Profiler 分析死锁的链接msdn.microsoft.com/en-us/library/ms188246.aspx 【参考方案1】:

死锁基本上意味着当进程A依赖于进程B并且进程B依赖于进程A时,所以A只会在B完成时启动\继续,而B只会在A完成时启动\继续

您可能遇到的是表(或行)锁定,因此 SQL 在更新表之前锁定该行,以确保在进行更新时没有其他进程尝试访问该行。

您能否更具体地说明您是如何执行插入\更新\删除的。在这种情况下,您不应该出现死锁。

仅供参考,请勿使用with (NOLOCK)。它会阻止锁定,但它是通过告诉 SQL Server 读取未提交的数据来实现的,并且最终可能导致数据不一致。

【讨论】:

这就是我担心的原因。在正常情况下不应该有任何死锁。即使我打开新的查询窗口并编写一个简单的选择查询,如 SELECT * FROM Table_History where NAME='BLUE' ... 有时执行此语句时会显示死锁。 你能提供更多关于死锁是如何发生的信息 好的。我正在使用 sql server 2005。现在在 sql server 2005 中,一些连接是可运行的,一些正在休眠,但一些被挂起。当 SUSPENDED 连接的数量增加时,应用程序就会关闭。我执行了 sp_who2 我想我需要更强大的sql server 2005。我如何学习sqlserver 2005的内部工作?像上述情况一样,选择查询实际上是如何执行的?有什么学习资料吗??【参考方案2】:

当进程 A 等待进程 B 释放资源而进程 B 正在等待进程 A 释放资源时,就会发生死锁。

如果我正确理解了更新的顺序,那就是: 1. 读取 Table_Now 中的一行 2. 更新 Table_History 中的一行 3. 更新 Table_Now 中的一行 4. 删除 Table_History 中的一行。

如果您错误地使用事务或锁定,这可能是一个有风险的订单。

为避免死锁,您应该为每个进程执行: 1.开始事务(最好是表锁) 2. 执行所有数据库操作 3. 提交事务(或回滚,以防数据库更新时出现问题)

这将确保每个进程都锁定两个表,执行所有操作然后退出。

如果您已经在使用事务,您使用的是什么范围和级别?如果没有,请引入交易。它应该可以解决问题。

【讨论】:

在所描述的场景中,事务肯定会造成死锁:) 您通常可以在步骤 1 中使用 (updlock) 提示来避免它们 - 请阅读 Table_Now。 我没有使用上面的原因。如果上述任何一项都不起作用,我将丢失传入记录。假设删除失败。因此,当回滚时,所有​​内容都将被还原。插入到 Table_Now 是非常高的优先级

以上是关于如何消除 SQL Server 2005 中的死锁?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2005 中的死锁!两个实时批量更新正在战斗。为啥?

SQL Server 2005 密钥死锁

sql server 2005 死锁在生产中超时,而不是在测试环境中:为啥?

sql server2005的死锁

SQL Server 2005:读取提交事务隔离级别中的键范围锁?

SQL Server中解决死锁的新方法介绍