SQL Server中如何定位Row Lock锁定哪一行数据

在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/

时间: 2024-10-26 08:29:23

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

sql server中如何将相同货物的两条数据的数量相加合成一条替代原始数据

问题描述 sql server中如何将相同货物的两条数据的数量相加合成一条替代原始数据 表中如图所示两条数据,按照mh,有相同的,则将两条数据的数量相加合并为一条,没有相同则不变,表中mh相同最多只有2条.怎么样得到 mh sl dw ck A2 100 A A 解决方案 select mh,dw,ck,sum(sl) from xxx group by mh,dw,ck 这样汇总出一个新的数据,用这个数据替换你原有的就好了 还可以将这些数据 select into 到一个新表,然后删除旧表,再

基于SQL Server中如何比较两个表的各组数据 图解说明_MsSql

开始 前一阵子,在项目中碰到这样一个SQL查询需求,有两个相同结构的表(table_left & table_right),如下: 图1. 检查表table_left的各组(groupId),是否在表table_right中存在有一组(groupId)数据(data)与它的数据(data)完全相等. 如图1. 可以看出表table_left和table_right存在两组数据完整相等: 图2. 分析 从上面的两个表,可以知道它们存放的是一组一组的数据:那么,接下来我借助数学集合的列举法和运算进行

SQL Server中如何比较两个表的各组数据方法总结

 代码如下 复制代码 use tempdb go if object_id('table_left') is not null drop table table_left if object_id('table_right') is not null drop table table_right go create table table_left(groupId nvarchar(5),dataSub1 nvarchar(10),dataSub2 nvarchar(10)) create ta

SQL server中如何备份和还原以及备份系统数据库

备份 SQL Server 数据库.在备份上运行测试还原过程以及在另一个安全位置存储备份副本可防止可能的灾难性数据丢失. 使用有效的数据库备份,可从多种故障中恢复数据,例如: 介质故障. 用户错误(例如,误删除了某个表). 硬件故障(例如,磁盘驱动器损坏或服务器报废). 自然灾难. 备份模式在sql server中也有三种类型(它决定备份哪些数据) 1.完整备份 备份包括这个数据库,部分事务日志,数据库结构和文件结构.完整备份代表的是备份完成时刻的数据库状态 2.差异备份 它备份在上一次完整备份

将SQL Server中的表变成txt文件

方法一:用BCP命令 bcp 实用工具 bcp 实用工具在 Microsoft? SQL Server? 2000 实例和数据文件之间以用户指定的格式复数据. 语法 bcp {[[database_name.][owner].]{table_name | view_name} | "query"} {in | out | queryout | format} data_file [-m max_errors] [-f format_file] [-e err_file] [-F fir

《SQL Server企业级平台管理实践》读书笔记——SQL Server中数据文件空间使用与管理

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server中数据文件空间使用与管理 1.表和索引存储结构 在SQL Server2005以前,一个表格是以一个B树或者一个堆(heap)存放的.每个B树或者堆,在sysindexes里面都有一条记录相对应.SQL Server2005以后,引入了分区表的概念(Table Partition),在存储组织上,现有的分区基本上替代了原来表格的概念,原先表的概念成为了一个逻辑概念.一个分区就是一个B树或者一个堆.而一张表格则是一个

SQL Server学习笔记之事务、锁定、阻塞、死锁用法详解

本文实例讲述了SQL Server学习笔记之事务.锁定.阻塞.死锁用法.分享给大家供大家参考,具体如下: 1.事务 隐式事务 /*================================================================== 当以create,drop, fetch,open, revoke,grand, alter table,select,insert,delete,update,truncate table 语句首先执行的时候,SQL Server会话

SQL SERVER中对查询结果随机排序

server|排序|随机 译:SQL SERVER中对查询结果随机排序 Randomly Sorting Query Results 查询结果随机排序 Q. How can I randomly sort query results?问:怎样才能对查询结果随机排序? A. To randomly order rows, or to return x number of randomly chosen rows, you can use the RAND function inside the S

深入理解SQL Server 中的错误处理

大多数迭代语言编译器都有内置的错误处理程序(例如,TRY-CATCH语句),开发者们在设计代码的时候可以利用它们.虽然SQL Server 2000的开发者不能够像迭代语言的开发者那样利用内置的工具,但是他们可以用系统变量@@ERROR来设计自己有效的错误处理工具. 引入事务 为了能够掌握在SQL Server 2000中错误处理是如何工作的,你必须首先要理解数据库事务的概念.在数据库术语中,事务就是指作为一个单独的工作单位出现的一系列语句.举个例子来说,假设你有三个语句要执行,事务就可以这样被