Загрузка данных


USE [replTransVas];
SET NOCOUNT ON;

DECLARE @old_lock_timeout int = @@LOCK_TIMEOUT;
SET LOCK_TIMEOUT 5000;

BEGIN TRY
    IF CONVERT(sysname, SERVERPROPERTY('ServerName'))
       <> N'WIN-5ODCFIGQRP3\SQL2016SQL'
        THROW 50001, N'Неверный экземпляр SQL Server.', 1;

    IF @@TRANCOUNT <> 0
        THROW 50002, N'Запустите блок вне открытой транзакции.', 1;

    DECLARE @obj int = OBJECT_ID(N'dbo.sb_answer', N'U');
    DECLARE @kod int;

    IF @obj IS NULL
        THROW 50003, N'Таблица replTransVas.dbo.sb_answer не найдена.', 1;

    SELECT @kod = column_id
    FROM sys.columns
    WHERE object_id = @obj
      AND name = N'kod';

    IF @kod IS NULL
        THROW 50004, N'Столбец kod не найден.', 1;

    -- 1. Исправляем только подтвержденное отсутствие
    -- действующего нефильтрованного индекса с первым ключом kod.
    IF NOT EXISTS
    (
        SELECT 1
        FROM sys.indexes AS i
        JOIN sys.index_columns AS ic
          ON ic.object_id = i.object_id
         AND ic.index_id = i.index_id
        WHERE i.object_id = @obj
          AND i.type IN (1, 2)
          AND i.is_disabled = 0
          AND i.is_hypothetical = 0
          AND i.has_filter = 0
          AND ic.key_ordinal = 1
          AND ic.column_id = @kod
    )
    BEGIN
        IF EXISTS
        (
            SELECT 1
            FROM sys.indexes
            WHERE object_id = @obj
              AND name = N'IX_sb_answer_kod_repl_fix'
        )
            THROW 50005,
                N'Имя IX_sb_answer_kod_repl_fix уже занято. Требуется проверка существующего индекса.',
                1;

        RAISERROR(
            N'Нет индекса с первым ключом kod. Создаю индекс на подписчике...',
            10, 1
        ) WITH NOWAIT;

        CREATE NONCLUSTERED INDEX [IX_sb_answer_kod_repl_fix]
            ON dbo.sb_answer ([kod])
            WITH (MAXDOP = 1);

        SELECT
            N'01_ACTION' AS section,
            N'CREATED_INDEX' AS result,
            N'IX_sb_answer_kod_repl_fix' AS index_name;
    END
    ELSE
    BEGIN
        SELECT
            N'01_ACTION' AS section,
            N'INDEX_ALREADY_EXISTS' AS result,
            N'Дополнительный индекс не создавался.' AS details;
    END;

    -- 2. Состав индексов: одна строка на столбец индекса.
    SELECT
        N'02_INDEXES' AS section,
        i.name AS index_name,
        i.type_desc,
        i.is_unique,
        i.is_primary_key,
        i.is_disabled,
        i.has_filter,
        i.filter_definition,
        c.name AS column_name,
        ic.key_ordinal,
        ic.is_included_column
    FROM sys.indexes AS i
    LEFT JOIN sys.index_columns AS ic
      ON ic.object_id = i.object_id
     AND ic.index_id = i.index_id
    LEFT JOIN sys.columns AS c
      ON c.object_id = ic.object_id
     AND c.column_id = ic.column_id
    WHERE i.object_id = @obj
    ORDER BY i.index_id, ic.index_column_id;

    -- 3. Статистика индексов, используемых для поиска по kod.
    SELECT
        N'03_KOD_STATISTICS' AS section,
        i.name AS index_name,
        p.last_updated,
        p.rows,
        p.rows_sampled,
        p.modification_counter
    FROM sys.indexes AS i
    JOIN sys.index_columns AS ic
      ON ic.object_id = i.object_id
     AND ic.index_id = i.index_id
    OUTER APPLY sys.dm_db_stats_properties(
        i.object_id, i.index_id
    ) AS p
    WHERE i.object_id = @obj
      AND i.type IN (1, 2)
      AND ic.key_ordinal = 1
      AND ic.column_id = @kod;

    -- 4. Триггеры и накопленное время их выполнения.
    -- Ничего автоматически не отключаем:
    -- триггер может содержать необходимую бизнес-логику.
    SELECT
        N'04_TRIGGERS' AS section,
        t.name AS trigger_name,
        t.is_disabled,
        t.is_not_for_replication,
        ts.execution_count,
        CAST(
            ts.total_worker_time / 1000.0
            / NULLIF(ts.execution_count, 0)
            AS decimal(18, 3)
        ) AS average_cpu_ms,
        CAST(
            ts.total_elapsed_time / 1000.0
            / NULLIF(ts.execution_count, 0)
            AS decimal(18, 3)
        ) AS average_elapsed_ms,
        m.definition AS trigger_definition
    FROM sys.triggers AS t
    LEFT JOIN sys.sql_modules AS m
      ON m.object_id = t.object_id
    LEFT JOIN sys.dm_exec_trigger_stats AS ts
      ON ts.database_id = DB_ID()
     AND ts.object_id = t.object_id
    WHERE t.parent_id = @obj;

    -- 5. Текущий запрос агента и его кешированный план.
    -- session_id определяется заново: номер 58 не зашит.
    SELECT
        N'05_CURRENT_REPLICATION_REQUEST' AS section,
        s.session_id,
        r.status,
        r.command,
        r.blocking_session_id,
        r.wait_type,
        r.wait_time,
        r.cpu_time,
        r.total_elapsed_time,
        r.logical_reads,
        r.reads,
        r.writes,
        OBJECT_SCHEMA_NAME(txt.objectid, txt.dbid) AS procedure_schema,
        OBJECT_NAME(txt.objectid, txt.dbid) AS procedure_name,
        SUBSTRING(
            txt.text,
            r.statement_start_offset / 2 + 1,
            (
                CASE r.statement_end_offset
                    WHEN -1 THEN DATALENGTH(txt.text)
                    ELSE r.statement_end_offset
                END - r.statement_start_offset
            ) / 2 + 1
        ) AS current_statement,
        qp.query_plan
    FROM sys.dm_exec_sessions AS s
    JOIN sys.dm_exec_requests AS r
      ON r.session_id = s.session_id
    OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS txt
    OUTER APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp
    WHERE r.database_id = DB_ID()
      AND s.program_name = N'WIN-5ODCFIGQRP3_myNewVasya_V3Trans';

    SET LOCK_TIMEOUT @old_lock_timeout;
END TRY
BEGIN CATCH
    SET LOCK_TIMEOUT @old_lock_timeout;
    THROW;
END CATCH;

-- 6. Состояние доставки после проверки/исправления.
SELECT TOP (5)
    N'06_DISTRIBUTION_HISTORY' AS section,
    h.[time],
    h.runstatus,
    h.delivered_commands,
    h.current_delivery_rate,
    h.comments
FROM distribution.dbo.MSdistribution_agents AS a
JOIN distribution.dbo.MSdistribution_history AS h
  ON h.agent_id = a.id
WHERE a.publisher_db = N'myNewVasya'
  AND a.publication = N'V3Trans'
  AND a.subscriber_db = N'replTransVas'
ORDER BY h.[time] DESC;