sql server是否锁定整个表并在表为堆时保持锁定状态?

var*_*ble 2 sql-server heap sql-server-2019

无论 where 子句如何;

当表是堆(没有聚集索引)时,选择查询是否会使sql server锁定所有行,直到它完成读取所有行?

在具有聚集索引的表的情况下,sql server将逐一锁定行并在读取该行后立即释放它们?

有关此主题的任何参考链接都会非常有帮助。

Pau*_*ite 9

堆表支持多种锁粒度,包括RID(行标识符)、PAGE、分区和表。

来自文档:锁定数据库引擎

应用程序通常不会直接请求锁。锁由 SQL Server 数据库引擎中称为锁管理器的部分进行内部管理。当 SQL Server 数据库引擎实例处理 Transact-SQL 语句时,SQL Server 数据库引擎查询处理器确定要访问哪些资源。查询处理器根据访问类型和事务隔离级别设置确定需要什么类型的锁来保护每个资源。然后,查询处理器向锁管理器请求适当的锁。

存储引擎使用来自查询处理器的信息和提示来确定运行时的初始锁定粒度。您可以通过和 等提示来影响此决定。引擎可能会在执行期间尝试将锁升级到分区或表级别。ROWLOCKPAGLOCK

这并不完全“不考虑 where 子句”,因为基数估计是从 QP 传递到 SE 的影响锁定粒度决策的因素之一。获取和释放锁并不是免费的。如果预期有大量操作,则引擎可以选择例如页粒度而不是行。

另一个因素是行目标的存在,例如因为查询有一个TOP子句或等效的东西。如果引擎能够期望在不读取太多数据的情况下定位所需的行数,则它可能会选择 RID 锁。

锁的类型和持续时间还取决于引用中提到的事务隔离级别。它还可能取决于隔离级别的实现。例如,使用版本控制 (RCSI) 的已提交读在读取时通常不会采用共享锁,但锁定已提交读会采用共享锁。

在锁定已提交读(非云 SQL Server 的默认设置)下,单个共享锁通常会尽快释放。对于 RID 锁,这意味着每行在处理时都被共享锁定。该锁通常在获取下一行的锁之前被释放。请参阅Craig Freedman 的“读取提交的隔离级别” 。