You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SELECT查询中的索引与意向共享锁(IS锁)问题

三种索引场景下SELECT查询的锁行为详解

嘿,针对你用SQL Profiler监控到的锁行为,我来拆解一下细节——你观察到的Object级IS锁 + Page级IS锁其实是SQL Server读操作的标准前置流程,不管查询基于聚集索引、非聚集索引还是完全无索引,这两步锁获取都是必然发生的,原因如下:

  • Object级IS锁:这是表级的意向共享锁,作用是告诉其他会话“我打算读这个表的数据”,防止有人对表执行DDL(比如ALTER TABLE)这类会修改对象结构的操作,属于锁层级机制里的顶层意向声明。
  • Page级IS锁:这是数据页级的意向共享锁,意思是“我可能要读这个页里的行数据”,避免其他会话直接对整个数据页加排他锁(X锁),保证读操作的并行性。

接下来重点说三个场景的核心差异——也就是行级锁的施加情况:

1. 基于聚集索引列的查询

当查询条件命中聚集索引时,SQL Server会通过聚集索引直接定位到目标数据行(毕竟聚集索引本身就是数据行的存储结构),此时会在找到的目标行上施加S锁(共享锁)。如果是默认的读提交隔离级别,这个S锁会持有到查询结束;如果开启了快照隔离或读提交快照(RCSI),则会使用行版本,不会持有S锁。

2. 基于非聚集索引列的查询

这里要分两种子情况:

  • 如果你的非聚集索引是覆盖索引(包含了SELECT *需要的所有列),SQL Server直接从非聚集索引获取完整数据,只会在非聚集索引的键行上施加S锁,不需要回表访问聚集索引。
  • 如果是非覆盖索引,SQL Server需要通过非聚集索引里的书签(RID或聚集索引键)回表查找完整数据,此时会先在非聚集索引的匹配行上加S锁,再在对应的聚集索引行(也就是实际数据行)上加S锁。

3. 完全无索引的列(全表扫描)

这种场景下SQL Server会执行全表扫描,遍历每个数据页,此时会对扫描过程中访问到的每一行都施加S锁(默认读提交隔离级别下)。当然,如果开启了快照隔离或RCSI,同样会用行版本替代S锁,避免锁竞争。

最后补充一点:意向锁(IS)本身不会阻塞其他意向锁或共享锁,只会阻塞排他锁(X),所以三个场景下的Object和Page级IS锁行为完全一致,差异主要体现在行级锁的范围和数量上。

内容的提问来源于stack exchange,提问作者John L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:51:50