【问题标题】:Deadlocks - Finding full SQL statement from deadlock report死锁 - 从死锁报告中查找完整的 SQL 语句
【发布时间】:2021-09-09 10:11:22
【问题描述】:

我有一个针对导致死锁的 SQL Server 2016 数据库运行的应用程序。

死锁图显示了底层对象的 Objectid 和对象名称。它还提供了截断的 SQL 语句。

但是,有些语句非常大,超出了<inputbuf> 实体的 XML 死锁报告中的 1024 个字符限制。我希望能够查看这些锁中涉及的完整语句,以便重现和调试问题。

有没有办法可以增加这个限制,或者有没有办法在给定死锁图中包含的事务描述符的情况下找到完整的 SQL 语句?

【问题讨论】:

    标签: sql-server database-deadlocks


    【解决方案1】:

    如果您使用存储过程等代码对象,您可以使用第三方工具轻松找到它们。 过去为我节省了大量时间的一些免费的。 SSMS 的免费插件。

    或者你可以通过这段代码找到 -

    -- =============================================
    -- Author:      Sharon
    -- Create date: 12/10/2014
    -- Description: FindObject
    -- =============================================
    ALTER PROCEDURE [dbo].[usp_FindObject]
        @Text         NVARCHAR(4000),
        @DatabaseName sysname,
        @Table        BIT = 1,
        @Column       BIT = 1,
        @View         BIT = 1,
        @Function     BIT = 1,
        @Procedure    BIT = 1,
        @Trigger      BIT = 1,
        @Constreint   BIT = 1,
        @Job          BIT = 0,
        @ReportServer BIT = 0,
        @IsExactMatch BIT = 0
    AS
    BEGIN
        SET NOCOUNT ON;
    
    
        DECLARE @IsAllDatabases BIT = 0;
        DECLARE @Print NVARCHAR(2048) = N'';
        DECLARE @cmd NVARCHAR(MAX) = N'';
    
    
    
        IF @Text IS NULL
            RAISERROR('Insert text to look for!', 16, 1);
    
        IF @IsExactMatch IS NULL
            SET @IsExactMatch = 0;
        IF IIF(@Table IS NULL, 0, @Table) + IIF(@Column IS NULL, 0, @Column) + IIF(@View IS NULL, 0, @View)
           + IIF(@Function IS NULL, 0, @Function) + IIF(@Procedure IS NULL, 0, @Procedure)
           + IIF(@Trigger IS NULL, 0, @Trigger) + IIF(@Constreint IS NULL, 0, @Constreint) > 0
        BEGIN
            IF NOT EXISTS (   SELECT    TOP (1)  1
                              FROM      sys.databases
                              WHERE     name = @DatabaseName)
            BEGIN
                SET @IsAllDatabases = 1;
                CREATE TABLE #DBResult
                     (   [Database Name] sysname       NULL,
                         [Object Schema] sysname       NULL,
                         [Object Name]   sysname       NULL,
                         [Object Type]   sysname       NULL,
                         [TEXT Location] NVARCHAR(MAX) NULL,
                         [Position]      NVARCHAR(1000)
                     );
                DECLARE curDatabases CURSOR LOCAL FAST_FORWARD READ_ONLY FOR 
                SELECT  d.name
                FROM    master.sys.databases d
                WHERE   d.state = 0 --ONLINE
                        AND d.database_id > 4
                        AND HAS_DBACCESS(d.name) = 1  -- Have access
                        AND DATABASEPROPERTYEX(d.name, 'Updateability') = 'READ_WRITE'
                        AND NOT EXISTS
                          (
                            SELECT  TOP (1) 1 
                            FROM    sys.dm_hadr_database_replica_states AS drs 
                                    INNER JOIN sys.availability_replicas AS ar ON ar.replica_id = drs.replica_id
                                    INNER JOIN sys.dm_hadr_availability_group_states ags ON ags.group_id = ar.group_id
                              WHERE drs.database_id = d.database_id
                                    AND ar.secondary_role_allow_connections = 0
                                    AND ags.primary_replica <> CONVERT(sysname, SERVERPROPERTY('ServerName'))
                          );
            END;
            ELSE
            BEGIN
                
                DECLARE curDatabases CURSOR LOCAL FAST_FORWARD READ_ONLY FOR 
                SELECT  d.name
                FROM    master.sys.databases d
                WHERE   d.state = 0 --ONLINE
                        AND d.database_id > 4
                        AND HAS_DBACCESS(d.name) = 1  -- Have access
                        AND DATABASEPROPERTYEX(d.name, 'Updateability') = 'READ_WRITE'
                        AND NOT EXISTS
                          (
                            SELECT  TOP (1) 1 
                            FROM    sys.dm_hadr_database_replica_states AS drs 
                                    INNER JOIN sys.availability_replicas AS ar ON ar.replica_id = drs.replica_id
                                    INNER JOIN sys.dm_hadr_availability_group_states ags ON ags.group_id = ar.group_id
                              WHERE drs.database_id = d.database_id
                                    AND ar.secondary_role_allow_connections = 0
                                    AND ags.primary_replica <> CONVERT(sysname, SERVERPROPERTY('ServerName'))
                          )
                        AND d.name = @DatabaseName;
                CREATE TABLE #Result
                     (
                         [Object Schema] sysname       NULL,
                         [Object Name]   sysname       NULL,
                         [Object Type]   sysname       NULL,
                         [TEXT Location] NVARCHAR(MAX) NULL,
                         [Position]      NVARCHAR(1000)
                     );
            END
                -- Table names
                IF @Table = 1
                BEGIN
    
    
    
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
                    SET @cmd = CONCAT(IIF(@DatabaseName IS NOT NULL,N'USE [' + @DatabaseName + '];',N''),N'
    INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'TABLE_SCHEMA  AS [Object Schema]
            ,TABLE_NAME    AS [Object Name]
            ,TABLE_TYPE    AS [Object Type]
            ,''Table Name''  AS [TEXT Location]
            ,NULL
    FROM    INFORMATION_SCHEMA.TABLES
    WHERE   TABLE_TYPE = N''BASE TABLE''
            AND  TABLE_NAME LIKE ''%''+@Text+''%''');
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Table on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                    
                END;
    
                --Column names| computed_columns
                IF @Column = 1
                BEGIN
    
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(IIF(@DatabaseName IS NOT NULL,N'USE [' + @DatabaseName + '];',N''),N'
    INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'TABLE_SCHEMA AS [Object Schema]
            ,TABLE_NAME   AS [Object Name]
            ,''COLUMN''      AS [Object Type]
            ,COLUMN_NAME AS [TEXT Location]
            ,NULL
    FROM  INFORMATION_SCHEMA.COLUMNS
    WHERE COLUMN_NAME LIKE ''%''+@Text+''%''
    UNION ALL 
    
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,o.type_desc       AS [Object Type]
            ,C.definition AS [TEXT Location]
            ,NULL
    FROM    sys.computed_columns C
            INNER JOIN sys.objects o ON C.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   C.definition Like ''%''+@Text+''%''
    ')              ;
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Column on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
    
                --PROCEDURE
                IF @Procedure = 1
                BEGIN
                
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(
                                   N'INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,''PROCEDURE'' AS [Object Type]
            ,m.definition AS [TEXT Location]
            ,SUBSTRING(m.definition,PATINDEX(''%''+@Text+''%'',m.definition),100)
    FROM    sys.sql_modules m 
            INNER JOIN sys.objects o ON m.object_id=o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   m.definition Like ''%''+@Text+''%''
            and o.type = ''P''');
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Procedure on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
    
    
                -- FUNCTION
                IF @Function = 1
                BEGIN
    
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(
                                   N'INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,''FUNCTION('' + o.type + '')'' COLLATE SQL_Latin1_General_CP1_CI_AS AS [Object Type]
            ,m.definition AS [TEXT Location]
            ,SUBSTRING(m.definition,PATINDEX(''%''+@Text+''%'',m.definition),100)
    FROM    sys.sql_modules m 
            INNER JOIN sys.objects o ON m.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   m.definition Like ''%''+@Text+''%''
            and o.type in (''FN'',''AF'',''FS'',''FT'',''IF'',''TF'')');
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Function on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
                -- Trigger
                IF @Trigger = 1
                BEGIN
                
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(
                                   N'INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,''FUNCTION('' + o.type + '')'' COLLATE SQL_Latin1_General_CP1_CI_AS AS [Object Type]
            ,m.definition AS [TEXT Location]
            ,SUBSTRING(m.definition,PATINDEX(''%''+@Text+''%'',m.definition),100)
    FROM    sys.sql_modules m 
            INNER JOIN sys.objects o ON m.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   m.definition Like ''%''+@Text+''%''
            and o.type = ''TR''');
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Trigger on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
                --View
                IF @View = 1
                BEGIN
                
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(
                                   N'INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,o.type_desc COLLATE SQL_Latin1_General_CP1_CI_AS AS [Object Type]
            ,m.definition AS [TEXT Location]
            ,SUBSTRING(m.definition,PATINDEX(''%''+@Text+''%'',m.definition),100)
    FROM    sys.sql_modules m 
            INNER JOIN sys.objects o ON m.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   m.definition Like ''%''+@Text+''%''
            and o.type = ''v''');
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search View on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
    
                --default_constraints| check_constraints
                IF @Constreint = 1
                BEGIN
                
                    OPEN curDatabases;
    
                    FETCH NEXT FROM curDatabases INTO @DatabaseName;
    
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
    
                    SET @cmd = CONCAT(
                                   N'INSERT #',IIF(@IsAllDatabases = 1,'DB',''),'Result
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,o.type_desc       AS [Object Type]
            ,D.definition AS [TEXT Location]
            ,SUBSTRING(D.definition,PATINDEX(''%''+@Text+''%'',D.definition),100)
    FROM    sys.default_constraints D
            INNER JOIN sys.objects o ON D.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   D.definition Like ''%''+@Text+''%''
    UNION ALL 
    SELECT  ',IIF(@IsAllDatabases = 1,'DB_NAME(),',''),'s.name AS [Object Schema]
            ,o.name       AS [Object Name]
            ,o.type_desc       AS [Object Type]
            ,C.definition AS [TEXT Location]
            ,SUBSTRING(D.definition,PATINDEX(''%''+@Text+''%'',C.definition),100)
    FROM    sys.check_constraints C
            INNER JOIN sys.objects o ON C.object_id = o.object_id
            INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
    WHERE   C.definition Like ''%''+@Text+''%''');
    
                        EXEC sp_executesql @cmd, N'@Text nvarchar(4000)', @Text = @Text;
                        SET @Print = CONCAT('Search Constreint on ',@DatabaseName,' complete.');
                        RAISERROR (@Print, 10, 1) WITH NOWAIT;
    
                        FETCH NEXT FROM curDatabases INTO @DatabaseName;
                    END
    
                    CLOSE curDatabases;
                END;
    
    
                
                IF OBJECT_ID('tempdb..#DBResult') IS NOT NULL
                BEGIN
                    SELECT  *
                    FROM    #DBResult
                    WHERE   @IsExactMatch = 0
                            OR (@IsExactMatch = 1 AND [Object Name] = @Text);
                    DROP TABLE #DBResult;
                END 
                IF OBJECT_ID('tempdb..#Result') IS NOT NULL
                BEGIN
                    SELECT  *
                    FROM    #Result
                    WHERE   @IsExactMatch = 0
                            OR (@IsExactMatch = 1 AND [Object Name] = @Text);
                    DROP TABLE #Result;
                END
    
            END;
        END;
        -- Job
        IF @Job = 1
        BEGIN
            DECLARE @PreviewTextSize INT = 100;
    
            SELECT  'Job Steps'                AS SearchType,
                    j.[name]                   AS [Job Name],
                    s.step_id                  AS [Step #],
                    REPLACE(
                        REPLACE(
                            SUBSTRING(s.command, CHARINDEX(@Text, s.command) - @PreviewTextSize / 2, @PreviewTextSize),
                            CHAR(13) + CHAR(10),
                            ''),
                        @Text,
                        '***' + @Text + '***') AS Command
            FROM    msdb.dbo.sysjobs                j
                    INNER JOIN msdb.dbo.sysjobsteps s ON j.job_id = s.job_id
            WHERE   s.command LIKE '%' + @Text + '%';
        END;
        -- SSRS
        IF @ReportServer = 1
        BEGIN
            IF EXISTS (SELECT TOP (1) 1 FROM sys.databases WHERE name = 'ReportServer')
            BEGIN;
                WITH cte AS
                    (
                    --gets the RDL; note the double convert.
                    SELECT  [Path],
                            [Name]                                         AS Report_Name,
                            CONVERT(XML, CONVERT(VARBINARY(MAX), Content)) AS rdl
                    FROM    ReportServer.dbo.Catalog)
                SELECT      LEFT([Path], LEN([Path]) - CHARINDEX('/', REVERSE([Path])) + 1)           AS Report_Path,
                            Report_Name,
                            T1.N.value('@Name', 'nvarchar(128)')                                      AS DataSetName,
                            T2.N.value('(*:DataSourceName/text())[1]', 'nvarchar(128)')               AS DataSourceName,
                            ISNULL(T2.N.value('(*:CommandType/text())[1]', 'nvarchar(128)'), 'T-SQL') AS CommandType,
                            T2.N.value('(*:CommandText/text())[1]', 'nvarchar(max)')                  AS CommandText
                INTO        #SSRS
                FROM        cte                                                       AS T
                            CROSS APPLY T.rdl.nodes('/*:Report/*:DataSets/*:DataSet') AS T1(N)
                            CROSS APPLY T1.N.nodes('*:Query') AS T2(N)
                ORDER BY    Report_Path,
                            Report_Name,
                            DataSetName,
                            DataSourceName,
                            CommandType,
                            CommandText;
    
                SELECT  *
                FROM    #SSRS
                WHERE   CommandText LIKE '%' + @Text + '%';
            END;
            
        DEALLOCATE curDatabases;
    END;
    

    但是,如果您与 EFNhibernate 合作,您将处于困境中

    【讨论】:

    • 谢谢你,但我实际上是在寻找导致死锁的完整 SQL 语句(而不是数据库中的对象)。在 Oracle 中,这可能是通过搜索提供的会话 SQL_ID 获得的 SQL_Text。我怀疑“事务描述符”是 SQL Server 对 SQL_ID 的替代品,但我找不到从中提取任何信息的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 2018-12-23
    • 1970-01-01
    • 2015-04-03
    相关资源
    最近更新 更多