由于正在进行的 ASYNC_NETWORK_IO 而暂停的查询是否会导致阻塞?

var*_*ble 4 sql-server blocking waits sql-server-2019

我正在查看dm_exec_sessions请求生产服务器上的 DMV。有些查询的状态为“已暂停”,持续时间为 12 分钟,等待类型为ASYNC_NETWORK_IO

我理解这是因为客户端应用程序获取数据的速度不够快(或者结果太大以至于客户端程序需要时间来消耗它)。

这样的查询(由于正在进行的查询而暂停ASYNC_NETWORK_IO)是否会导致该表阻塞?

该查询是 a SELECT,我看不到该查询阻止任何其他查询。因此我要问的问题是它是否有可能阻止任何东西。

例如:是否ASYNC_NETWORK_IO意味着执行正在进行或执行已完成并且客户端应用程序正在提取数据?在后一种情况下,我不明白为什么这个查询可能会阻止其他查询,因为它已经产生了结果。

查询持有的锁如下:

  • 页面锁定请求方式S
  • 对象锁请求方式IS

Pau*_*ite 13

这样的查询(由于正在进行的 ASYNC_NETWORK_IO 而被暂停)是否会导致该表阻塞?

可能会也可能不会。

ASYNC_NETWORK_IO它本身无法阻止其他任何人(好吧,如果您的系统用完工作线程,它可以,但这是一种边缘情况)。请继续阅读。

例如:ASYNC_NETWORK_IO 是否意味着执行正在进行或执行已完成并且客户端应用程序正在提取数据?

您说运行查询的会话是“挂起”而不是“睡眠”。根据定义,挂起的查询尚未完成。如果它完成了,它将具有“完成”(非常短暂)或“睡眠”状态。

在后一种情况下,我不明白为什么这个查询可能会阻止其他查询,因为它已经产生了结果。

嗯,会话正在锁定。这些锁会阻止任何其他需要不兼容锁的会话。换句话说,暂停的会话可能会阻止其他人,但目前还没有。

重要的一点是,阻塞的是,而不是ASYNC_NETWORK_IO状态直接。

此时您可能会问为什么会话持有锁。

您可能有一个心理模型,其中 SQL Server 生成结果,将其存储在某处,然后结束查询并等待客户端使用结果。(通常)这不是它的工作原理。总是在服务器上存储任意大的结果是低效且不切实际的。

相反,SQL Server在执行计划中可用时将结果行流式传输到客户端,您可以将其视为数据的“管道”。当客户端停止接收行时,管道将停止,并且执行将暂停,直到客户端再次开始请求行。

如果会话挂起时查询持有锁,则只要挂起状态持续,这些锁就会继续持有。


旁注:

服务器和客户端之间有少量缓冲(相当于几个网络数据包),但这通常不足以保存整个结果,并且无论如何,直到客户端读取行而清空缓冲区后,查询才会完成。

A query won't always hold locks when suspended. It depends on what the execution plan looks like and what it was doing when SQL Server tried to put the next result row in the buffer and found no room.

For example, some plans might have a final sort that will indeed consume all result rows in order to sort them. Data access has finished by the time the sort is ready to produce output, so there often won't be any need to hold locks (depending on isolation level etc.)

For more on how execution plans stream rows one at a time, see my article Iterators, Query Plans, and Why They Run Backwards.