增加的网络延迟会导致 MS SQL Server 中的表锁定吗?

Eva*_*n M 16 sql-server network locking

如果我通过高延迟网络对 SQL Server 数据库进行一次调用,是否会由于该延迟而发生表锁定?假设我查询表 A 中的某些记录,并且 SQL Server 必须通过慢速网络返回该数据 - 当服务器通过网络发送响应时,表 A 上是否存在读取锁定,或者 SQL Server 在发送之前是否释放锁定响应?

此外,答案是否会根据响应的大小而有所不同?如果它只需要返回几 KB 与几百 MB,那会有什么不同吗?

创建显式事务、运行查询和关闭事务显然会导致表锁定,因为事务的持续时间与我的延迟相关。

Mar*_*ith 15

如果客户端需要很长时间来接收数据,然后又向 SQL Server 发送确认,它已收到 SQL Server 必须等待的数据,由于此等待,除非收到来自客户端的确认,否则 SQL Server 将不会释放查询持有的锁。

这不准确,它取决于隔离级别。

默认情况下READ COMMITTED,在语句执行期间不持有锁。READ COMMITTED不提供语句级读一致性,唯一的保证是你不能读取未提交的数据。获取并持有共享锁以读取该行,然后释放。

除非您有 LOB 类型。

LOB 类型可能非常大,无法缓冲。在语句完成之前,必须获取并保持共享锁,这实质上是REPEATABLE READ在 处为您提供行为READ COMMITTED

如果我通过高延迟网络对 MSSQL 数据库进行一次调用,是否会由于该延迟而发生表锁定?

延迟不会导致表锁定,不。但是,如果已获取表锁,则延迟会延长它。

引用一个比我更了解这个机制的人(@RemusRusanu):

随着执行的进行,结果将返回给客户端程序。当行在执行树上“冒泡”时,顶级操作员通常负责将这些行写入网络缓冲区并将它们发送回客户端。结果不是首先创建到某个中间存储(内存或磁盘)然后发送回客户端,而是在创建时发送回(在查询执行时)。将结果发送回客户端当然要遵守网络流量控制协议。如果客户端没有主动使用结果(例如,通过调用 SqlDataReader.Read()),那么最终流控制将不得不阻塞发送端(正在执行的查询),这反过来将暂停执行询问。[来源]

在结果没有像 SQL Server 交付时那样快速消耗的情况下,无论是由于客户端还是网络,我们都会看到ASYNC_NETWORK_IO等待累积。重申一下,这不会影响获取的锁,只会影响它们被持有的持续时间。


Eva*_*n M 9

Mark 的回答消除了我的很多困惑,但我想在使用 NetBalancer 模拟延迟进行测试后发布我的发现。

我让我的本地机器调用远程 SQL 服务器并在一个小事务中的表上执行 SELECT 和 INSERT。在远程机器上,我连接到本地 SQL 实例并使用 WHILE 循环重复遍历 sys.dm_tran_locks 表,查找我正在修改和读取的表上的任何锁。我在服务器上安装了 NetBalancer,并用它来模拟服务器网络连接上的网络延迟。

这是我发现的:

  • 对于不向客户端返回大量数据的语句,延迟对锁定没有影响。 我最多只返回几百字节的数据。我机器上的事务有一个 250 毫秒的等待时间来保持锁定,当我将网络延迟增加到 5000 毫秒时,锁定持续时间保持接近 250 毫秒。
  • 对于返回大量数据的语句,延迟肯定会影响锁定我将数万行返回给客户端,并且没有延迟,锁定持续时间很短。当我增加延迟时,锁会一直持续到我收到所有数据。

由此,我得出的结论是,只要数据适合网络缓冲区,延迟就无关紧要。如果 SQL 必须将大量数据放入网络缓冲区,延迟将导致该缓冲区备份,并且 SQL 将持有表锁,直到它可以将所有查询结果放入缓冲区。