【问题标题】:SQL Server Insert in several Threads DeadlockSQL Server 在多个线程中插入死锁
【发布时间】:2011-12-21 12:52:32
【问题描述】:

我在一个具有许多并发线程的表中插入,在这个表中是一个 AFTER INSERT 触发器,它更新插入行上的一个字段。 当这在一个线程中执行时,一切都很好,但是有很多线程我遇到了死锁。 有什么我可以做的吗?

【问题讨论】:

  • 你能告诉我们插入和触发器的 SQL 吗?

标签: c# .net sql sql-server deadlock


【解决方案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.

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-14
          • 1970-01-01
          • 2019-07-11
          • 1970-01-01
          • 1970-01-01
          • 2018-06-16
          相关资源
          最近更新 更多