AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 106762
Accepted
Mark Freeman
Mark Freeman
Asked: 2015-07-14 05:37:15 +0800 CST2015-07-14 05:37:15 +0800 CST 2015-07-14 05:37:15 +0800 CST

如何将 SQL Server 死锁报告中的键转换为值?

  • 772

我有一份僵局报告告诉我存在涉及的冲突

waitresource="KEY: 9:72057632651542528 (543066506c7c)"

我可以看到这个:

<keylock hobtid="72057632651542528" dbid="9" objectname="MyDatabase.MySchema.MyTable" indexname="MyPrimaryKeyIndex" id="locka8c6f4100" mode="X" associatedObjectId="72057632651542528">

<resource-list>元素内。

我希望能够找到键的实际值(例如 id = 12345)。我需要使用什么 SQL 语句来获取该信息?

sql-server sql-server-2012
  • 4 4 个回答
  • 13942 Views

4 个回答

  • Voted
  1. dbafromthecold
    2015-07-14T06:22:11+08:002015-07-14T06:22:11+08:00

    您有 hobt_id,因此以下查询将识别该表:-

    SELECT o.name
    FROM sys.partitions p
    INNER JOIN sys.objects o ON p.object_id = o.object_id
    WHERE p.hobt_id = 72057632651542528
    

    然后,您可以运行以下语句来识别表中的行(如果它仍然存在):-

    SELECT %%LOCKRES%%,  *
    FROM [TABLE NAME] WITH(INDEX(MyPrimaryKeyIndex))
    WHERE %%LOCKRES%% = '(543066506c7c)'
    

    但是请注意上面的语句,它会扫描目标表,因此在 READ UNCOMMITTED 中运行并监视您的服务器。

    这是 Grant Fritchey 撰写的关于 %%LOCKRES%% 的文章 - http://www.scarydba.com/2010/03/18/undocumented-virtual-column-lockres/

    这是我自己博客中关于使用 %%LOCKRES%% 从扩展事件中识别行的文章:- https://dbafromthecold.wordpress.com/2015/02/24/identifying-blocking-via-extended-events/

    • 15
  2. Best Answer
    BateTech
    2015-08-04T13:16:35+08:002015-08-04T13:16:35+08:00

    @Kin、@AaronBertrand 和 @DBAFromTheCold 的答案很棒,而且很有帮助。我在测试期间发现的一条重要信息是,在查找(通过索引查询提示)时,您需要使用从sys.partitions给定返回的索引。此索引并不总是 PK 或聚集索引。HOBT_ID%%lockres%%

    例如:

    --Sometimes this does not return the correct results.
    SELECT lockResKey = %%lockres%% ,* 
    FROM [MyDB].[dbo].[myTable]  
    WHERE %%lockres%% = @lockres
    ;
    --But if you add the index query hint, it does return the correct results
    SELECT lockResKey = %%lockres%% ,* 
    FROM [MyDB].[dbo].[myTable] WITH(NOLOCK INDEX([IX_MyTable_NonClustered_index]))  
    WHERE %%lockres%% = @lockres
    ;
    

    这是使用每个答案中的片段修改的示例脚本。

    declare @keyValue varchar(256);
    SET @keyValue = 'KEY: 5:72057598157127680 (92d211c2a131)' --Output from deadlock graph: process-list/process[waitresource] -- CHANGE HERE !
    ------------------------------------------------------------------------
    --Should not have to change anything below this line: 
    declare @lockres nvarchar(255), @hobbitID bigint, @dbid int, @databaseName sysname;
    --.............................................
    --PARSE @keyValue parts:
    SELECT @dbid = LTRIM(SUBSTRING(@keyValue, CHARINDEX(':', @keyValue) + 1, CHARINDEX(':', @keyValue, CHARINDEX(':', @keyValue) + 1) - (CHARINDEX(':', @keyValue) + 1) ));
    SELECT @hobbitID = convert(bigint, RTRIM(SUBSTRING(@keyValue, CHARINDEX(':', @keyValue, CHARINDEX(':', @keyValue) + 1) + 1, CHARINDEX('(', @keyValue) - CHARINDEX(':', @keyValue, CHARINDEX(':', @keyValue) + 1) - 1)));
    SELECT @lockRes = RTRIM(SUBSTRING(@keyValue, CHARINDEX('(', @keyValue) + 0, CHARINDEX(')', @keyValue) - CHARINDEX('(', @keyValue) + 1));
    --.............................................
    --Validate DB name prior to running dynamic SQL
    SELECT @databaseName = db_name(@dbid);  
    IF not exists(select * from sys.databases d where d.name = @databaseName)
    BEGIN
        RAISERROR(N'Database %s was not found.', 16, 1, @databaseName);
        RETURN;
    END
    
    declare @objectName sysname, @indexName sysname, @schemaName sysname;
    declare @ObjectLookupSQL as nvarchar(max) = '
    SELECT @objectName = o.name, @indexName = i.name, @schemaName = OBJECT_SCHEMA_NAME(p.object_id, @dbid)
    FROM ' + quotename(@databaseName) + '.sys.partitions p
    JOIN ' + quotename(@databaseName) + '.sys.indexes i ON p.index_id = i.index_id AND p.[object_id] = i.[object_id]
    JOIN ' + quotename(@databaseName)+ '.sys.objects o on o.object_id = i.object_id
    WHERE hobt_id = @hobbitID'
    ;
    --print @ObjectLookupSQL
    --Get object and index names
    exec sp_executesql @ObjectLookupSQL
        ,N'@dbid int, @hobbitID bigint, @objectName sysname OUTPUT, @indexName sysname OUTPUT, @schemaName sysname OUTPUT'
        ,@dbid = @dbid
        ,@hobbitID = @hobbitID
        ,@objectName = @objectName output
        ,@indexName = @indexName output
        ,@schemaName = @schemaName output
    ;
    
    DECLARE @fullObjectName nvarchar(512) = quotename(@databaseName) + '.' + quotename(@schemaName) + '.' + quotename(@objectName);
    SELECT fullObjectName = @fullObjectName, lockIndex = @indexName, lockRes_key = @lockres, hobt_id = @hobbitID, waitresource_keyValue = @keyValue;
    
    --Validate object name prior to running dynamic SQL
    IF OBJECT_iD( @fullObjectName) IS NULL 
    BEGIN
        RAISERROR(N'The object "%s" was not found.',16,1,@fullObjectName);
        RETURN;
    END
    
    --Get the row that was blocked
    --NOTE: we use the NOLOCK hint to avoid locking the table when searching by %%lockres%%, which might generate table scans.
    DECLARE @finalResult nvarchar(max) = N'SELECT lockResKey = %%lockres%% ,* 
    FROM ' + @fullObjectName
    + ISNULL(' WITH(NOLOCK INDEX(' + QUOTENAME(@indexName) + ')) ', '')  
    + ' WHERE %%lockres%% = @lockres'
    ;
    
    --print @finalresult
    EXEC sp_executesql @finalResult, N'@lockres nvarchar(255)', @lockres = @lockres;
    
    • 14
  3. Kin Shah
    2015-07-14T06:39:52+08:002015-07-14T06:39:52+08:00

    这是对DBAFromTheCold和Aaron Bertrand已经发布的答案的补充。

    微软仍然留下%%lockres%%了未记录的功能。

    以下是可以帮助您的脚本:

    declare @databaseName varchar(100) = 'yourdatabaseName' --CHANGE HERE !
    declare @keyValue varchar(100) = 'KEY: 9:72057632651542528 (543066506c7c)' --Output from deadlock graph -- CHANGE HERE !
    declare @lockres varchar(100)
    declare @hobbitID bigint
    
    select @hobbitID = convert(bigint, RTRIM(SUBSTRING(@keyValue, CHARINDEX(':', @keyValue, CHARINDEX(':', @keyValue) + 1) + 1, CHARINDEX('(', @keyValue) - CHARINDEX(':', @keyValue, CHARINDEX(':', @keyValue) + 1) - 1)))
    
    select @lockRes = RTRIM(SUBSTRING(@keyValue, CHARINDEX('(', @keyValue) + 1, CHARINDEX(')', @keyValue) - CHARINDEX('(', @keyValue) - 1))
    
    declare @objectName sysname
    declare @ObjectLookupSQL as nvarchar(max) = '
    SELECT @objectName = o.name
    FROM ' + quotename(@databaseName) + '.sys.partitions p
    JOIN ' + quotename(@databaseName) + '.sys.indexes i ON p.index_id = i.index_id AND p.[object_id] = i.[object_id]
    join ' + quotename(@databaseName)+ '.sys.objects o on o.object_id = i.object_id
    WHERE hobt_id = ' + convert(nvarchar(50), @hobbitID) + ''
    
    --print @ObjectLookupSQL
    exec sp_executesql @ObjectLookupSQL
        ,N'@objectName sysname OUTPUT'
        ,@objectName = @objectName output
    
    --print @objectName
    
    declare @finalResult nvarchar(max) = N'select %%lockres%% ,* 
    from ' + quotename(@databaseName) + '.dbo.' + @objectName + '
    where %%lockres%% = ''(' + @lockRes + ')''
    '
    --print @finalresult
    exec sp_executesql @finalResult
    

    另请参阅这篇出色的博客文章:可疑死锁和不那么合乎逻辑的锁的奇怪案例

    • 10
  4. Aaron Bertrand
    2015-07-14T06:27:46+08:002015-07-14T06:27:46+08:00

    对不起,已经在研究这个答案,并在另一个出现时发布。添加为社区 wiki 只是因为它是一种略有不同的方法并添加了一些其他信息。

    543066506c7c本质上是主键的散列,您可以使用以下动态 SQL 检索该行(以及可能存在散列冲突的任何行):

    -- Given: KEY: 9:72057632651542528 (543066506c7c)
    -- and object = MyDatabase.MySchema.MyTable
    
    DECLARE 
      @hobt BIGINT = 72057632651542528,
      @db SYSNAME = DB_NAME(9),
      @res VARCHAR(255) = '(543066506c7c)';
    
    DECLARE @exec NVARCHAR(MAX) = QUOTENAME(@db) + N'.sys.sp_executesql';
    
    DECLARE @sql NVARCHAR(MAX) = N'SELECT %%LOCKRES%%,*
      FROM MySchema.MyTable WHERE %%LOCKRES%% = @res;';
    
    EXEC @exec @sql, N'@res VARCHAR(255)', @res;
    

    当然,您可以在没有动态 SQL 的情况下执行此操作,但这为您提供了一个很好的片段或存储过程模板,您可以在其中插入值,如果这是您经常解决的问题。(你也可以参数化表名,你也可以构建 KEY: 字符串的解析来动态地为你确定一切,但我认为这可能超出了本文的范围。)

    • 6

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve