SQL Server 在多个线程中插入死锁
Posted
技术标签:
【中文标题】SQL Server 在多个线程中插入死锁【英文标题】:SQL Server Insert in several Threads Deadlock 【发布时间】:2011-12-21 12:52:32 【问题描述】:我在一个具有许多并发线程的表中插入,在这个表中是一个 AFTER INSERT 触发器,它更新插入行上的一个字段。 当这在一个线程中执行时,一切都很好,但是有很多线程我遇到了死锁。 有什么我可以做的吗?
【问题讨论】:
你能告诉我们插入和触发器的 SQL 吗? 【参考方案1】:要么不为此过程使用多个线程(我认为这不是一个合理的选择),要么不使用触发器,而是使用后处理存储过程来一次更新所有记录。
【讨论】:
【参考方案2】:我建议您捕获死锁事件图,以识别正在争夺哪些数据库对象/资源(并最终导致死锁)。
见:Detecting and Ending Deadlocks
您还应该查看此过程中涉及的查询的执行计划。您可能会发现特定列是争用的来源(通常通过表/索引扫描),可以通过部署合适的索引来解决(以鼓励 Index Seek 操作)。
【讨论】:
【参考方案3】:在所有更新发生之后,是否可以删除触发器并通过代码运行等效操作? 还是运行定期过程来执行触发器的等效操作?
除此之外,我想查找锁定提示可能是个好主意?也许您的触发器可以使用 nolock 提示?
【讨论】:
NOLOCK 没有帮助...该语句看起来像 UPDATE field = 'some text' + otherfield WHERE ID IN (SELECT ID FROM INSERTED) 您是否尝试将锁定提示放在选择以及更新上? 'UPDATE Table WITH NOLOCK set field = 'some text' + otherfield WHERE ID IN (SELECT ID FROM INSERTED WITH NOLOCK)' 或者类似的东西?【参考方案4】:如果您将值更新为插入的一部分,而不是插入后触发器,该怎么办。您可能还想查看整体的 db 使用情况。可能有一种方法可以通过更改某些查询来减少死锁的可能性。
【讨论】:
【参考方案5】:从长远来看,最简单的方法是完全避免高并发。您可以通过临时表或表值参数批量插入行吗?你可以从一个连接中做到这一点吗?这可能会更快并且没有死锁。
虽然我们的系统有很多 OLTP 修改,但至少从 4 月份开始,我们已经完全没有死锁了。
Also I wrote a canned answer with more approaches.
【讨论】:
以上是关于SQL Server 在多个线程中插入死锁的主要内容,如果未能解决你的问题,请参考以下文章
使用 INSERT INTO (SQL Server 2005) 插入多个值
如何在不同条件的sql server的case语句中插入多个else?