在SQL Server中,我们知道一个SELECT语句执行过程中只会申请一些意向共享锁(IS) 与共享锁(S), 例如我使用SQL Profile跟踪会话86执行SELECT * FROM dbo.TEST WHERE OBJECT_ID =1 这个查询语句,其申请、释放的锁资源的过程如下所示:

而且从最常见的锁模式的兼容性表,我们可以看到IS锁与S锁都是兼容的,也就是说SELECT查询是不会阻塞SELECT查询的。

现有的授权模式

请求的模式

IS

S

U

IX

SIX

X

意向共享 (IS)

共享 (S)

更新 (U)

意向排他 (IX)

意向排他共享 (SIX)

排他 (X)

但是在某些特殊场景。你会看到SELECT语句居然“阻塞”SELECT操作,那么SQL Server中SELECT会真的阻塞SELECT操作吗?我们先构造测试的案例场景,那么先准备测试数据吧

CREATE TABLE TEST (OBJECT_ID  INT, NAME VARCHAR(8));
 
CREATE INDEX PK_TEST ON TEST(OBJECT_ID) 
 
 
DECLARE @Index INT =0;
 
WHILE @Index < 20
BEGIN
    INSERT INTO TEST
    SELECT @Index, 'kerry';
    
    SET @Index = @Index +1;
END

在会话窗口A中,执行下面SQL语句,模拟一个UPDATE语句正在执行

 
BEGIN TRANSACTION
 
    UPDATE dbo.TEST SET NAME='Kerry' WHERE OBJECT_ID=1;
    --ROLLBACK;

会话窗口B中,执行下面的SQL语句

SELECT * FROM dbo.TEST WHERE OBJECT_ID=1

会话窗口C中,执行下面的SQL语句

SELECT * FROM dbo.TEST WHERE OBJECT_ID=1

我实验的场景下,会话窗口A的会话ID为85,会话窗口B的会话ID为90,会话窗口C的会话ID为87,如下所示

如下所示,你会看到SELECT语句“阻塞”了SELECT语句,即会话90“阻塞”了会话87, 它们的等待事件都为LCK_M_S,也就是说它们都在等待获取共享锁,也许你会置疑这个SQL是否有问题,那么我们使用SP_WHO来查看,你会发现也是如此,如下所示:

如下所示,我们会发现会话ID为90 、87的会话都在等待类型为RID,Resource为1:24171:1的共享锁

其实应该说,会话87、90都在等待RID对象的共享锁,我们知道共享锁与意向共享锁都是兼容的,所以SELECT是不会阻塞SELECT的,那么又怎么解释这个现象呢?在宋大神的指点下,粗略的翻了Database System Implementaion这本书(很多原理性知识,看起来相当吃力)。里面介绍了在锁表(lock table)以及Element Info、Handling Lock Requests、Handling Unlocks等概念,有一个有意思的图所示,

在锁表(lock table)里,elements info里的锁的申请是在一个类似队列的结构。先进先出机制,所以当会话90先进入队列,它在等待共享锁(S), 会话87也进入队列等待共享锁(S),而且它在会话90的后面(即会话90这个elements info后面的Next指针指向会话87会话的事务),由于两个会话都被阻塞,这两个会话的Wait字段都是Yes,由于内部某些机制,会话87显示阻塞它的会话为90(这个是我个人臆测,实际具体原因有待考究),实质阻塞的源头还是会话85. 当会话85释放排它锁(X)后,会话队列根据下面几个原则来处理解锁(Handling Unlocks):

1: First-come-first-served: Grant the lock request that has been waiting the longest. This strategy guarantees no starvation, the situation where a transaction can wait forever for a lock

先来先服务(队列的原则):授予锁等待时间最长的锁请求,这种策略保证不会饿死(翻译感觉不贴切),即一个事务不会永远等待锁的情况。

2. Priority to shared locks: First grant all the shared locks waiting. Then,grant one update lock, if there are any waiting. Only grant an exclusive lock if no others are waiting. This strategy can allow starvation, if a transaction is waiting for a U or X lock.

共享锁优先,首先授予所有等待共享锁(S),然后授予其中一个更新锁(U),如果有其它类型等待,只有在没有其它锁等待时,才授予排它锁、这一策略允许等待更新锁或排它锁的事务饿死(结束)

3. Priority to upgrading: If there is a transaction with a U lock waiting to upgrade it to an X lock, grant that first. Otherwise, follow one of the other strategies mentioned.

锁升级优先,如果有一个持有共享锁(U)等待升级Wie排他锁(X),那么先授予它排它锁,否则采用前面已经提到的策略中的一个。

按照这些原则,当会话85释放了排它锁(X)后,调度器(Scheduler)应该会根据先后顺序依次授予会话90、87共享锁(S),两者的阻塞会几乎同时消失。 这个可以也可以通过实验进行一个大概的推断, 在上面实验中,你可以手工取消90会话的查询操作,然后再查看阻塞情况,就会发现会话87被85阻塞了。这个阻塞的源头就变成了85,而不是90了。

PS:上面是个人结合一些知识和理解,做的一些肤浅的判断与分析,如果不对的地方,敬请指正!

参考资料:

Database System Implementaion

转载于:https://www.cnblogs.com/kerrycode/p/6250606.html

SQL Server中SELECT会真的阻塞SELECT吗?相关推荐

  1. 深入浅出SQL Server中的死锁

    简介 死锁的本质是一种僵持状态,是多个主体对于资源的争用而导致的.理解死锁首先需要对死锁所涉及的相关观念有一个理解. 一些基础知识 要理解SQL Server中的死锁,更好的方式是通过类比从更大的面理 ...

  2. 如何在SQL Server中实现错误处理

    错误处理概述 (Error handling overview) Error handling in SQL Server gives us control over the Transact-SQL ...

  3. 如何从 SQL Server 中的 SELECT 更新?

    问题描述: 在 SQL Server 中,可以使用 INSERT- SELECT 语句将行插入到表中: INSERT INTO Table (col1, col2, col3) SELECT col1 ...

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

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

  5. SQL server中的SELECT查询语句执行顺序

    各位大牛们好第一次写博客有点小激动!以后我会把自己的心得分享给大家,求各种评论 SQL server 中SELSECT查询语句的执行顺序如下: (8) SELECT   (9) DISTINCT (1 ...

  6. 如何从SQL Server中的SELECT语句更新

    In this article, we will learn different methods that are used to update the data in a table with th ...

  7. SQL Server中SET赋值和SELECT赋值的区别

    2019独角兽企业重金招聘Python工程师标准>>> 一.SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值 SELECT @VAR1='Y',@VAR ...

  8. 如何从SQL Server中的SELECT更新?

    在SQL Server中 ,可以使用SELECT语句insert表中: INSERT INTO Table (col1, col2, col3) SELECT col1, col2, col3 FRO ...

  9. Microsoft SQL Server中的事务(转载)

    1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一组语句要么全部成功,对数据库中的某些数据成功修改; 要么全部不成功,数据 ...

最新文章

  1. 余承东没有吹牛:华为首次超越三星,成为全球最大手机供应商
  2. VS插件开发——格式化变量定义语句块
  3. eslint 保存自动格式化_ESLint一款可组装的JavaScript和JSX检查工具
  4. 演练 类的定义 java 1615134691
  5. 如何建立自己的知识体系?(摘)
  6. chart控件做实时曲线显示_组态王实时趋势曲线控件介绍,让你对此不再陌生
  7. SpringBoot之Bean之条件注入@Condition
  8. LGP2046[NOI2010]海拔正确性证明
  9. 【转】余弦相似度及基于python的三种代码实现、与欧氏距离的区别
  10. appium+python环境搭建_想学习自动化测试,已经学习了appium+python环境搭建和python的简单内容,下面该怎么做?...
  11. 全球第二大成人网站,黄了!
  12. IOS平台下的音视频即时通讯
  13. java求1到20的阶乘
  14. SCSI代码分析(5)SCSI驱动编程模式
  15. 工业面阵相机与源型PLC和漏型PLC外部触发接线
  16. WPF基础到企业应用系列8——依赖属性之“风云再起”
  17. MATLAB 像素画绘制APP
  18. NDIM 磁力下载器 MAC多版本设置UA
  19. 微软 Visual Studio 2017 RC 中文版下载 - 免费社区版/专业版/企业版
  20. 吴中太湖新城在京路演,北京企业260亿投资助力苏州打造“未来之城

热门文章

  1. mysql索引空间太大_MySQL优化索引
  2. es日期format_elasticsearch存储日期格式字段
  3. 《OpenCV3编程入门》学习笔记7 图像变换(五 )直方图均衡化
  4. usaco Calf Flac(O(n)时间求回文串长度)
  5. c++ memset 语言_自学C语言不知道从哪儿下手?学习框架都帮你列好了!
  6. 描述文件_【iOS】描述文件删除不了?教你一键移除所有恶意描述文件
  7. python规则网格插值_Python中规则网格上的插值
  8. 电大计算机应用,(2016年电大)电大全国计算机应用考试网考.doc
  9. mysql优化说明_MySQL性能优化各个参数解释说明
  10. puml绘制思维导图_如何用ProcessOn画出漂亮的思维导图