简介

在SQL Server中,每一个查询都会找到最短路径实现自己的目标。如果数据库只接受一个连接一次只执行一个查询。那么查询当然是要多快好省的完成工作。但对于 大多数数据库来说是需要同时处理多个查询的。这些查询并不会像绅士那样排队等待执行,而是会找最短的路径执行。因此,就像十字路口需要一个红绿灯那 样,SQL Server也需要一个红绿灯来告诉查询:什么时候走,什么时候不可以走。这个红绿灯就是锁。

图1.查询可不会像绅士们那样按照次序进行排队

为什么需要锁

在开始谈锁之前,首先要简单了解一下事务和事务的ACID属性。如果你了解了事务之间的影响方式,你就应该知道在数据库中,理论上所有的事务之间应 该是完全隔离的。但是实际上,要实现完全隔离的成本实在是太高(必须是序列化的隔离等级才能完全隔离,这个并发性有点….)。所以,SQL Server默认的Read Commited是一个比较不错的在隔离和并发之间取得平衡的选择。SQL Server通过锁,就像十字路口的红绿灯那样,告诉所有并发的连接,在同一时刻上,那些资源可以读取,那些资源可以修改。前面说到,查询本身可不是什么 绅士,所以需要被监管。当一个事务需要访问的资源加了其所不兼容的锁,SQL Server会阻塞当前的事务来达成所谓的隔离性。直到其所请求资源上的锁被释放,如图2所示。

图2.SQL Server通过阻塞来实现并发

如何查看锁

了解SQL Server在某一时间点上的加锁情况无疑是学习锁和诊断数据库死锁和性能的有效手段。我们最常用的查看数据库锁的手段不外乎两种:

使用sys.dm_tran_locks这个DMV

SQL Server提供了sys.dm_tran_locks这个DMV来查看当前数据库中的锁,前面的图2就是通过这个DMV来查看的.

这里值得注意的是sys.dm_tran_locks这个DMV看到的是在查询时间点的数据库锁的情况,并不包含任何历史锁的记录。可以理解为数据 库在查询时间点加锁情况的快照。sys.dm_tran_locks所包含的信息分为两类,以resource为开头的描述锁所在的资源的信息,另一类以 request开头的信息描述申请的锁本身的信息。如图3所示。更详细的说明可以查看MSDN(http://msdn.microsoft.com/en-us/library/ms190345.aspx)

图3.sys.dm_tran_locks

这个DMV包含的信息比较多,所以通常情况下,我们都会写一些语句来从这个DMV中提取我们所需要的信息。如图4所示。

图4.写语句来提取我们需要的锁信息

使用Profiler来捕捉锁信息

我们可以通过Profiler来捕捉锁和死锁的相关信息,如图5所示。

图5.在Profiler中捕捉锁信息

但默认如果不过滤的话,Profiler所捕捉的锁信息包含SQL Server内部的锁,这对于我们查看锁信息非常不方便,所以往往需要筛选列,如图6所示。

图6.筛选掉数据库锁的信息

所捕捉到的信息如图7所示。

图7.Profiler所捕捉到的信息

锁的粒度

锁是加在数据库对象上的。而数据库对象是有粒度的,比如同样是1这个单位,1行,1页,1个B树,1张表所含的数据完全不是一个粒度的。因此,所谓锁的粒度,是锁所在资源的粒度。所在资源的信息也就是前面图3中以Resource开头的信息。

对于查询本身来说,并不关心锁的问题。就像你开车并不关心哪个路口该有红绿灯一样。锁的粒度和锁的类型都是由SQL Server进行控制的(当然你也可以使用锁提示,但不推荐)。锁会给数据库带来阻塞,因此越大粒度的锁造成更多的阻塞,但由于大粒度的锁需要更少的锁, 因此会提升性能。而小粒度的锁由于锁定更少资源,会减少阻塞,因此提高了并发,但同时大量的锁也会造成性能的下降。因此锁的粒度对于性能和并发的关系如图 8所示。

图8.锁粒度对于性能和并发的影响

SQL Server决定所加锁的粒度取决于很多因素。比如键的分布,请求行的数量,行密度,查询条件等。但具体判断条件是微软没有公布的秘密。开发人员不用担心SQL Server是如何决定使用哪个锁的。因为SQL Server已经做了最好的选择。

在SQL Server中,锁的粒度如表1所示。

资源

说明

RID

用于锁定堆中的单个行的行标识符。

KEY

索引中用于保护可序列化事务中的键范围的行锁。

PAGE

数据库中的 8 KB 页,例如数据页或索引页。

EXTENT

一组连续的八页,例如数据页或索引页。

HoBT

堆或 B 树。 用于保护没有聚集索引的表中的 B 树(索引)或堆数据页的锁。

TABLE

包括所有数据和索引的整个表。

FILE

数据库文件。

APPLICATION

应用程序专用的资源。

METADATA

元数据锁。

ALLOCATION_UNIT

分配单元。

DATABASE

整个数据库。

表1.SQL Server中锁的粒度

锁的升级

前面说到锁的粒度和性能的关系。实际上,每个锁会占96字节的内存,如果有大量的小粒度锁,则会占据大量的内存。

下面我们来看一个例子,当我们选择几百行数据时(总共3W行),SQL Server会加对应行数的Key锁,如图9所示

图9.341行,则需要动用341个key锁

但当所取得的行的数目增大时,比如说6000(表中总共30000多条数据),此时如果用6000个键锁的话,则会占用大约 96*6000=600K左右的内存,所以为了平衡性能与并发之间的关系,SQL Server使用一个表锁来替代6000个key锁,这就是所谓的锁升级。如图10所示。

图10.使用一个表锁代替6000个键锁

虽然使用一个表锁代替了6000个键锁,但是会影响到并发,我们对不在上述查询中行做更新(id是50001,不在图10中查询的范围之内),发现会造成阻塞,如图11所示。

图11.锁升级提升性能以减少并发为代价

锁模式

当SQL Server请求一个锁时,会选择一个影响锁的模式。锁的模式决定了锁对其他任何锁的兼容级别。如果一个查询发现请求资源上的锁和自己申请的锁兼容,那么 查询就可以执行下去,但如果不兼容,查询会被阻塞。直到所请求的资源上的锁被释放。从大类来看,SQL Server中的锁可以分为如下几类:

共享锁(S锁):用于读取资源所加的锁。拥有共享锁的资源不能被修改。共享锁默认情况下是读取了资源马上被释放。比如我读100条数据,可以想像成读完了 第一条,马上释放第一条,然后再给第二条数据上锁,再释放第二条,再给第三条上锁。以此类推直到第100条。这也是为什么我在图9和图10中的查询需要将 隔离等级设置为可重复读,只有设置了可重复读以上级别的隔离等级或是使用提示时,S锁才能持续到事务结束。实际上,在同一个资源上可以加无数把S锁

排他锁(X锁): 和其它任何锁都不兼容,包括其它排他锁。排它锁用于数据修改,当资源上加了排他锁时,其他请求读取或修改这个资源的事务都会被阻塞,知道排他锁被释放为止。

更新锁(U锁) :U锁可以看作是S锁和X锁的结合,用于更新数据,更新数据时首先需要找到被更新的数据,此时可以理解为被查找的数据上了S锁。当找到需要修改的数据时, 需要对被修改的资源上X锁。SQL Server通过U锁来避免死锁问题。因为S锁和S锁是兼容的,通过U锁和S锁兼容,来使得更新查找时并不影响数据查找,而U锁和U锁之间并不兼容,从而 减少了死锁可能性。这个概念如图12所示。

图12.如果没有U锁,则S锁和X锁修改数据很容易造成死锁

意向锁(IS,IU,IX):意向锁与其说是锁,倒不如说更像一个指示器。在SQL Server中,资源是有层次的,一个表中可以包含N个页,而一个页中可以包含N个行。当我们在某一个行中加了锁时。可以理解成包含这个行的页,和表的一 部分已经被锁定。当另一个查询需要锁定页或是表时,再一行行去看这个页和表中所包含的数据是否被锁定就有点太痛苦了。因此SQL Server锁定一个粒度比较低的资源时,会在其父资源上加上意向锁,告诉其他查询这个资源的某一部分已经上锁。比如,当我们更新一个表中的某一行时,其 所在的页和表都会获得意向排他锁,如图13所示。

图13.当更新一行时,其所在的页和表都会获得意向锁

其它类型的构架锁,键范围锁和大容量更新锁就不详细讨论了,参看MSDN(http://msdn.microsoft.com/zh-cn/library/ms175519.aspx)

锁之间的兼容性微软提供了一张详细的表,如图14所示。

图14.锁的兼容性列表

理解死锁

当两个进程都持有一个或一组锁时,而另一个进程持有的锁和另一个进程视图获得的锁不兼容时。就会发生死锁。这个概念如图15所示。

图15.死锁的简单示意

下面我们根据图15的概念,来模拟一个死锁,如图16所示。

图16.模拟一个死锁

可以看到,出现死锁后,SQL Server并不会袖手旁观让这两个进程无限等待下去,而是选择一个更加容易Rollback的事务作为牺牲品,而另一个事务得以正常执行。

分类: SqlServer
本文转自快乐就好博客园博客,原文链接:http://www.cnblogs.com/happyday56/p/3926713.html,如需转载请自行联系原作者

sqlserver锁机制详解(sqlserver查看锁)相关推荐

  1. MySQL锁、事务隔离级别、MVCC机制详解、间隙锁、死锁等

    一. 简介 1. 锁定义 锁是计算机协调多个进程或线程并发访问某一资源的机制. 在数据库中,除了传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供需要用户共享的资源.如何保证数据并 ...

  2. mysql innodb 的锁机制_Mysql之Innodb锁机制详解

    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.关于事务我们之前有专题介绍,这里就着重介绍下它的锁机制. 总的来说,InnoDB按照不同的分类共有 ...

  3. MySQL锁机制详解-表锁与行锁

    文章目录 1. 数据库锁理论 2. 锁的分类 2.1 按数据操作的类型分类 2.2 按数据操作的颗粒度分类 3. 表锁的应用 3.1 表锁相关命令 3.2 给表加表共享读锁 3.3 给表加表独占写锁 ...

  4. Oracle索引、视图、序列、同义词、事务、锁机制详解

    索引 什么是索引? -- 索引就类似于书的目录,根据目录查询内容会快很多,提高数据查询效率 创建索引有俩种方式 1.Oracle会自动为主键和唯一键创建索引 2.手动创建约束. 那么表中什么样的字段应 ...

  5. 数据库之mysql事务原理分析与锁机制 详解

    1.事务 1.2.目的 事务将数据库从一种一致性状态转换为另一种一致性状态: 1.3.组成 事务可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成: 其中单条语句会默认自动添加事务控制 ...

  6. 乐观锁的颗粒度_MySql数据库锁机制详解

    概述 数据库锁定机制简单的来说,就是数据库为了保证数据的一致性与完整性,而使各种共享资源在被并发访问时变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁机制,所以MySQL也不能例外.M ...

  7. 第八节:数据库层次的锁机制详解和事务隔离级别

    一. 基本概念 1.共享锁:(holdlock) (1). select的时候会自动加上共享锁,该条语句执行完,共享锁立即释放,与事务是否提交没有关系. (2). 显式通过添加(holdlock)来显 ...

  8. java中的CAS操作以及锁机制详解

    关于CAS操作 CAS:Compare And Swap   --  乐观锁策略 CAS(无锁操作):使用CAS叫做比较交换来判断是否出现冲突,出现冲突就重试当前操作直到不冲突为止. 悲观锁(JDK1 ...

  9. mysql表锁机制详解

    为了给高并发情况下的mysql进行更好的优化,有必要了解一下mysql查询更新时的锁表机制. 一.概述 MySQL有三种锁的级别:页级.表级.行级. MyISAM和MEMORY存储引擎采用的是表级锁( ...

最新文章

  1. python打印指定行数的分割线_在Python中的分隔线上打印列表元素
  2. 怎么把项目推到gitlab上_将本地项目添加到 GitLab 上管理
  3. 链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)
  4. Ktor 1.0发布:JetBrains推出的Kotlin Web框架
  5. 1.8 Remove
  6. 匹兹堡计算机科学公司,2017美国匹兹堡大学计算机科学CS专业硕士录取
  7. Entity Framewrok 7beta7中不同版本sql server自动生成分页sql语句的问题
  8. Linux进程的创建和父子进程同步,操作系统实验报告_Linux进程创建与通信.doc
  9. wxWidgets:国际化
  10. 阿里云边缘计算与云边端协同网络的融合与挑战
  11. 【渝粤题库】广东开放大学 微信平台开发与应用 形成性考核 (2)
  12. 你的“不着急”,最后都是“来不及”
  13. Git笔记(7) 撤消操作
  14. linux 两个mysql_Linux 安装两个MySQL
  15. 3dmax疯狂模渲大师软件有什么使用指南?疯狂模渲大师的目录,教你怎么使用疯狂模渲大师,疯狂模渲大师其实并不难!
  16. R语言学习记录:array()函数
  17. cogs 944. [東方S3] 藤原妹红
  18. 【AE扩展插件问题解决记录】
  19. Linux配置网络服务
  20. 我在2022北大夏令营被吊起来打

热门文章

  1. Win7:“找不到该项目”错误解决大法
  2. java中关于时间的计算
  3. ckeditor4.4.6添加代码高亮
  4. iOS 使用Quartz 2D画虚线 .
  5. linux useradd
  6. html景图片怎么设置百分比,8个风光照片拍摄技巧
  7. 您的主机不满足在启用hyper-v或device_是时候换掉你的旧书桌了!乐歌E5M电动升降桌,坐立换姿不疲劳...
  8. [python教程入门学习]Python标准库映射类型与可散列数据类型的关系
  9. 微博鸿蒙测试版,不久前华为宣布,将会在6月2日举... - @姬永锋 的微博精选 - 微博国际站...
  10. python会搞坏电脑吗_搞python,把原本php环境所需的libjpeg搞坏了