我有一个错误日志报告死锁:
事务(进程 ID 55)在 lock | 上陷入死锁与另一个进程的通信缓冲区资源,并已被选为死锁受害者。重新运行交易。
我正在尝试重现此错误,但我的标准死锁 SQL 代码产生了一个不同错误:
事务(进程 ID 54)在 锁定资源 上与另一个进程发生死锁,并被选为死锁受害者。重新运行交易。
我想非常清楚地表明我不是在问什么是死锁。我确实了解基础知识。
我的问题是:在这种情况下
lock | communication buffer resources
的含义是什么?什么是“通信缓冲资源”? lock |
有什么意义吗?
我最好的猜测是,当并行线程组合其结果时,会使用通信缓冲区。谁能证实或否认这一点?
我的最终目标是以某种方式触发第一个错误再次发生。
我会将该消息解释为锁定资源或通信缓冲区资源的某些组合上的死锁。 “锁资源”是普通对象锁,“通信缓冲区资源”是用于组合并行查询结果的交换事件。这些在 https://blogs.msdn.microsoft.com/bartd/2008/09/24/todays-annoyingly-unwieldy-term-intra-query-parallel-thread-deadlocks/ 中有进一步描述,其中相关段落是:
“exchangeEvent”资源指示查询计划中存在并行运算符。 这个想法是将大型扫描、排序或连接等操作的工作进行划分,以便可以在多个子线程上执行。 有“生产者”线程执行繁重的工作并将行集提供给“消费者”。 查询内并行需要在这些工作线程之间发送信号:消费者可能必须等待生产者向他们提供更多数据,而生产者可能必须等待消费者完成对最后一批数据的处理。 与并行性相关的等待在 SQL DMV 中显示为 CXPACKET 或 EXCHANGE 等待类型(请注意,这些等待类型的存在是正常的,并且仅指示并行查询执行的存在 - 就其本身而言,这些等待并不指示此类型或正在发生任何其他类型的死锁)。
我见过的其中一个死锁图包括一组只有一个 SPID 的进程以及一个对象锁和交换事件图。我猜消息“事务(进程 ID 55)在锁 | 与另一个进程的通信缓冲区资源上死锁,并已被选为死锁受害者。重新运行事务”出现而不是“查询内并行性导致您的服务器命令” (进程 ID #51)通过使用查询提示选项 (maxdop 1)“”在没有查询内并行性的情况下重新运行查询,因为对象锁和ExchangeEvents,否则自本文撰写以来,SQL Server 中的消息已被更改。
您可以使用 MAXDOP 1 作为查询提示 - 即在一个 cpu 上运行该查询 - 而不影响服务器的其余部分。
您的问题与并行性相关,并且该错误“没有意义”,因为错误消息没有反映您的问题,并且不要去更改 maxdope 设置。为了找到错误的原因,您需要使用跟踪标志 1204
当你这样做时,你会得到关于为什么、在哪里以及哪一行代码导致锁定的答案。我想你可以从那时开始搜索自己,如果没有,那么发布它,你会得到你需要的答案。
只需要在这里更新以使其他人受益,对我来说这是一个奇怪的错误消息,花了很多时间解决错误消息。最后在网上得到了一条线索,我应该使用查询选项 MAXDOP 1 来避免并行性。当我选择它时,错误消息完全不同。实际上是由于 varchar 列中的 insert 语句导致字符串截断,调整了要摄取的字符串的长度,一切都恢复正常。
在我的例子中,更新负载非常重,出现此错误是因为存储过程使用了更新并且没有在搜索字段上使用索引。表不大,最多有3000条记录,但更新很广泛。创建索引解决了 MS SQL Server 2019 的问题