如果并行交换事件死锁是无受害者的,这是一个问题吗?

Mar*_*son 15 sql-server deadlock parallelism

我们在生产环境(SQL Server 2012 SP2 - 是的......我知道......)中看到了很多这些查询内并行线程死锁,但是当查看通过扩展事件捕获的死锁 XML 时,受害者列表是空的。

<victim-list />
Run Code Online (Sandbox Code Playgroud)

死锁似乎在 4 个线程之间,两个线程WaitType="e_waitPipeNewRow"和两个WaitType="e_waitPipeGetRow".

 <resource-list>
  <exchangeEvent id="Pipe13904cb620" WaitType="e_waitPipeNewRow" nodeId="19">
   <owner-list>
    <owner id="process4649868" />
   </owner-list>
   <waiter-list>
    <waiter id="process40eb498" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe30670d480" WaitType="e_waitPipeNewRow" nodeId="21">
   <owner-list>
    <owner id="process368ecf8" />
   </owner-list>
   <waiter-list>
    <waiter id="process46a0cf8" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe13904cb4e0" WaitType="e_waitPipeGetRow" nodeId="19">
   <owner-list>
    <owner id="process40eb498" />
   </owner-list>
   <waiter-list>
    <waiter id="process368ecf8" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe4a106e060" WaitType="e_waitPipeGetRow" nodeId="21">
   <owner-list>
    <owner id="process46a0cf8" />
   </owner-list>
   <waiter-list>
    <waiter id="process4649868" />
   </waiter-list>
  </exchangeEvent>
 </resource-list>
Run Code Online (Sandbox Code Playgroud)

所以:

  1. 受害者名单为空
  2. 运行查询的应用程序没有出错并完成查询
  3. 就我们所见,除了图形被捕获之外,没有明显的问题

所以,这除了噪音还有什么可担心的吗?

编辑:感谢 Paul 的回答,我可以看到问题可能发生的位置,并且似乎可以通过 tempdb 溢出自行解决。 在此处输入图片说明

Pau*_*ite 15

如果这是通过交换溢出解决查询内并行死锁时死锁图的显示方式,我不会感到惊讶(因此除了性能之外没有受害者)。

您可以通过捕获交换溢出并将它们与僵局匹配(或不匹配)来证实这一理论。

将交换缓冲区写入tempdb以解决死锁并不理想。希望消除执行计划中的顺序保留操作序列(例如,提供并行合并连接的顺序保留交换)。除非它不会引起明显的性能问题,而且您还有其他事情要担心。

出于兴趣,这个问题是否可能因高度碎片化/过时的统计数据而加剧?

碎片化,没有。过时的统计数据:在我能想到的任何特定意义上都没有,没有。当然,不具代表性的统计数据一般来说很少是好事。

这里的基本问题是,当线程之间的依赖关系尽可能少时,并行效果最好;保留顺序引入了相当讨厌的依赖关系。事情很容易被搞砸,而解决这个僵局的唯一方法是将交换中保存的一堆行溢出到tempdb


笔记

在针对 SQL Server 2017 的累积更新 10 和 SQL Server 2016 SP2 的累积更新 2 发布修复程序后,当死锁可以通过交换溢出解决时,查询内并行死锁不再生成 xml 图形。