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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 在SQL Server中有时候会使用提示(Hint)强制SQL使用行锁(Row Lock),前两天有个同事咨询了一个问题,如何定位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 

 

 

clip_image001

 

 

查询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;

 

 

 

clip_image002

 

准备下面脚本,为了后续我们定位到行锁锁定哪一行记录。准备好后面脚本后,我们就可以开始测试了。注意,需要开启跟踪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  这个表示这个页面的第几行记录。

                                                                                                                                                                                                                                                      

 

 

clip_image003

 

 

但是,有时候你锁定了一行,查询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;

 

 

clip_image004

 

 

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

 

clip_image005

 

 

其它一些页面,例如 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.

 

 

clip_image006

 

clip_image007

 

 

 

 

 

参考资料:

 

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

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

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
1月前
|
SQL 存储 缓存
SQL Server 数据太多如何优化
11种优化方案供你参考,优化 SQL Server 数据库性能得从多个方面着手,包括硬件配置、数据库结构、查询优化、索引管理、分区分表、并行处理等。通过合理的索引、查询优化、数据分区等技术,可以在数据量增大时保持较好的性能。同时,定期进行数据库维护和清理,保证数据库高效运行。
|
2月前
|
SQL 移动开发 Oracle
SQL语句实现查询连续六天数据的方法与技巧
在数据库查询中,有时需要筛选出符合特定时间连续性条件的数据记录
|
2月前
|
SQL 存储 关系型数据库
添加数据到数据库的SQL语句详解与实践技巧
在数据库管理中,添加数据是一个基本操作,它涉及到向表中插入新的记录
|
2月前
|
SQL 数据挖掘 数据库
SQL查询每秒的数据:技巧、方法与性能优化
id="">SQL查询功能详解 SQL(Structured Query Language,结构化查询语言)是一种专门用于与数据库进行沟通和操作的语言
|
2月前
|
SQL 监控 数据处理
SQL数据库数据修改操作详解
数据库是现代信息系统的重要组成部分,其中SQL(StructuredQueryLanguage)是管理和处理数据库的重要工具之一。在日常的业务运营过程中,数据的准确性和及时性对企业来说至关重要,这就需要掌握如何在数据库中正确地进行数据修改操作。本文将详细介绍在SQL数据库中如何修改数据,帮助读者更好
388 4
|
2月前
|
SQL 关系型数据库 MySQL
SQL批量插入测试数据的几种方法?
SQL批量插入测试数据的几种方法?
129 1
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
97 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
43 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
56 0
|
2月前
|
SQL
使用SQL进行集合查询和数据维护
使用SQL进行集合查询和数据维护
43 0