在SQL Server中有时候会使用提示(Hint)强制SQL使用行锁(Row Lock),前两天有个同事咨询了一个问题,如何定位Row Lock具体锁定了哪一行。其实这个问题只适合研究一下,实际意义并不大,因为找到、定位被锁定的行的代价开销较大,而意义却不怎么大,而且使用场景也很少。那么下面我们来探讨、研究一下这个问题吧:

在会话窗口(会话ID=65)下执行下面SQL语句,模拟SQL Server使用行锁锁定某一行记录:

USE AdventureWorks2012;

GO

 

SELECT  @@SPID;

 

BEGIN TRAN;

UPDATE  [dbo].[DatabaseLog] WITH ( ROWLOCK )

SET     TSQL = N'dddd'

WHERE   DatabaseLogID = 1;

--ROLLBACK;

在另外一个会话窗口使用下面SQL查询,我们能看到相关锁的一些信息,如下所示,但是这些信息还不够详细,我们还需要更详细的信息:

SELECT Db_name(RSC_DBID)                AS 'DATABASE_NAME', 

       CASE RSC_TYPE 

         WHEN 1 THEN 'null' 

         WHEN 2 THEN 'DATABASE' 

         WHEN 3 THEN 'FILE' 

         WHEN 4 THEN 'INDEX' 

         WHEN 5 THEN 'TABLE' 

         WHEN 6 THEN 'PAGE' 

         WHEN 7 THEN 'KEY' 

         WHEN 8 THEN 'EXTEND' 

         WHEN 9 THEN 'RID ( ROW ID)' 

         WHEN 10 THEN 'APPLICATION' 

       END                              AS 'REQUEST_TYPE', 

       CASE REQ_OWNERTYPE 

         WHEN 1 THEN 'TRANSACTION' 

         WHEN 2 THEN 'CURSOR' 

         WHEN 3 THEN 'SESSION' 

         WHEN 4 THEN 'ExSESSION' 

       END                              AS 'REQUEST_OWNERTYPE', 

       Object_name(RSC_OBJID, RSC_DBID) AS 'OBJECT_NAME', 

       PROCESS.HOSTNAME, 

       PROCESS.NT_DOMAIN, 

       PROCESS.NT_USERNAME, 

       PROCESS.PROGRAM_NAME, 

       SQLTEXT.TEXT 

FROM   sys.syslockinfo LOCK 

       JOIN sys.sysprocesses PROCESS 

         ON LOCK.REQ_SPID = PROCESS.SPID 

       CROSS apply sys.DM_EXEC_SQL_TEXT(PROCESS.SQL_HANDLE) SQLTEXT 

WHERE  PROCESS.SPID = 65 

查询sys.dm_tran_locks我们可以得到更详细的信息,例如,从resource_description中我们可以得到file_id=1, 页面编号为273,这个页面的第一条记录(0)

SELECT  resource_type ,

resource_database_id , --数据库id

resource_description , --资源描述

resource_associated_entity_id , --资源关联实体id

request_mode , --请求模式

request_type , --请求类型

request_status ,

request_session_id , --请求会话id

request_owner_type

FROM    sys.dm_tran_locks

WHERE   request_session_id = 65;

准备下面脚本,为了后续我们定位到行锁锁定哪一行记录。准备好后面脚本后,我们就可以开始测试了。注意,需要开启跟踪DBCC TRACEON(3604)。否则DBCC PAGE没有任何输出信息

IF EXISTS (SELECT * FROM sys.objects WHERE type='U' AND name='DBCC_PAGE_RESULT')

    DROP TABLE DBCC_PAGE_RESULT;

GO

 

CREATE TABLE DBCC_PAGE_RESULT

(

    [ParentObject]      NVARCHAR(200),

    [Object]          NVARCHAR(2000),

    [Field]          NVARCHAR(4000),

    [Value]          NVARCHAR(MAX)

)

GO

 

CREATE PROCEDURE PRC_DBCC_PAGE

(

 @dbid        INT,

 @filenum    INT,

 @pagenum     INT

)

AS

 

 DBCC PAGE(@dbid, @filenum,  @pagenum, 3) WITH TABLERESULTS;

 

GO

 

DBCC TRACEON(3604)

 

 

 

 

;WITH    t AS ( SELECT   Object ,

                        Field ,

                        Value ,

                        CASE WHEN CHARINDEX('Column', Object) > 0

                             THEN CHARINDEX('Column', Object)

                             ELSE CHARINDEX('Offset', Object)

                        END AS substring_len

               FROM     dbo.DBCC_PAGE_RESULT dp

               WHERE    Object LIKE 'Slot%Column%'

                        OR Field = 'KeyHashValue'

             ),

        tt

          AS ( SELECT   Object ,

                        Field ,

                        Value ,

                        CAST(SUBSTRING(Object, LEN('Slot') + 1,

                                       substring_len - LEN('Slot') - 1) AS INT) AS row

               FROM     t

             ),

        ttt

          AS ( SELECT   Object ,

                        Field ,

                        Value ,

                        row ,    --第几行  

                        MAX(CASE WHEN Field = 'KeyHashValue' THEN Value

                                 ELSE ''

                            END) OVER ( PARTITION BY row ) AS KeyHashValue

               FROM     tt

             )

    SELECT  *

    FROM    ttt

    WHERE   ttt.row = 0

如下截图所示,就可以找到行锁(Row Lock)锁定了row=0这行记录(注意,这里的行记录是从0开始的,而不是1),也就是DatabaseLogID=1的记录。如果1:273:2, 那么查询条件中row=2  这个表示这个页面的第几行记录。

但是,有时候你锁定了一行,查询sys.dm_tran_locks时,你会发现resource_type为RID类型的记录有好几条,如下所示:

USE AdventureWorks2012;

GO

 

SELECT  @@SPID;

 

BEGIN TRAN;

UPDATE  [dbo].[DatabaseLog] WITH ( ROWLOCK )

SET     TSQL = N'dddd'

WHERE   DatabaseLogID = 21;

--ROLLBACK;

其实真正是数据页的只有resource_description=1:273:4 这行记录, 也就是说这行记录位于Page Number=273下的第5条记录

其它一些页面,例如 1,295;  1,279等都不是数据页,如下截图所示:m_type的值表示这个是数据页、索引页、IAM页等等。具体参考

m_type

·         This is the page type. The values you’re likely to see are:

o   1 – data page. This holds data records in a heap or clustered index leaf-level.

o   2 – index page. This holds index records in the upper levels of a clustered index and all levels of non-clustered indexes.

o   3 – text mix page. A text page that holds small chunks of LOB values plus internal parts of text tree. These can be shared between LOB values in the same partition of an index or heap.

o   4 – text tree page. A text page that holds large chunks of LOB values from a single column value.

o   7 – sort page. A page that stores intermediate results during a sort operation.

o   8 – GAM page. Holds global allocation information about extents in a GAM interval (every data file is split into 4GB chunks – the number of extents that can be represented in a bitmap on a single database page). Basically whether an extent is allocated or not. GAM = Global Allocation Map. The first one is page 2 in each file. More on these in this post.

o   9 – SGAM page. Holds global allocation information about extents in a GAM interval. Basically whether an extent is available for allocating mixed-pages. SGAM = Shared GAM. the first one is page 3 in each file. More on these in this post.

o   10 – IAM page. Holds allocation information about which extents within a GAM interval are allocated to an allocation unit (portion of a table or index). IAM = Index Allocation Map. More on these in this post.

o   11 – PFS page. Holds allocation and free space information about pages within a PFS interval (every data file is also split into approx 64MB chunks – the number of pages that can be represented in a byte-map on a single database page. PFS = Page Free Space. The first one is page 1 in each file. More on these in this post.

o   13 – boot page. Holds information about the database. There’s only one of these in the database. It’s page 9 in file 1.

o   15 – file header page. Holds information about the file. There’s one per file and it’s page 0 in the file.

o   16 – diff map page. Holds information about which extents in a GAM interval have changed since the last full or differential backup. The first one is page 6 in each file.

o   17 – ML map page. Holds information about which extents in a GAM interval have changed while in bulk-logged mode since the last backup. This is what allows you to switch to bulk-logged mode for bulk-loads and index rebuilds without worrying about breaking a backup chain. The first one is page 7 in each file.

o   18 – a page that’s be deallocated by DBCC CHECKDB during a repair operation.

o   19 – the temporary page that ALTER INDEX … REORGANIZE (or DBCC INDEXDEFRAG) uses when working on an index.

o   20 – a page pre-allocated as part of a bulk load operation, which will eventually be formatted as a ‘real’ page.

 

 

 

参考资料:

http://blog.csdn.net/sqlserverdiscovery/article/details/13291629

https://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-page/

SQL Server中如何定位Row Lock锁定哪一行数据的更多相关文章

  1. SQL Server 将两行或者多行拼接成一行数据

    一个朋友,碰到一个问题. 就是查询出来的结果集,需要每隔三行.就将这三行数据以此拼接为一行显示.起初我想着用ROW_NUMBER加CASE WHEN去做,发现结果并非我预期那样. 结果如下: 由于别人 ...

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

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

  3. SQL Server中解决死锁

    SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

  4. SQL Server中解决死锁的新方法介绍

    SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

  5. Microsoft SQL Server中的事务与并发详解

    本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...

  6. Sql Server 中锁的概念

    锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 丢失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 脏 ...

  7. SQL Server中的锁 详解 nolock,rowlock,tablock,xlock,paglock

    摘自: http://www.myexception.cn/sql-server/385562.html 高手进 锁 nolock,rowlock,tablock,xlock,paglock 锁 no ...

  8. SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

  9. 【转】SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

随机推荐

  1. Flex(ActionScript)与JavaScript交互的两种方式示例

    随着各单位部门信息化进程的不断发展,互通互联.共享协调不断的被越来越多的客户所重视.很多新项目都要去必须能够集成已有的早期系统,至少也要能够实现交互对接.今天跟大家分享的是系统对接中ActionScr ...

  2. PXC快速入门

    1.快速入门 实验环境: Node Host IP Node1 pxc1 192.168.70.61 Node2 pxc2 192.168.70.62 Node3 pxc3 192.168.70.63 ...

  3. 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一)

    转发时请注明原创作者及地址,否则追究责任. 原创:alunchen 当创建AspNetCore项目时 当我们创建一个AspNetCore项目时,需要我们手动添加Log: services.AddLog ...

  4. mvc 中合并两个list集合

    有时候,在进行查询操作的时候需要将从数据库中查询的两张表进行合并,成为一张表然后返回给前端.或者在原有的一张表基础上面加几个新的字段. 这个时候可以新建一个.class[model类],在这个新建的m ...

  5. [转]How to Add Bootstrap to an Angular CLI project

    本文转自:https://loiane.com/2017/08/how-to-add-bootstrap-to-an-angular-cli-project/ In this article we w ...

  6. 【转载】ASP.NET以Post方式抓取远程网页内容类似爬虫功能

    使用HttpWebRequest等Http相关类,可以在应用程序中或者网站中模拟浏览器发送Post请求,在请求带入相应的Post参数值,而后请求回远程网页信息.实现这一功能也很简单,主要是依靠Http ...

  7. CLR 协变、逆变

    看书看得有点晕了,协变.逆变傻傻分不清楚. 看到泛型和委托.委托方法,发现这里面的协变和逆变不一样. 泛型的逆变和协变:如果某个返回类型可以由其基类替换,那么这个类型就是支持协变的.如果某个参数类型可 ...

  8. C# 中 FindControl 方法及使用

    FindControl 的使用方法 FindControl (String  id): 在页命名容器中搜索带指定标识符的服务器控件.(有点类似javascript中的getElementById(st ...

  9. 1.shell学习之常用语句

    本章学习内容: 1.常见符号 2.命令分隔符-分号";" 3.双分号 ";;" 4. '单引号和"双引号 5.`反引号和$() 6.${}和$ 7.冒 ...

  10. 改变Tomcat在地址栏上显示的小猫图标

    部署在Tomcat上的项目通常在地址栏会显示一个小猫的图标,那么如何改变这个图标呢? 第一步.制作自己显示的图标 这里使用的是在线制作的方式,推荐一个在线制作的网站---比特虫:http://www. ...