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 在多个线程中插入死锁的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中使用双重检查锁定死锁

由于多线程插入导致 MySQL 死锁

使用 INSERT INTO (SQL Server 2005) 插入多个值

如何在不同条件的sql server的case语句中插入多个else?

使用 Monitor 线程插入查询时 SQL 中的死锁 [关闭]

如何处理SQL Server死锁问题