SQL 服务器阻塞链

SQL Server Blocking Chains

假设我在 SSMS 中按此顺序运行 有 3 个查询

(1) select * from MainTableA

(2) truncate table MainTableA

(3) select name from MainTableA (nolock) where Id=1

在 (1) 完成之前 (2) 开始,并且在 (2) 完成之前,但在它开始之后,(3) 开始。

(1) 在 MainTableA

上取得 table IS 锁

(2) 等待 MainTableA 上的 Sch-M table 锁并被 (1)

阻止

(3) 等待 MainTableA 上的 Sch-S 锁并被 (2)

阻塞

为什么 (3) 被 (2) 屏蔽了?由于 Sch-S 锁与 IS 锁兼容并且 (2) 尚未获得它的锁,那么 (3) 不应该继续吗?阻塞链显示 (2) 被 (1) 阻塞,(3) 被 (2) 阻塞,但我不明白为什么 (2) 在尚未获得锁时可以阻塞 (3)。

Why is (3) blocked by (2)? Since a Sch-S lock is compatible with an IS lock and (2) hasn't acquired it's lock yet, shouldn't (3) proceed?

这是一个非常好的问题,但并不明显应该如此。事实上,它没有用于阻止。

但当前的行为是等待的 Sch-M 锁会阻止新的 Sch-S 锁请求。因此 (3) 排在 (2) 之后,并且在元数据操作(此处为 TRUNCATE TABLE)完成之前不会获得其 Sch-S 锁。

在旧行为下,(3) 可以继续,但是一旦它获得 Sch-S 锁,那么 将阻止 (2),然后 (4),(5 ), (6) ... 一起来,也获得 Sch-S 锁和阻塞 (2)。并且 (2) 可能必须无限期地等待安静 window 完成。

对于联机数据库操作,元数据更改最好能快速完成,强制新的 Sch-S 锁在挂起的 Sch-M 锁后面等待有助于实现这一点。

当然,有时您更愿意使用 旧的 行为,因此最近针对某些操作重新引入了它作为“低优先级等待”以及新的超时行为。参见 https://bobsql.com/how-it-works-sql-server-locking-wait_with_low_priority/ and https://www.sqlskills.com/blogs/paul/low-priority-locking-wait-types/