锁的概念

  • 锁是什么

锁是数据库中在并发操作情形下保护资源的机制。通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性。

  • 锁的概念可分为几部分
  1. 锁资源(锁住什么)
  2. 锁模式(怎么锁法)
  3. 锁持续时间
  4. 兼容性
  5. 锁的行为(锁转换,锁升级)

1.锁的资源

2.锁的模式

  1. 共享锁:Shared Lock,S Lock. 通常情况下,读取数据时会对数据加上S Lock。
  2. 排它锁: Exclusive Lock,X Lock。对数据进行更改(insert update,delete)时加X Lock
  3. 更新锁:Update Lock,U Lock(或叫UPD Lock)。通常对数据进行Update操作会加U锁。查找数据时会加U锁,找到后对数据进行更改时在转换为X锁。U锁是为了防止在并发对数据进行更新时出现死锁,因为如果先加S锁再转换为X锁,由于S锁和S锁兼容,但X锁和S锁不兼容,所以有可能出现死锁。
  4. 意向锁:Intent Lock(例如:IX,IU,IS),是指对被锁定的资源的上层资源加锁。意向锁是为了提高锁的效率。例如对行加X锁,会对表加IX锁(意向排他锁),如果其他线程或事物想对该表加X锁,就不用逐行检查是否有其他所,只需检查是否有IX锁(或其他意向锁)

3.锁在事务中的持续时间

不同的事务隔离级别下,锁有不同的持续时间。(单一个SQL语句也是一个事物,称为“自动提交事务”,用begin tran/commit声明的是显式事务)

  1. Read uncommitted: select不会加锁(no lock),但更新会加U锁并持续到事务介绍
  2. Read committed:select加S锁,读完释放。U锁和X锁持续到事务结束
  3. Repeatable Read : select加S锁,但读完不释放,和U锁,X锁一样持续到事务结束。
  4. Serializable :select会加范围锁,读完不释放,和U锁,X锁一样持续到事务结束。

4.锁兼容性

锁兼容性是指不同模式的锁能不能共存。锁兼容性对照图:

图片出自Microsoft

5.锁转换和锁升级

  1. 锁转换:锁会由一种模式转换为另一种模式。例如delete一条数据,先在数据查找时对数据加上U锁,再在准备删除数据前转换成X锁。
  2. 锁升级:为了提高效率,锁会从一种粒度升级到另一种粒度。一个锁大概需要96B空间,如果锁太多会占用太多资源。如果一个操作需要对很多资源加锁,SQL会自动对这个资源的上级加相同的锁,即锁升级

死锁的概念

死锁就是两个或多个会话(SPID)相互请求对方持有的锁资源,导致循环等待的情况。

死锁的检查和分析

在Profiler中使用Deadlock Graph分析死锁

捕获到死锁图

也可以使用ErrorLog来记录死锁

  • 打开trace flag

    • dbcc traceon(1204,-1)
    • dbcc traceon(1222,-1)
  • 清空errorLog(不一定需要清空,只为减少log数据)
    • dbcc errorlog或者  exec sp_cycle_errorlog
  • 打开errorlog文件或者执行 xp_readerrorlog
  • 分析死锁图,如下图:

根据errorlog内容画出死锁图,其中:

  • NODE:代表每个死锁节点
  • Key/RID/Object:被锁定的资源
  • Grant List:拥有该资源的锁的SPID
  • Reuested List:请求该资源的SPID
  • SPID:会话ID
  • MODE: 该资源被锁定的模式。参考:锁模式
  • Input Buf:发生死锁时的SQL语句

这样就可以画出死锁图:

这样便可以分析出死锁的情况,当然如果对errorlog已经比较熟悉,就可以不用画出死锁图了。

死锁和索引

  • 如果被锁的资源是一个Object,只有object_id,可以通过Object_name()函数获取object的名字。
  • 如果是RID,可以通过 dbcc page指令去知道哪行数据被锁。
  • 如果是key,需要通过 %%lockres%%列,或者“dbcc ind指”令和“dbcc page”指令去知道哪个索引键被锁。
  • 在死锁节点的Key中,显示被锁的key为:

KEY: 49:72057594189512704 (11036c0fa4d3),格式为:
 KEY: db_id:hobt_id(index key hash value)
SQL SERVER通过对一个由索引键值生成的hash value进行锁定,来达到对索引锁定的目的。其中(11036c0fa4d3)就是某个key的hash value。
如何由hash value得知是哪行数据被锁定?请按以下步骤:

如果是聚集索引,可以使用%%lockres%%隐藏列获取lock hash value:

如果是非聚集索引,%%lockres%%只显示 RID。如果需要确定数据行对应的索引页中的索引键,需要使用dbcc ind和dbcc page指令进行分析:

  • 要查看索引的lock hash value,需要查看索引所在的数据页的内容。
  • 要知道索引在什么数据页中,需要使用dbcc ind指令:dbcc ind(‘moe_dev’,592773219,3)  “592773219”代表表的object_id,3代表索引的index_id 。可使用dbcc ind指令:

知道了索引所在数据页的Page_ID,可以使用dbcc page指令查看数据页内容(最后一个参数必须为“3”):

知道了索引所在数据页的Page_ID,可以使用dbcc page指令查看数据页内容(最后一个参数必须为“3”):

知道了key hash value和Heap RID,可以通过下面的SQL语句转换成RID

DECLARE @HeapRid BINARY(8)
SET @HeapRid = 0xDB27000001001700
SELECT
CONVERT (VARCHAR(5),
CONVERT(INT, SUBSTRING(@HeapRid, 6, 1)
+ SUBSTRING(@HeapRid, 5, 1)))
+ ':'
+ CONVERT(VARCHAR(10),
CONVERT(INT, SUBSTRING(@HeapRid, 4, 1)
+ SUBSTRING(@HeapRid, 3, 1)
+ SUBSTRING(@HeapRid, 2, 1)
+ SUBSTRING(@HeapRid, 1, 1)))
+ ':'
+ CONVERT(VARCHAR(5),
CONVERT(INT, SUBSTRING(@HeapRid, 8, 1)
+ SUBSTRING(@HeapRid, 7, 1)))
AS 'Fileid:Pageid:slot'

得到的RID为:

通过dbcc page指令就可以查看是哪行被锁定了。

参考资料

有关死锁的资料和比较好的文章,请看另一篇博文《有关DeadLock的文章列表

SQL Server 死锁概念和分析的更多相关文章

  1. 通过SQL Server Profiler来监视分析死锁

    在两个或多个SQL Server进程中,每一个进程锁定了其他进程试图锁定的资源,就会出现死锁,例如,进程process1对table1持有1个排它锁(X),同时process1对table2请求1个排 ...

  2. SQL SERVER 查询性能优化——分析事务与锁(五)

    SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...

  3. Update导致SQL Server死锁的典型方法(转载)

    此文为转载文章,描述的很好,没有验证过. 最近遇到了一个看上去很奇怪,分析起来很有意思的死锁问题.这个死锁看上去难以理解.而分析过程中,又使用了很多分析SQL Server死锁的典型方法.记录下来整个 ...

  4. SQL Server死锁

    SQL Server死锁 多个事务之间互相等待对方的资源,导致这些事务永久等待 注意是永久等待,而非长事务 死锁的4个条件 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程 ...

  5. SQL Server死锁的解除方法

    如果想要查出SQL Server死锁的原因,下面就教您SQL Server死锁监控的语句写法,如果您对此方面感兴趣的话,不妨一看. 下面的SQL语句运行之后,便可以查找出SQLServer死锁和阻塞的 ...

  6. SQL Server死锁的分析、处理与预防

    1.基本原理 所谓“死锁”,在操作系统的定义是:在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 定义比较抽象,下图可以帮助你比较直观的 ...

  7. SQL Server死锁诊断--同一行数据在不同索引操作下引起的死锁

    死锁概述 对于数据库中出现的死锁,通俗地解释就是:不同Session(会话)持有一部分资源,并且同时相互排他性地申请对方持有的资源,然后双方都得不到自己想要的资源,从而造成的一种僵持的现象.当然,在任 ...

  8. SQL Server 死锁的告警监控

    今天这篇文章总结一下如何监控SQL Server的死锁,其实以前写过MS SQL 监控错误日志的告警信息,这篇文章着重介绍如何监控数据库的死锁,当然这篇文章不分析死锁产生的原因.以及如何解决死锁.死锁 ...

  9. SQL Server死锁中的会话隔离级别为序列化(Serializable)实验测试

    最近在分析SQL Server的死锁时,发现一个比较有意思的现象,发现死锁当中一个会话的隔离级别为序列化(Serializable),这个是让人比较奇怪的地方,我们知道SQL Server数据库的默认 ...

随机推荐

  1. NodeJS链接MongDB

    创建一个mongdb.js var mongodb = require('mongodb') // 创建数据库服务的链接 var server = new mongodb.Server( 'local ...

  2. 自定义分页Gridview中Excel导出

    先上图,如图所示导出所有查询出的数据 用的是AspNetPager分页控件,这个导出方法,不受分页和gridview列中数据的约束,可以导出您想导出的数据 首先前台页面代码,lblink即为导出exc ...

  3. json基础入门

    json是什么? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成.它基于ECMAScript的一个子集. JSO ...

  4. jquery与js的区别与基础操作

    一.什么是 jQuery jQuery是一个JavaScript库,它通过封装原生的JavaScript函数得到一整套定义好的方法.它的作者是John Resig,于2006年创建的一个开源项目,随着 ...

  5. C/C++学习路线图

    文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 这里整理的C/C++学习路线图包含初中高三个部分,你可以通过百度云盘下载观看对应的视频 链接: http://pan.baidu.c ...

  6. java深拷贝和浅拷贝

    1.概念 java里的clone分为: A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍. Java中对 ...

  7. Winform自定义控件在界面上拖动、滚动鼠标。。会闪烁的解决方法

    环境说明:   项目中有一个基类窗体BaseForm,有一个自定义控件TextBoxBase,两个控件都做了一些独特常规的封装和重写,在TextBoxBase中有一点重绘的下划线,发现在窗体运行之后, ...

  8. 千呼万呼使出来Gogland (jetBrains发布的golang IDE)

    由于之前一直在用PyCharm在开发, 已经习惯了这个IDE. 转golang开发后一直没找到合适的debug功能的IDE,忽然听说jetBrains发布测试版golang IDE: Gogland带 ...

  9. 【iOS】7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  10. Linux MTD子系统 _从模型分析到Flash驱动模板

    MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...