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


USE msdb;
SET NOCOUNT ON;

DECLARE @DatabaseName sysname = N'myNewVasya';
DECLARE @StartStoppedAgents bit = 1; -- 0 = только диагностика

/* 1. Состояние SQL Server Agent */
BEGIN TRY
    SELECT
        servicename,
        status_desc,
        startup_type_desc,
        last_startup_time
    FROM sys.dm_server_services
    WHERE servicename LIKE N'SQL Server Agent%';
END TRY
BEGIN CATCH
    SELECT N'Проверка службы' AS stage, ERROR_MESSAGE() AS errorMessage;
END CATCH;

/* 2. Находим задания.
   Отбираем Log Reader и Distribution, связанные с указанной БД. */
IF OBJECT_ID(N'tempdb..#ReplicationJobs') IS NOT NULL
    DROP TABLE #ReplicationJobs;

SELECT DISTINCT
    j.job_id,
    j.name AS jobName,
    c.name AS categoryName,
    j.enabled
INTO #ReplicationJobs
FROM dbo.sysjobs AS j
JOIN dbo.syscategories AS c
    ON c.category_id = j.category_id
WHERE c.name IN (N'REPL-Distribution', N'REPL-LogReader')
  AND
  (
      CHARINDEX(@DatabaseName, j.name) > 0
      OR EXISTS
      (
          SELECT 1
          FROM dbo.sysjobsteps AS s
          WHERE s.job_id = j.job_id
            AND CHARINDEX(@DatabaseName, s.command) > 0
      )
  );

DECLARE @AgentSessionId int =
    (SELECT MAX(session_id) FROM dbo.syssessions);

SELECT
    N'ДО ЗАПУСКА' AS stage,
    j.jobName,
    j.categoryName,
    j.enabled,
    a.start_execution_date,
    a.stop_execution_date,
    CASE
        WHEN a.start_execution_date IS NOT NULL
         AND a.stop_execution_date IS NULL
            THEN N'RUNNING'
        ELSE N'NOT RUNNING'
    END AS agentState
FROM #ReplicationJobs AS j
LEFT JOIN dbo.sysjobactivity AS a
    ON a.job_id = j.job_id
   AND a.session_id = @AgentSessionId
ORDER BY j.categoryName, j.jobName;

/* 3. Последние сообщения выбранных заданий */
SELECT TOP (60)
    j.jobName,
    h.step_id,
    h.step_name,
    h.run_date,
    h.run_time,
    h.run_duration,
    CASE h.run_status
        WHEN 0 THEN N'FAILED'
        WHEN 1 THEN N'SUCCEEDED'
        WHEN 2 THEN N'RETRY'
        WHEN 3 THEN N'CANCELED'
        WHEN 4 THEN N'IN PROGRESS'
    END AS runStatus,
    h.message
FROM dbo.sysjobhistory AS h
JOIN #ReplicationJobs AS j
    ON j.job_id = h.job_id
ORDER BY h.instance_id DESC;

/* 4. Последние ошибки распространителя.
   Это общий журнал: ошибки могут относиться к другим публикациям. */
IF DB_ID(N'distribution') IS NOT NULL
BEGIN
    BEGIN TRY
        EXEC sys.sp_executesql N'
            SELECT TOP (30)
                [time],
                error_code,
                error_text
            FROM distribution.dbo.MSrepl_errors
            ORDER BY [time] DESC, id DESC;';
    END TRY
    BEGIN CATCH
        SELECT
            N'Ошибки distribution' AS stage,
            ERROR_MESSAGE() AS errorMessage;
    END CATCH;
END
ELSE
BEGIN
    SELECT N'База distribution здесь не найдена. Журнал ошибок нужно '
         + N'проверить на распространителе либо в БД распространения '
         + N'с другим именем.' AS diagnosticMessage;
END;

/* 5. Запускаем только остановленные включённые задания.
   Сначала Log Reader, затем Distribution.
   Отключённые задания автоматически не включаем. */
DECLARE
    @JobId uniqueidentifier,
    @JobName sysname;

DECLARE agent_cursor CURSOR LOCAL FAST_FORWARD FOR
    SELECT job_id, jobName
    FROM #ReplicationJobs
    WHERE enabled = 1
    ORDER BY
        CASE categoryName
            WHEN N'REPL-LogReader' THEN 0
            ELSE 1
        END,
        jobName;

IF @StartStoppedAgents = 1
BEGIN
    OPEN agent_cursor;
    FETCH NEXT FROM agent_cursor INTO @JobId, @JobName;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Проверяем актуальный сеанс перед каждым запуском.
        SELECT @AgentSessionId = MAX(session_id)
        FROM dbo.syssessions;

        IF NOT EXISTS
        (
            SELECT 1
            FROM dbo.sysjobactivity
            WHERE job_id = @JobId
              AND session_id = @AgentSessionId
              AND start_execution_date IS NOT NULL
              AND stop_execution_date IS NULL
        )
        BEGIN
            BEGIN TRY
                EXEC dbo.sp_start_job @job_id = @JobId;

                SELECT
                    @JobName AS jobName,
                    N'Команда запуска принята' AS actionResult;
            END TRY
            BEGIN CATCH
                SELECT
                    @JobName AS jobName,
                    N'Ошибка запуска' AS actionResult,
                    ERROR_MESSAGE() AS errorMessage;
            END CATCH;
        END
        ELSE
        BEGIN
            SELECT
                @JobName AS jobName,
                N'Уже работает — без изменений' AS actionResult;
        END;

        FETCH NEXT FROM agent_cursor INTO @JobId, @JobName;
    END;

    CLOSE agent_cursor;

    -- Небольшая пауза для появления результата запуска.
    WAITFOR DELAY '00:00:05';
END;

DEALLOCATE agent_cursor;

/* 6. Состояние после запуска */
SELECT @AgentSessionId = MAX(session_id)
FROM dbo.syssessions;

SELECT
    N'ИТОГ' AS stage,
    j.jobName,
    j.categoryName,
    currentJob.enabled,
    a.start_execution_date,
    a.stop_execution_date,
    CASE
        WHEN a.start_execution_date IS NOT NULL
         AND a.stop_execution_date IS NULL
            THEN N'RUNNING'
        ELSE N'NOT RUNNING'
    END AS agentState,
    lastHistory.run_date AS lastHistoryDate,
    lastHistory.run_time AS lastHistoryTime,
    lastHistory.message AS lastHistoryMessage
FROM #ReplicationJobs AS j
JOIN dbo.sysjobs AS currentJob
    ON currentJob.job_id = j.job_id
LEFT JOIN dbo.sysjobactivity AS a
    ON a.job_id = j.job_id
   AND a.session_id = @AgentSessionId
OUTER APPLY
(
    SELECT TOP (1)
        h.run_date,
        h.run_time,
        h.message
    FROM dbo.sysjobhistory AS h
    WHERE h.job_id = j.job_id
    ORDER BY h.instance_id DESC
) AS lastHistory
ORDER BY j.categoryName, j.jobName;

IF NOT EXISTS (SELECT 1 FROM #ReplicationJobs)
BEGIN
    SELECT N'Задания не найдены. Проверьте сервер выполнения: '
         + N'Log Reader находится на распространителе, '
         + N'Distribution для pull-подписки — на подписчике.'
         AS diagnosticMessage;
END;

SELECT
    jobName,
    N'Задание отключено. Автоматический запуск пропущен.'
        AS diagnosticMessage
FROM #ReplicationJobs
WHERE enabled = 0;

DROP TABLE #ReplicationJobs;