如何消除 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 死锁在生产中超时,而不是在测试环境中:为啥?