以NA_TrafficMemberOrderRelation表为例,表的索引如下:

index_id name cols
1 PK__NA_Traff__FB6751642649A903 TrafficMemberOrderRelationId
26 IX_NA_TrafficMemberOrderRelation_usermobile UserMobile

下面的查询语句,正常情况下会先使用IX_NA_TrafficMemberOrderRelation_usermobile索引进行查找,再返回聚集索引查找剩下的列

select * from NA_TrafficMemberOrderRelation where usermobile='13719805324' and ecprdcode='50615801625'

执行计划如下:

因为在read committed隔离级别上,查询语句申请的锁,会马上释放,所以把隔离级别设置为可重复读(repeatable read),再开启事务后运行查询语句,但不提交事务

set transaction isolation level repeatable read;
begin tran
select * from NA_TrafficMemberOrderRelation with(index=PK__NA_Traff__FB6751642649A903) where usermobile='13719805324' and ecprdcode='50615801625'

然后运行 exec sp_lock来查看申请的锁:

spid dbid ObjId IndId Type Resource Mode Status
58 17 610361489 1 PAG 1:8005696                        IS GRANT
58 17 610361489 26 KEY (525b6b18cbd1)                   S GRANT
58 17 610361489 26 PAG 4:53295                          IS GRANT
58 17 610361489 1 KEY (b1b78d542d80)                   S GRANT
58 17 610361489 26 KEY (6e79de43f52b)                   S GRANT
58 17 610361489 0 TAB   IS GRANT
58 17 610361489 1 KEY (8d95380f137a)                   S GRANT

图中看出,查询语句申请的锁如下:

1、对象上的意向共享锁(IS)

58 17 610361489 0 TAB   IS GRANT

2、UserMobile索引页面上的意向共享锁(IS)

58 17 610361489 26 PAG 4:53295                          IS GRANT

3、符合条件的键值上的共享锁(S),因为手机号码13719805324有两条记录,所以申请了两个共享锁

58 17 610361489 26 KEY (525b6b18cbd1)                   S GRANT
58 17 610361489 26 KEY (6e79de43f52b)                   S GRANT

4、通过UserMobile索引找到的第一行,都会通过主键去聚集索引查找这一行以获取其他列的数据,所以会在聚集索引上申请跟2、3步一要样的锁(页上的IS锁和键上的S锁):

58 17 610361489 1 PAG 1:8005696                        IS GRANT
58 17 610361489 1 KEY (b1b78d542d80)                   S GRANT
58 17 610361489 1 KEY (8d95380f137a)                   S GRANT

所以,通过索引查找来获取数据的查询,大致总结如下:

1、对使用到的PAGE加IS锁

2、对使用到的每一个索引键或聚集索引键加共享锁

下面看下在没有索引的情况,通过表扫描,需要申请哪些锁(先通过alter table NA_TrafficMemberOrderRelation set(lock_escalation=disable)禁止表上的索升级,防止直接升级为表上的S锁):

<span style="font-family: Arial, Helvetica, sans-serif;">select * from NA_TrafficMemberOrderRelation where CreateTime='2015-10-25 05:29:47.000'</span>

CreateTime字段没有索引,所以上面的查询会使用聚集索引扫描,执行exec sp_lock查看申请的锁:

spid dbid ObjId IndId Type Resource Mode Status
58 17 610361489 0 TAB   IS GRANT
58 17 610361489 1 PAG 1:8086440                        S GRANT
58 17 610361489 1 PAG 4:459840                         S GRANT
58 17 610361489 1 PAG 4:167476                         S GRANT
58 17 610361489 1 PAG 1:8317404                        S GRANT
58 17 610361489 1 PAG 1:8432309                        S GRANT
58 17 610361489 1 PAG 1:8154231                        S GRANT
58 17 610361489 1 PAG 1:8267887                        S GRANT
58 17 610361489 1 PAG 1:8052942                        S GRANT
58 17 610361489 1 PAG 1:8086441                        S GRANT
58 17 610361489 1 PAG 4:459841                         S GRANT
58 17 610361489 1 PAG 4:167477                         S GRANT
58 17 610361489 1 PAG 1:8317405                        S GRANT
58 17 610361489 1 PAG 1:8432308                        S GRANT
58 17 610361489 1 PAG 1:8154230                        S GRANT
58 17 610361489 1 PAG 1:8267886                        S GRANT
........              

此处省略数万行

因为使用的是聚集索引扫描,表中的每一行都会读取到,如果还是按上面的规则的话,对每一行都加锁,那会产生大量的锁,所以SQL SERVER默认对锁进行了升级,直接在PAGE上加了S锁,如果页中的数据被修改(插入或修改页中的一行数据),会在页上加IX锁,而S和IX是不兼容的,所以在PAGE上的S锁就能达到隔离级别的要求

所以,通过索引扫描来获取数据的查询,大致总结如下:

1、对扫描到的每一个PAGE加上S锁。

S锁和IS锁的释放时间是:

1、当事务隔离级别为read committed时,当读取完这一行或页时(此时查询还没有结束),直接释放。

2、当事务隔离级别为repeatable read时,如果读取的这一行不满足查询条件,会直接释放掉,如果满足条件,会等到事务结束再释放,而通过扫描对页加的S锁,会等到事务结束才释放

锁的申请和释放可以通过Sql server profile中跟踪:Lock:Acquired,Lock:Released来获得:

sql server中select语句需要申请的锁相关推荐

  1. SQL Server 中 SELECT INTO 和 INSERT INTO SELECT语句的区别

    SQL Server 中 SELECT INTO 和 INSERT INTO SELECT语句的区别 我们在写存储过程的时候经常会遇到需要将查询到的数据存到一张表里面的情况,如将一个table1的数据 ...

  2. SQL Server中SELECT会真的阻塞SELECT吗?

    在SQL Server中,我们知道一个SELECT语句执行过程中只会申请一些意向共享锁(IS) 与共享锁(S), 例如我使用SQL Profile跟踪会话86执行SELECT * FROM dbo.T ...

  3. SQL Server中T-SQL语句查询使用的函数

    SQL Server中T-SQL语句查询使用的函数 一,字符串函数 字符串函数用于对字符串数据进行处理,并返回一个字符串或数字. 函数名 描述 举例 CHARINDEX 用来寻找一个指定的字符串在另一 ...

  4. SQL Server 中as语句后加英文,标点符号等内容

    SQL中as语句后加英文,标点符号等内容 SELECT  isnull(EndTime,getdate()) as '完成时间(H)' FROM [PCMIS].[dbo].[ProcessOfInt ...

  5. Sql Server中Select @Value和Select Value的区别

    Select @Value至多返回一个值, 而Select Value可以返回一组值 转载于:https://www.cnblogs.com/quanxi888/archive/2007/11/29/ ...

  6. sql server中的go

    1. 作用: 向 SQL Server 实用工具发出一批 Transact-SQL 语句结束的信号. 2. 语法: 一批 Transact-SQL 语句 GO 如 Select 1 Select 2 ...

  7. sql server一个查询语句引发的死锁

    程序错误日志大量的报死锁错误,去数据库错误日志查看确实有很多死锁(应在数据库实例启动时执行dbcc traceon(1222,-1)开启死锁跟踪): 04/29/2016 14:07:51,spid3 ...

  8. SQL Server中SQL Union vs Union All

    This article explains to the SQL Union and vs Union All operators in SQL Server. We will also explor ...

  9. oracle 图片 显示不出,Sql Server 中image类型迁移到Oracle 中Blob类型出现图片显示不出来,why????请博客们帮忙 | 学步园...

    我现在在一项目中碰到这么一个问题 Sql Server 中image类型迁移到Oracle Blob类型出现图片显示不出来,我在Sql Server 中看了一条image数据 如下: 1.Sql Se ...

最新文章

  1. 手把手用YOLO做目标检测
  2. 【深度学习】图像数据集处理常用方法合集(部分基于pytorch)
  3. 《Windows 8 权威指南》——1.5 版本对比
  4. 对象映射工具AutoMapper介绍
  5. Python使用pip安装/卸载包
  6. [转]mysql下如何执行sql脚本
  7. Python—基础知识之总结(6)
  8. 上海华谊(集团)公司-统一业务协同平台
  9. python使用pika库调用rabbitmq的交换机模式
  10. 新的博客,新的开始。
  11. 食物链 (利用并查集的两种解决方法)
  12. html中qq号码怎么写,qq号码免费申请6位号的方法
  13. 微信开发者工具-调试器
  14. 英语不好学java好学吗_英语不好能学好java,做程序员吗?
  15. Arduino uno esp01s 硬串口通信
  16. PS需要用到数位板吗,PS中怎么设置和运用手绘板
  17. linux服务器性能阈值,linux – 如何根据可用内核的数量选择最大负载阈值?
  18. 傻傻分不清楚的研究设计类型
  19. JaveMail实现发送QQ邮件
  20. scGEMA:基于单细胞多组学增强子的基因调控网络推断

热门文章

  1. windows卸载qt_如何在Qt中显示一个窗口并在关闭后立即将其删除?
  2. php excel列增加_PHP 高性能 Excel 扩展 1.2.7 发布
  3. html流光按钮,【CSS】css实现流光效果-按钮流光显示效果-自发光
  4. c语言学习-从键盘上输入100个字符,统计其中字母、每个数字和其它字符的个数及其百分比
  5. 直方图均衡化计算过程步骤
  6. OpenShift 4 之 GitOps(2)用ArgoCD部署应用
  7. 具有搜索和自定义分页的React Bootstrap表
  8. SQLite 3.30.0 发布,世界上使用量最大的数据库引擎
  9. JHelpers——一个善良忠实的仆人
  10. sqlserver 更新 datetime 数据_SqlServer 关于 datetime 的更新引发的思考