原文:通过DBCC Page查看在SQL Server中哪行数据被锁住了?


如何查看被锁的是哪行数据?通过dbcc page可以。

要想明白这个问题:

首先,需要模拟阻塞问题,这里直接模拟了阻塞问题的一个比较极端的情况,就是死锁。

然后,需要知道如何监控死锁,否则,就算产生了死锁,你也不一定知道。这里在模拟死锁之前,通过SQL Profiler先来监控死锁问题。

接下来,我们可以通过sys.dm_tran_locks来获取更详细的阻塞信息。

最后,通过dbcc page来解析哪一行数据被锁住了。

下面就按照上面的步骤,一步一步来实现:

1、先监控死锁。

先选择SQL Profiler:

然后,新建跟踪,单击连接:

接下来,选择“事件选择”选项卡,点击“显示所有事件”复选框,在其中点击“Locks”事件,在“Deadlock graph”复选框,这样在发生死锁的时候,就会被监控到,而且以图像的方式显示死锁的信息,易于理解:

2、构造死锁。

先创建一个表


  1. --建表
  2. if OBJECT_ID('t1') is not null
  3. drop table t1
  4. go
  5. create table t1
  6. (
  7. id int primary key,
  8. v varchar(20)
  9. )
  10. insert into t1
  11. select 1 ,'aa' union all
  12. select 2 ,'bb' union all
  13. select 3 ,'cc' union all
  14. select 4 ,'dd' union all
  15. select 5 ,'ee' union all
  16. select 6 ,'ff'

开启会话X,在里面输入下面的代码:


  1. --执行顺序.1
  2. begin tran
  3. update t1
  4. set v = 'xx'
  5. where id = 3
  6. --执行顺序.1
  7. --执行顺序.3
  8. update t1
  9. set v = 'yy'
  10. where id = 6
  11. --执行顺序.3

再次开启会话Y,在里面输入代码:


  1. --执行顺序.2
  2. begin tran
  3. update t1
  4. set v = 'mm'
  5. where id = 6
  6. --执行顺序.2
  7. --执行顺序.4
  8. update t1
  9. set v = 'nn'
  10. where id = 3
  11. --执行顺序.4

然后,按照先执行会话X中的执行顺序1,然后执行会话Y中的执行顺序2,执行会话X中的执行顺序3,执行会话Y中的执行顺序4,一步一步执行。

当执行完这4个步骤后,在会话X中,显示了死锁,且会话X的事务被回滚:

同时,能在SQL Profiler中看到监控到的死锁:

从这个图中,我们可以看到详细的死锁信息,打叉的表示被回滚的会话,把鼠标放到椭圆上,会显示导致死锁的,这个会话正在运行的sql语句。

在长方形的框中,可以看到两个会话要获取X锁,左边的会话拥有下面方框中的键锁,右边的会话拥有上面的键锁,而当左边的会话想要获取上面的键锁是,被阻塞住了,而当右边的会话想要获取下面的键锁时,也被阻塞了,于是整个图像中形成了一个循环,也就导致了死锁。

3、获取更详细的阻塞信息。

注意,上面提到的会话X,这里是53,而会话Y是55,这个可以从上面图中,椭圆形中的“服务器进程ID”获得。

通过通过sys.dm_tran_locks,可以获取到更为详细的阻塞信息。


  1. select resource_type,
  2. resource_database_id, --数据库id
  3. resource_description, --资源描述
  4. resource_associated_entity_id, --资源关联实体id
  5. request_mode, --请求模式
  6. request_type, --请求类型
  7. request_status,
  8. request_session_id, --请求会话id
  9. request_owner_type
  10. from sys.dm_tran_locks
  11. where request_session_id = 55

解析resource_associated_entity_id的值:


  1. --1.查询resource_associated_entity_id的意义
  2. select *
  3. from sys.tables
  4. where object_id = 837578022
  5. /*
  6. 这个id是t1表
  7. name object_id
  8. t1 837578022
  9. */
  10. --2.查询resource_associated_entity_id的意义
  11. select *
  12. from sys.partitions p
  13. where p.hobt_id = 72057594041466880
  14. /*
  15. 这个是表t1的一个b树
  16. partition_id object_id index_id partition_number hobt_id
  17. 72057594041466880 837578022 1 1 72057594041466880
  18. */

4、通过dbcc page来解析sys.dm_tran_locks中resource_description列的值:


  1. resource_type resource_database_id resource_description
  2. PAGE 10 1:188
  3. KEY 10 (b9b173bbe8d5)
  4. KEY 10 (98ec012aa510)

为了能解析resource_description的值,需要建立一个表和一个存储过程,注意在存储过程中引用的1:188,就是上面sys.dm_tran_locks中的结果:


  1. --3.这里创建一个表,用来存放dbcc page的结果
  2. if exists(select * from sys.tables where name = 'dbcc_page')
  3. drop table dbcc_page
  4. go
  5. create table dbcc_page
  6. (
  7. ParentObject varchar(500),
  8. Object varchar(2000),
  9. Field varchar(1000),
  10. Value nvarchar(max)
  11. )
  12. go
  13. --创建一个存储过程
  14. if exists(select * from sys.procedures where name = 'proc_dbcc_page')
  15. drop procedure proc_dbcc_page
  16. go
  17. create procedure proc_dbcc_page
  18. as
  19. DBCC page(10, --数据库id : 10
  20. 1, --文件id: 1
  21. 188, --页id: 188
  22. 3) with tableresults
  23. go
  24. insert into dbcc_page
  25. exec proc_dbcc_page
  26. go

最后,我们查询一下,(b9b173bbe8d5)和(98ec012aa510),到底是哪一行数据


  1. --查询(b9b173bbe8d5)和(98ec012aa510),到底是哪一行数据
  2. ;with t
  3. as
  4. (
  5. select OBJECT,
  6. Field,
  7. value,
  8. case when charindex('Column',object) > 0
  9. then charindex('Column',object)
  10. else charindex('Offset',object)
  11. end as substring_len
  12. from dbcc_page dp
  13. where Object like 'Slot%Column%'
  14. or
  15. Field = 'KeyHashValue'
  16. ),
  17. tt
  18. as
  19. (
  20. select object,
  21. field,
  22. value,
  23. cast(substring(object,len('Slot')+1,substring_len-len('Slot')-1) as int) as row
  24. from t
  25. ),
  26. ttt
  27. as
  28. (
  29. select object,
  30. field,
  31. value,
  32. row, --第几行
  33. max(case when field = 'KeyHashValue'
  34. then value
  35. else ''
  36. end) over(partition by row) as KeyHashValue
  37. from tt
  38. )
  39. select *
  40. from ttt
  41. where KeyHashValue in ('(b9b173bbe8d5)', '(98ec012aa510)')

下面的是查询结果:

从上图中,我们能很清楚的看到(b9b173bbe8d5)和(98ec012aa510),就是id为3、6的两行数据,这两行数据最后被会话55锁住了。

发布了416 篇原创文章 · 获赞 135 · 访问量 94万+

通过DBCC Page查看在SQL Server中哪行数据被锁住了?的更多相关文章

  1. .SQL Server中 image类型数据的比较

    原文:.SQL Server中 image类型数据的比较 在SQL Server中如果你对text.ntext或者image数据类型的数据进行比较.将会提示:不能比较或排序 text.ntext 和 ...

  2. 删除sql server中重复的数据

    原文:删除sql server中重复的数据 with list_numbers as( select Name, AuthorOrTime, Url, Price, EstimatePrice, Si ...

  3. sql Server中临时表与数据表的区别

    sql server 中临时表与数据表的区别 1.如何判断临时表和数据表已生成 --如何判断临时表是否已创建--- if exists(select * from tempdb..sysobjects ...

  4. 转:Sql Server中清空所有数据表中的记录

    如果要删除数据表中所有数据只要遍历一下数据库再删除就可以了,清除所有数据我们可以使用搜索出所有表名,构造为一条SQL语句进行清除了,这里我一一给各位同学介绍.   使用sql删除数据库中所有表是不难的 ...

  5. SQL Server中Table字典数据的查询SQL示例代码

    SQL Server中Table字典数据的查询SQL示例代码 前言 在数据库系统原理与设计(第3版)教科书中这样写道: 数据库包含4类数据: 1.用户数据 2.元数据 3.索引 4.应用元数据 其中, ...

  6. Sql Server中清空所有数据表中的记录

    Sql Server中清空所有数据表中的记录 清空所有数据表中的记录: 代码如下:exec sp_msforeachtable  @Command1 ='truncate table ?'删除所有数据 ...

  7. 从TXT文本文档向Sql Server中批量导入数据

    下面我们通过以下的简单的SQL语句即可实现数据的批量导入,代码如下: Bulk insert id From 'G:\文档\test.txt' With ( fieldterminator=',', ...

  8. SQL Server 中 ROWLOCK 行级锁

    一.ROWLOCK的使用 1.ROWLOCK行级锁确保,在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改.因而行级锁即可保证数据的一致性,又能提高数据操作的并发性. 2.ROWLOC ...

  9. Sql Server实现多行数据按分组用逗号分隔成一行数据

    例如,要将下面的数据 以GROUP_ID进行分组,一组一行,一组中的多个PRODUCT_ID用逗号分隔,select 出来成如下结果: 在Sql Server中,我目前想到的一种方法是写一个函数,如下 ...

随机推荐

  1. cat file | while read line的问题

    循环中的重定向 或许你应该在其他脚本中见过下面的这种写法: while read line do        … done < file 刚开始看到这种结构时,很难理解< file是如何 ...

  2. 项目管理工具-OmniPlan 3 for Mac

    链接:https://pan.baidu.com/s/1tp_37fHXHwJuklL1nNSwig  密码:l0sf 激活迷药(里面自带的keygen不能用,用这个好使): Name: Appked ...

  3. centos上安装Python并修复yum

    date: 2019-07-01  18:09:53 author: headsen chen notice: 个人原创 1,安装python3.7: yum install zlib-devel b ...

  4. Qt编写自定义控件40-导航进度条

    一.前言 导航进度条控件,其实就是支付宝.京东.淘宝订单页面的进度控件,提示当前第几步,总共有几步,然后当前进度特殊颜色显示,每个进度带有时间文字等信息,本控件特意将三种样式风格都集成进去了,京东订单 ...

  5. 学习TypeScript 笔记

    TypeScript 什么是TypeScript TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准. TypeScript 由微软开发的自由和开源的编程 ...

  6. 简介Python设计模式中的代理模式与模板方法模式编程

    简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...

  7. 使用json_encode编码中文返回null的解决方案

    在gbk的程序中,直接使用json_encode编码包含中文字符的数组,将会返回null. 解决方法: 1.把程序文件编码改为utf8 2.使用mb_convert_encoding把编码转换为utf ...

  8. Spring Cloud(7.3):配置Consumer Server

    接下来我们创建一个消费者服务.消费者服务从生产者服务拿取商品-价格信息,并保存在Redis中.同时,接收消息队列中生产者服务的更新提示,如果某个商品-价格被修改,则删除Redis中的缓存数据,并重新从 ...

  9. 925. Long Pressed Name

    题目链接:https://leetcode.com/problems/long-pressed-name/description/ Example 1: Input: name = "ale ...

  10. ELK之elasticsearch删除索引

    参考文档:https://www.cnblogs.com/Dev0ps/p/9493576.html elasticsearch使用时间久了会产生大量索引占用磁盘空间,可以删除索引来释放 查看当前所有 ...