Getting NULL for Object Name when trying to decode sys.dm_tran_locks.resource_associated_entity_id

  • I am getting a lot of NULL values for object name ([Parent Object] column in SQL below) when querying sys.dm_tran_locks and the resource_type column is OBJECT, PAGE, KEY or RID.

    Here is the SQL I am running:

    SELECT

    DTL.[resource_type] AS [resource type] ,

    DTL.resource_associated_entity_id,

    CASE

    WHEN DTL.[resource_type] IN ( 'DATABASE', 'FILE', 'METADATA' )

    THEN DTL.[resource_type]

    WHEN DTL.[resource_type] = 'OBJECT'

    THEN OBJECT_NAME(DTL.resource_associated_entity_id)

    WHEN DTL.[resource_type] IN ( 'KEY', 'PAGE', 'RID' )

    THEN (SELECT OBJECT_NAME([object_id])

    FROM sys.partitions

    WHERE sys.partitions.[hobt_id] =

    DTL.[resource_associated_entity_id]

    )

    ELSE 'Unidentified'

    END AS [Parent Object]

    FROM

    sys.dm_tran_locks DTL

    Here are some links discussing variations of the query above:

    http://www.simple-talk.com/sql/database-administration/investigating-transactions-using-dynamic-management-objects/

    http://jmkehayias.blogspot.com/2008/12/troubleshooting-locking-in-database.html

    http://www.insidesqlserver.com/companion/QTO_Chapter6code.txt

    I have seen this issue reported here as well:

    http://stackoverflow.com/questions/2957484/strange-values-in-sys-dm-tran-locks-table-resource-associated-entity-id-column

    Anyone know how to reliably get object names from sys.dm_tran_locks?

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • Mario the object_name() function has a second parameter for the database_id;;

    i suspect that's what you need to add;

    try this and confirm it fixes the issue...you'll see all i did was add OBJECT_NAME([object_id],DTL.resource_database_id)

    in my sample, i didn't have any null objects to prove it on my side for testing.

    SELECT

    DTL.[resource_type] AS [resource type] ,

    DTL.resource_associated_entity_id,

    CASE

    WHEN DTL.[resource_type] IN ( 'DATABASE', 'FILE', 'METADATA' )

    THEN DTL.[resource_type]

    WHEN DTL.[resource_type] = 'OBJECT'

    THEN OBJECT_NAME(DTL.resource_associated_entity_id)

    WHEN DTL.[resource_type] IN ( 'KEY', 'PAGE', 'RID' )

    THEN ( SELECT OBJECT_NAME([object_id],DTL.resource_database_id)

    FROM sys.partitions

    WHERE sys.partitions.[hobt_id] =

    DTL.[resource_associated_entity_id]

    )

    ELSE 'Unidentified'

    END AS [Parent Object]

    FROM

    sys.dm_tran_locks DTL

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • The partition_id and object_id are database-specific, they're not server-wide values. sys.partitions is per-database.

    I get the correct names only if I run that in the context of the DB that the locks are in.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Thanks, your suggestion is working.

    Still getting NULLs, but not as many as before:

    SELECT

    DTL.[resource_type] AS [resource type] ,

    DTL.resource_associated_entity_id,

    CASE

    WHEN DTL.[resource_type] IN ( 'DATABASE', 'FILE', 'METADATA' )

    THEN DTL.[resource_type]

    WHEN DTL.[resource_type] = 'OBJECT'

    THEN OBJECT_NAME(DTL.resource_associated_entity_id,DTL.resource_database_id)

    --THEN OBJECT_NAME(DTL.resource_associated_entity_id)

    WHEN DTL.[resource_type] IN ( 'KEY', 'PAGE', 'RID' )

    THEN ( SELECT OBJECT_NAME([object_id],DTL.resource_database_id)

    FROM sys.partitions

    WHERE sys.partitions.[hobt_id] =

    DTL.[resource_associated_entity_id]

    )

    ELSE 'Unidentified'

    END AS [Parent Object]

    FROM

    sys.dm_tran_locks DTL

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • sys.partitions is a per-database view. Not per-server. That join is only a valid one if you're running that in the DB that has the locks.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (8/26/2011)


    sys.partitions is a per-database view. Not per-server. That join is only a valid one if you're running that in the DB that has the locks.

    So is there a way to extract object-name info from sys.dm_tran_locks.resource_associated_entity_id?

    Because sys.dm_tran_locks is instance-wide, not database-specific and therefore so is resource_associated_entity_id.

    This part of the query should still work though:

    ...

    WHEN DTL.[resource_type] = 'OBJECT'

    THEN OBJECT_NAME(DTL.resource_associated_entity_id,DTL.resource_database_id)

    ...

    It looks like this query, which can be found over the place, is actually not entirely correct...

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • Only way I can think of is to loop through all databases in the SQL instance and issue the sys.dm_tran_locks query filtering by resource_database_id.

    Store the intermediate results in a temp table and retrieve the results from the temp table in the end.

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • Or loop through and create a temp table with all of the sys.partitions (partition_id, database_id, object_id, index_id) in it and join to that.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (8/27/2011)


    Or loop through and create a temp table with all of the sys.partitions (partition_id, database_id, object_id, index_id) in it and join to that.

    Good idea, I'll try it both ways and see what works best.

    Thanks!

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • Here is a script that cycles though all databases running the DMV query on each one separately and storing the results into a temp table for final retrieval;

    this is the full DMV query I was working with

    (http://www.simple-talk.com/sql/database-administration/investigating-transactions-using-dynamic-management-objects/):

    SET NOCOUNT ON;

    DECLARE @cnt SMALLINT;

    DECLARE @loopCnt SMALLINT;

    DECLARE @dbName SYSNAME;

    DECLARE @database_id SMALLINT;

    DECLARE @sql NVARCHAR(MAX);

    CREATE TABLE #blocks

    (

    resource_type NVARCHAR(300)

    , parent_object NVARCHAR(300)

    , lock_type NVARCHAR(300)

    , request_status NVARCHAR(300)

    , wait_duration_ms BIGINT

    , wait_type NVARCHAR(300)

    , blocked_session_id SMALLINT

    , blocked_user NVARCHAR(300)

    , blocked_command NVARCHAR(500)

    , blocking_session_id SMALLINT

    , blocking_user NVARCHAR(300)

    , blocking_command NVARCHAR(500)

    , blocking_resource_detail NVARCHAR(1024)

    );

    CREATE TABLE #databases

    (

    database_id SMALLINT

    , dbName SYSNAME

    );

    INSERT INTO #databases

    (

    database_id

    , dbName

    )

    SELECT

    d.database_id

    , d.name

    FROM

    sys.databases d;

    SELECT @cnt = COUNT(*) FROM #databases;

    SET @loopCnt = 1;

    WHILE ( @loopCnt <= @cnt )

    BEGIN

    SELECT

    @database_id = [database_id]

    , @dbName = [dbName]

    FROM #databases

    WHERE [database_id] = @loopCnt;

    SET @sql = '

    USE [' + @dbName + ']; ' + '

    SELECT

    DTL.[resource_type] AS [resource type] ,

    CASE

    WHEN DTL.[resource_type] IN ( ''DATABASE'', ''FILE'', ''METADATA'' )

    THEN DTL.[resource_type]

    WHEN DTL.[resource_type] = ''OBJECT''

    THEN OBJECT_NAME(DTL.resource_associated_entity_id)

    WHEN DTL.[resource_type] IN ( ''KEY'', ''PAGE'', ''RID'')

    THEN ( SELECT OBJECT_NAME([object_id])

    FROM sys.partitions

    WHERE sys.partitions.[hobt_id] =

    DTL.[resource_associated_entity_id]

    )

    ELSE ''Unidentified''

    END AS [Parent Object] ,

    DTL.[request_mode] AS [Lock Type] ,

    DTL.[request_status] AS [Request Status] ,

    DOWT.[wait_duration_ms] AS [wait duration ms] ,

    DOWT.[wait_type] AS [wait type] ,

    DOWT.[session_id] AS [blocked session id] ,

    DES_blocked.[login_name] AS [blocked_user] ,

    LEFT (

    SUBSTRING(dest_blocked.text, DER.statement_start_offset / 2,

    ( CASE WHEN DER.statement_end_offset = -1

    THEN DATALENGTH(dest_blocked.text)

    ELSE DER.statement_end_offset

    END - DER.statement_start_offset ) / 2 ) , 500 )

    AS [blocked_command] ,

    DOWT.[blocking_session_id] AS [blocking session id] ,

    DES_blocking.[login_name] AS [blocking user] ,

    LEFT (DEST_blocking.[text], 500) AS [blocking command] ,

    DOWT.resource_description AS [blocking resource detail]

    FROM

    sys.dm_tran_locks DTL WITH ( NOLOCK )

    INNER JOIN

    sys.dm_os_waiting_tasks DOWT WITH ( NOLOCK )

    ON

    DTL.lock_owner_address = DOWT.resource_address

    INNER JOIN

    sys.[dm_exec_requests] DER WITH ( NOLOCK )

    ON

    DOWT.[session_id] = DER.[session_id]

    INNER JOIN

    sys.dm_exec_sessions DES_blocked WITH ( NOLOCK )

    ON

    DOWT.[session_id] = DES_Blocked.[session_id]

    INNER JOIN

    sys.dm_exec_sessions DES_blocking WITH ( NOLOCK )

    ON

    DOWT.[blocking_session_id] = DES_Blocking.[session_id]

    INNER JOIN

    sys.dm_exec_connections DEC WITH ( NOLOCK )

    ON

    DTL.[request_session_id] = DEC.[most_recent_session_id]

    CROSS APPLY

    sys.dm_exec_sql_text(DEC.[most_recent_sql_handle]) AS DEST_Blocking

    CROSS APPLY

    sys.dm_exec_sql_text(DER.sql_handle) AS DEST_Blocked

    WHERE DTL.[resource_database_id] = ' + CAST ( @database_id AS NVARCHAR );

    INSERT INTO #blocks

    (

    resource_type

    , parent_object

    , lock_type

    , request_status

    , wait_duration_ms

    , wait_type

    , blocked_session_id

    , blocked_user

    , blocked_command

    , blocking_session_id

    , blocking_user

    , blocking_command

    , blocking_resource_detail

    )

    EXEC ( @sql );

    SET @loopCnt = @loopCnt + 1;

    END

    SELECT

    resource_type

    , parent_object

    , lock_type

    , request_status

    , wait_duration_ms

    , wait_type

    , blocked_session_id

    , blocked_user

    , blocked_command

    , blocking_session_id

    , blocking_user

    , blocking_command

    , blocking_resource_detail

    FROM

    #blocks;

    DROP TABLE #databases;

    DROP TABLE #blocks;

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • here I wrote an article about that: http://aiellodba.blogspot.com/2011/08/entendiendo-el-waitresource.html

  • Aiello DBA (8/31/2011)


    here I wrote an article about that: http://aiellodba.blogspot.com/2011/08/entendiendo-el-waitresource.html%5B/quote%5D

    Thanks, I'll take a look.

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • Marios Philippopoulos (8/29/2011)


    Here is a script that cycles though all databases running the DMV query on each one separately and storing the results into a temp table for final retrieval;

    ...

    The above script, cycling through all databases to get the Parent Object, is too slow to be useful for reporting purposes.

    I think I will dump it and focus instead on parsing the information of the sys.dm_os_waiting_tasks.resource_description column (returned as blocking_resource_detail in the above script).

    I'm currently having a problem with this, posted here:

    http://qa.sqlservercentral.com/Forums/Topic1168711-391-1.aspx

    __________________________________________________________________________________
    SQL Server 2016 Columnstore Index Enhancements - System Views for Disk-Based Tables[/url]
    Persisting SQL Server Index-Usage Statistics with MERGE[/url]
    Turbocharge Your Database Maintenance With Service Broker: Part 2[/url]

  • you well come 🙂

Viewing 14 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic. Login to reply