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


16

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

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

创建一个显式事务,运行查询并关闭该事务显然会导致表锁定,因为事务的持续时间与我的等待时间相关。


除非您指定nolock提示,否则总会有一个锁。延迟仅确定锁定将保持多长时间。
布兰登2014年

3
即使使用nolock您仍然会收到锁
billinkc 2014年

@brandon微软在任何地方都有记录吗?我的搜索结果为空。
伊万M

1
@Brandon NOLOCK并不表示您认为的含义。
亚伦·伯特兰

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<-这意味着如果您使用nolock,则可能没有锁。我只是在澄清。
亚伦·伯特兰

Answers:


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等待的积累。重申一下,这不会影响所获取的锁,只会影响其持有的持续时间。


9

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

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

这是我发现的:

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

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


有趣的结果。这是什么客户端程序/库?
詹姆斯L

好东西。您是否有机会花更多的时间在此上,看看是否可以确定发生这种情况的结果大小?
Mark Storey-Smith

@ MarkStorey-Smith我认为我无法获得精确的值,并且无疑会因机器而异。从vircom.com/security/improve-sql-nic-performance看来,这是您本地NIC上的一项设置,而我的数据库服务器上的设置已设为“自动”
Evan M

@James我刚刚在两台机器上都使用了SSMS
Evan M

0

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

当查询被SQL Server触发并完成后,它会生成结果,将其放在输出缓冲区中并将其发送给客户端,然后客户端将从输出缓冲区中获取结果。除非从客户端收到确认,否则SQL Server将不会释放查询持有的锁。这可能导致阻塞。

编辑:埃文,您可以参考此MS支持文章

在第3节中

由SPID引起的阻塞,其对应的客户端应用程序未获取要完成的所有结果行

将查询发送到服务器后,所有应用程序必须立即获取所有结果行以完成操作。如果应用程序未获取所有结果行,则可以在表上保留锁,从而阻止其他用户。如果使用的应用程序将SQL语句透明地提交到服务器,则该应用程序必须获取所有结果行。如果不是(并且无法对其进行配置),则可能无法解决阻塞问题。为避免此问题,您可以将行为不佳的应用程序限制为报表数据库或决策支持数据库。


感谢您的回答,Shanky!您是否知道这是否记录在任何地方?
Evan M


5
这是不正确的。
Mark Storey-Smith

这似乎是正确的,似乎“应用程序未获取所有结果行,锁可能留在表上,从而阻止了其他用户。如果使用的应用程序将SQL语句透明地提交到服务器,则该应用程序必须获取所有结果行。如果不是(并且无法对其进行配置),则可能无法解决阻塞问题。为了避免该问题,您可以将行为不佳的应用程序限制为报表或决策支持数据库。我说的更多。您可以从此处阅读support2.microsoft.com/kb/224453
Shanky

4
@Shanky创建一个大表。在一个SSMS连接中SELECT *从它READ COMMITTED插入,从另一个监视器锁定。在任何时候,您看到多少把锁?
Mark Storey-Smith
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.