AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 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

Como posso converter uma chave em um relatório de impasse do SQL Server para o valor?

  • 772

Tenho um relatório de impasse que me diz que houve um conflito envolvendo

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

e eu posso ver isso:

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

dentro do <resource-list>elemento.

Quero poder encontrar o valor real da chave (id = 12345, por exemplo). Qual instrução SQL eu precisaria usar para obter essas informações?

sql-server sql-server-2012
  • 4 4 respostas
  • 13942 Views

4 respostas

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

    Você tem o hobt_id, então a seguinte consulta identificará a tabela: -

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

    A partir disso, você pode executar a seguinte instrução para identificar a linha na tabela (se ainda existir): -

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

    Tenha cuidado com a instrução acima, no entanto, ela examinará a tabela de destino, portanto, execute READ UNCOMMITTED e monitore seu servidor.

    Aqui está um artigo de Grant Fritchey sobre %%LOCKRES%% - http://www.scarydba.com/2010/03/18/undocumented-virtual-column-lockres/

    E aqui está um artigo do meu próprio blog sobre o uso de %%LOCKRES%% para identificar linhas de um evento estendido:- 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

    As respostas de @Kin, @AaronBertrand e @DBAFromTheCold são ótimas e foram muito úteis. Uma informação importante que descobri durante o teste que as outras respostas foram deixadas de fora é que você precisa usar o índice que é retornado sys.partitionspara o dado HOBT_IDao procurar o %%lockres%%(por meio de uma dica de consulta de índice). Esse índice nem sempre é o índice PK ou clusterizado.

    Por exemplo:

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

    Aqui está um script de exemplo modificado usando partes de cada uma dessas respostas.

    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

    O é um complemento às respostas já postadas por DBAFromTheCold e Aaron Bertrand .

    A Microsoft ainda deixou %%lockres%%como recurso não documentado .

    Abaixo está o script que irá ajudá-lo :

    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
    

    Consulte também esta excelente postagem no blog: O curioso caso do impasse duvidoso e do bloqueio não tão lógico

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

    Desculpe, já estava trabalhando nessa resposta e prestes a postar quando apareceu a outra. Adicionando como wiki da comunidade apenas porque é uma abordagem ligeiramente diferente e adiciona um pouco de outras informações.

    O 543066506c7cé essencialmente um hash da chave primária e você pode recuperar essa linha (e potencialmente qualquer linha com uma colisão de hash) usando este SQL dinâmico:

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

    Você pode fazer isso sem SQL dinâmico, é claro, mas isso fornece um bom modelo para um trecho ou procedimento armazenado onde você pode simplesmente inserir os valores, se isso for algo que você soluciona muito. (Você também pode parametrizar o nome da tabela e também criar a análise da string KEY: para determinar tudo para você dinamicamente, mas achei que isso poderia estar fora do escopo desta postagem.)

    • 6

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve