SQL Server:锁定通信缓冲区资源上的死锁

35 sql-server-2008 deadlock

这种死锁类型的可能原因是什么?(一般不是死锁)

锁定通讯缓冲区资源

此指示的系统是否内存不足且缓冲区计数超出限制?

详细错误:

事务(进程 ID 59)在与另一个进程的锁定通信缓冲区资源上发生死锁,并已被选为死锁牺牲品。重新运行事务

小智 30

常见的完整信息:

事务(进程 ID 53)因锁定而死锁 | 与另一个进程的通信缓冲区资源并已被选为死锁受害者。重新运行事务。

这种锁类型常见于 SQL Server 作为并行执行的死锁查询,有时称为“查询内并行死锁”。我看到一些声明,这也指出系统资源不足,我想这可能涉及到很小的程度。

我注意到确定它是否是并行死锁的一般准则是,当您拉出 XML 死锁图(可以在 2008 年及更高版本中使用 system_health 会话完成)时,您会注意到不同的进程 ID 显示相同的代码位执行栈。

同样,查看死锁图的资源列表并注意服务员事件的类型。他们最常显示“e_xxxxxx”,或者类似的东西:

<waiter-list>
 <waiter event="e_waitPipeGetRow" type="consumer" id="process821d828" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process8209198" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process3827c18" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process3809eb8" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process8226b08" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process9acb6d8" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process6188d7828" />
 <waiter event="e_waitPipeGetRow" type="consumer" id="process381cef8" />
</waiter-list>
Run Code Online (Sandbox Code Playgroud)

为了尝试解决这个问题,网上和书中提供了各种途径。我通常首先查看查询/过程的执行计划,并关注显示并行执行的区域。然后从那里开始尝试首先调整查询,然后作为最后的手段可能开始使用查询提示。

您将看到的解决这些死锁的最常见查询提示是实现MAXDOP 1. 但是,在此之前,您可能会检查服务器级别 MAXDOP 和成本阈值的设置。默认情况下,成本阈值通常设置为 5,我喜欢将其提高到 35 或 40 开始,如果有问题的查询对该部分代码的成本很低,它可能根本不需要并行运行。我不太喜欢使用 MAXDOP 查询提示,但这并不意味着它们没有自己的位置和目的。只是我的观点。

  • 由于这个问题在搜索引擎结果中占有重要地位,因此应该注意至少解决了 2 个涉及列存储索引的死锁相关错误。[链接](https://support.microsoft.com/en-us/help/4057055/deadlock-when-you-run-parallel-query-on-clustered-columnstore-index), [链接 2](https: //support.microsoft.com/en-us/help/4506912/fix-concurrent-inserts-into-a-cci-can-cause-deadlock-under-memory-pres)。我很难解决这个问题,直到我意识到这是由于列存储索引造成的。 (2认同)