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

SQL Server中SELECT会真的阻塞SELECT吗?的更多相关文章

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

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

  2. SQL Server中的死锁

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

  3. 探讨SQL Server并发处理队列数据不阻塞解决方案

    前言 之前对于并发这一块确实接触的比较少,自从遇到现在的老大,每写完一块老大都会过目一下然后给出意见,期间确实收获不少,接下来有几篇会来讲解SQL Server中关于并发这一块的内容,有的是总结,有的 ...

  4. 深入浅出SQL Server中的死锁(实战篇)

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

  5. 深入浅出 关于SQL Server中的死锁问题

    深入浅出 关于SQL Server中的死锁问题 博客2013-02-12 13:44   分享到:我要吐槽 死锁的本质是一种僵持状态,是多个主体对于资源的争用而导致的.理解死锁首先需要对死锁所涉及的相 ...

  6. 【转载】深入浅出SQL Server中的死锁

    essay from:http://www.cnblogs.com/CareySon/archive/2012/09/19/2693555.html 简介 死锁的本质是一种僵持状态,是多个主体对于资源 ...

  7. SQL Server中 SET 和 SELECT 赋值有什么区别?

    SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT.对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们并没有注意,其实这两种 ...

  8. SQL Server中事务、锁定和阻塞

    事务是什么 在SQL Server中事务是构成一个工作逻辑单元的一系列任务,也就说多个任务放在一起执行,这些任务要么全部执行成功,要么全部执行失败. 通过事务我们可以保证数据的完整性,例如:用户A给用 ...

  9. 如何解决 SQL Server 中的锁升级所致的阻塞问题

    概要 锁升级为表锁插入转换很多细粒度的锁 (如行或页锁) 的过程.Microsoft SQL Server 动态确定何时执行锁升级.作出决定之前,SQL Server 将特定的扫描,整个事务,并且用于 ...

随机推荐

  1. 阿里云直播 C# SDK 如何使用

    阿里云直播SDK的坑 1.直播云没有单独的SDK,直播部分被封装在CDN的相关SDK当中. 2.针对SDK,没有相关Demo. 3.针对SDK,没有相关的文档说明. 4.针对SDK的说明,官网上的说明 ...

  2. Android笔记——Button点击事件几种写法

    Button点击事件:大概可以分为以下几种: 匿名内部类 定义内部类,实现OnClickListener接口 定义的构造方法 用Activity实现OnClickListener接口 指定Button ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(76)-微信公众平台开发-网页授权

    前言 网页授权是:应用或者网站请求你用你的微信帐号登录,同意之后第三方应用可以获取你的个人信息 网上说了一大堆参数,实际很难理解和猜透,我们以实际的代码来演示比较通俗易懂 配置 实现之前我们必须配置用 ...

  4. WebForm获取GET或者POST参数到实体的转换,ADO.NET数据集自动转换实体

    最近在修改维护以前的webform项目(维护别人开发的.....)整个aspx没有用到任何的控件,这个我也比较喜欢不用控件所以在提交信息的时候需要自己手动的去Request.QueryString[] ...

  5. Xamarin+Prism开发详解二:Xaml文件如何简单绑定Resources资源文件内容

    我们知道在UWP里面有Resources文件xxx.resx,在Android里面有String.Xml文件等.那跨平台如何统一这些类别不一的资源文件以及Xaml设计文件如何绑定这些资源?应用支持多国 ...

  6. spring boot 实战:我们的第一款开源软件

    在信息爆炸时代,如何避免持续性信息过剩,使自己变得专注而不是被纷繁的信息所累?每天会看到各种各样的新闻,各种新潮的技术层出不穷,如何筛选出自己所关心的? 各位看官会想,我们是来看开源软件的,你给我扯什 ...

  7. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  8. React Native Android gradle下载慢问题解决

    很多人会遇到 初次运行 react-native run android的时候 gradle下载极慢,甚至会失败的问题 如下图 实际上这个问题好解决的 首先 把对应版本的gradle下载到本地任意一个 ...

  9. web前端开发分享-目录

    1. web前端开发分享-css,js入门篇 2. web前端开发分享-css,js进阶篇 3. web前端开发分享-css,js提高篇 4. web前端开发分享-css,js工具篇 5. web前端 ...

  10. 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

    通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器.权限问题等).这篇文章向你介绍一个新的替代 ...