Published on

March 25, 2024

Автоматизация выявления проблемных подсказок NOLOCK в SQL Server

В предыдущей статье мы обсудили, как использовать шаблон Visitor для ручного выявления проблемных ситуаций, когда подсказки NOLOCK применяются к цели оператора UPDATE или DELETE в SQL Server. Однако такой ручной подход не масштабируется при работе с большим количеством операторов во всей среде. В этой статье мы рассмотрим решение для автоматизации сбора и выявления этих проблемных ситуаций.

Получение модулей сопоставления шаблонов

Чтобы получить все процедуры и триггеры из заданной базы данных, мы можем установить строку подключения, извлечь все модули, соответствующие нашему шаблону, а затем передать их через шаблон Visitor. Давайте создадим новую базу данных и несколько простых хранимых процедур для демонстрации:

CREATE DATABASE BadNOLOCKs;
GO

USE BadNOLOCKS;
GO

CREATE PROCEDURE dbo.p1_false AS
    UPDATE dbo.x SET i += 1;
    SELECT * FROM dbo.x WITH (NOLOCK);
GO

CREATE PROCEDURE dbo.p2_true AS
    UPDATE x SET i += 1 FROM dbo.x WITH (NOLOCK);
    UPDATE x SET i += 5 FROM dbo.x INNER JOIN dbo.y WITH (NOLOCK) ON x.i = y.i;
GO

CREATE PROCEDURE dbo.p3_true AS
    DELETE q FROM dbo.x AS q WITH (NOLOCK) WHERE EXISTS (SELECT 1 FROM sys.objects);
    DELETE x FROM dbo.x /* WITH (NOLOCK) */ AS x;
GO

После получения процедур и триггеров мы можем улучшить наш код с помощью глобальных переменных и условных операторов, чтобы исключить ложные срабатывания, которые могут пройти через наш фильтр.

Сохранение результатов для запросов

Чтобы отслеживать выявленные ситуации, мы можем сохранить результаты в таблице, которая позволяет нам выполнять запросы к данным. Мы можем создать временную таблицу для сбора результатов из каждой базы данных и добавить дополнительные столбцы для имени базы данных и имени сервера:

CREATE TABLE #Modules (
    ProcedureName nvarchar(512),
    Body nvarchar(max),
    DatabaseName sysname,
    ServerName sysname
);

Затем мы можем изменить наш код для вставки полученных данных в эту временную таблицу:

EXEC master.dbo.sp_ineachdb N'
    INSERT #Modules (
        ProcedureName,
        Body,
        DatabaseName,
        ServerName
    )
    SELECT
        ProcedureName = s.name + N''.'' + o.name + CASE WHEN t.[object_id] IS NOT NULL THEN N'' (триггер для '' + p.name + N'')'' ELSE N'''' END,
        Body = OBJECT_DEFINITION(o.object_id),
        DatabaseName = DB_NAME(),
        ServerName = @@SERVERNAME
    FROM
        sys.objects AS o WITH (NOLOCK)
        INNER JOIN sys.schemas AS s WITH (NOLOCK) ON s.[schema_id] = o.[schema_id]
        LEFT OUTER JOIN sys.triggers AS t WITH (NOLOCK) ON o.[object_id] = t.[object_id]
        LEFT OUTER JOIN sys.objects AS p WITH (NOLOCK) ON t.parent_id = p.[object_id]
    WHERE
        o.[type] IN (N''P'', N''TR'')
        AND (
            LOWER(OBJECT_DEFINITION(o.object_id)) LIKE N''%update%from%nolock%''
            OR LOWER(OBJECT_DEFINITION(o.object_id)) LIKE N''%delete%from%nolock%''
        );
';

Сохраняя результаты в таблице, мы теперь можем писать запросы для получения более краткой и содержательной информации о выявленных ситуациях.

Заключение

В этой статье мы рассмотрели, как автоматизировать выявление проблемных подсказок NOLOCK в SQL Server. Получая модули сопоставления шаблонов из набора серверов и сохраняя результаты в таблице, мы легко можем выполнять запросы к данным для получения более содержательных выводов. Этот автоматизированный подход масштабируем и устраняет необходимость вручной проверки результатов. В следующей части этой серии мы более подробно рассмотрим запросы к сохраненным данным для получения более конкретной информации о выявленных ситуациях.

Дата последнего обновления статьи: 2021-08-03

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.