sql-server – 如何将SQL Server死锁报告中的密钥转换为值?

前端之家收集整理的这篇文章主要介绍了sql-server – 如何将SQL Server死锁报告中的密钥转换为值?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个死锁报告,告诉我有一个涉及waitresource =“KEY:9:72057632651542528(543066506c7c)”的冲突,我可以看到:
  1. <keylock hobtid="72057632651542528" dbid="9" objectname="MyDatabase.MySchema.MyTable" indexname="MyPrimaryKeyIndex" id="locka8c6f4100" mode="X" associatedObjectId="72057632651542528">

在< resource-list>内我希望能够找到密钥的实际值(例如,id = 12345).我需要使用什么sql语句来获取该信息?

解决方法

来自@ Kin,@ AaronBertrand和@DBAFromTheCold的答案非常棒,非常有帮助.我在测试期间发现的另一个重要信息是,在查找%% lockres %%时(通过索引查询提示),您需要使用sys.partitions为给定HOBT_ID返回的索引. .此索引并不总是PK或聚簇索引.

例如:

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

这是使用来自每个答案的片段修改的示例脚本.

  1. declare @keyValue varchar(256);
  2. SET @keyValue = 'KEY: 5:72057598157127680 (92d211c2a131)' --Output from deadlock graph: process-list/process[waitresource] -- CHANGE HERE !
  3. ------------------------------------------------------------------------
  4. --Should not have to change anything below this line:
  5. declare @lockres nvarchar(255),@hobbitID bigint,@dbid int,@databaseName sysname;
  6. --.............................................
  7. --PARSE @keyValue parts:
  8. SELECT @dbid = LTRIM(SUBSTRING(@keyValue,CHARINDEX(':',@keyValue) + 1,@keyValue,@keyValue) + 1) - (CHARINDEX(':',@keyValue) + 1) ));
  9. SELECT @hobbitID = convert(bigint,RTRIM(SUBSTRING(@keyValue,@keyValue) + 1) + 1,CHARINDEX('(',@keyValue) - CHARINDEX(':',@keyValue) + 1) - 1)));
  10. SELECT @lockRes = RTRIM(SUBSTRING(@keyValue,@keyValue) + 0,CHARINDEX(')',@keyValue) - CHARINDEX('(',@keyValue) + 1));
  11. --.............................................
  12. --Validate DB name prior to running dynamic sql
  13. SELECT @databaseName = db_name(@dbid);
  14. IF not exists(select * from sys.databases d where d.name = @databaseName)
  15. BEGIN
  16. RAISERROR(N'Database %s was not found.',16,1,@databaseName);
  17. RETURN;
  18. END
  19.  
  20. declare @objectName sysname,@indexName sysname,@schemaName sysname;
  21. declare @ObjectLookupsql as nvarchar(max) = '
  22. SELECT @objectName = o.name,@indexName = i.name,@schemaName = OBJECT_SCHEMA_NAME(p.object_id,@dbid)
  23. FROM ' + quotename(@databaseName) + '.sys.partitions p
  24. JOIN ' + quotename(@databaseName) + '.sys.indexes i ON p.index_id = i.index_id AND p.[object_id] = i.[object_id]
  25. JOIN ' + quotename(@databaseName)+ '.sys.objects o on o.object_id = i.object_id
  26. WHERE hobt_id = @hobbitID'
  27. ;
  28. --print @ObjectLookupsql
  29. --Get object and index names
  30. exec sp_executesql @ObjectLookupsql,N'@dbid int,@objectName sysname OUTPUT,@indexName sysname OUTPUT,@schemaName sysname OUTPUT',@dbid = @dbid,@hobbitID = @hobbitID,@objectName = @objectName output,@indexName = @indexName output,@schemaName = @schemaName output
  31. ;
  32.  
  33. DECLARE @fullObjectName nvarchar(512) = quotename(@databaseName) + '.' + quotename(@schemaName) + '.' + quotename(@objectName);
  34. SELECT fullObjectName = @fullObjectName,lockIndex = @indexName,lockRes_key = @lockres,hobt_id = @hobbitID,waitresource_keyValue = @keyValue;
  35.  
  36. --Validate object name prior to running dynamic sql
  37. IF OBJECT_iD( @fullObjectName) IS NULL
  38. BEGIN
  39. RAISERROR(N'The object "%s" was not found.',@fullObjectName);
  40. RETURN;
  41. END
  42.  
  43. --Get the row that was blocked
  44. --NOTE: we use the NOLOCK hint to avoid locking the table when searching by %%lockres%%,which might generate table scans.
  45. DECLARE @finalResult nvarchar(max) = N'SELECT lockResKey = %%lockres%%,*
  46. FROM ' + @fullObjectName
  47. + ISNULL(' WITH(NOLOCK INDEX(' + QUOTENAME(@indexName) + ')) ','')
  48. + ' WHERE %%lockres%% = @lockres'
  49. ;
  50.  
  51. --print @finalresult
  52. EXEC sp_executesql @finalResult,N'@lockres nvarchar(255)',@lockres = @lockres;

猜你在找的MsSQL相关文章