Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Автоматично събиране на данни за изпълнени задачи в MS SQL Server

Въведение

Важно е администраторът на база данни да знае какви задачи и как са били изпълнени. За да опростите този процес, по-добре е да го автоматизирате, вместо да го извършвате ръчно.

В тази статия ще анализирам на конкретен пример как автоматично да събирам данни за изпълнени задачи на SQL Server Agent.

Решение

Алгоритъм:

  1. Създайте екземпляр, за да изберете задачи:
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE view [srv].[vJobRunShortInfo] as
    SELECT sj.[job_id] as Job_GUID
          ,j.name as Job_Name
          ,case sj.[last_run_outcome]
            when 0 then 'Error'
            when 1 then 'Successful'
            when 3 then 'Canceled'
            else case when sj.[last_run_date] is not null and len(sj.[last_run_date])=8 then 'Inconsistent state'
                    else NULL
                    end
           end as LastFinishRunState
          ,sj.[last_run_outcome] as LastRunOutcome
          ,case when sj.[last_run_date] is not null and len(sj.[last_run_date])=8 then
            DATETIMEFROMPARTS(
            substring(cast(sj.[last_run_date] as nvarchar(255)),1,4),
            substring(cast(sj.[last_run_date] as nvarchar(255)),5,2),
            substring(cast(sj.[last_run_date] as nvarchar(255)),7,2),
            case when len(cast(sj.[last_run_time] as nvarchar(255)))>=5 
            then substring(cast(sj.[last_run_time] as nvarchar(255)),1,len(cast(sj.[last_run_time] as nvarchar(255)))-4)
              else 0
              end,
            case when len(right(cast(sj.[last_run_time] as nvarchar(255)),4))>=4 
            then substring(right(cast(sj.[last_run_time] as nvarchar(255)),4),1,2)
            when len(right(cast(sj.[last_run_time] as nvarchar(255)),4))=3  
            then substring(right(cast(sj.[last_run_time] as nvarchar(255)),4),1,1)
               else 0
               end,
            right(cast(sj.[last_run_duration] as nvarchar(255)),2),
                                0
                            )
           else NULL
           end as LastDateTime
           ,case when len(cast(sj.[last_run_duration] as nvarchar(255)))>5 
           then substring(cast(sj.[last_run_duration] as nvarchar(255)),1,len(cast(sj.[last_run_duration] as nvarchar(255)))-4)
                when len(cast(sj.[last_run_duration] as nvarchar(255)))=5 
           then '0'+substring(cast(sj.[last_run_duration] as nvarchar(255)),1,len(cast(sj.[last_run_duration] as nvarchar(255)))-4)
                else '00'
           end
           +':'
           +case when len(cast(sj.[last_run_duration] as nvarchar(255)))>=4 then substring(right(cast(sj.[last_run_duration] as nvarchar(255)),4),1,2)
                 when len(cast(sj.[last_run_duration] as nvarchar(255)))=3  then '0'+substring(right(cast(sj.[last_run_duration] as nvarchar(255)),4),1,1)
                 else '00'
           end
           +':'
           +case when len(cast(sj.[last_run_duration] as nvarchar(255)))>=2
            then substring(right(cast(sj.[last_run_duration] as nvarchar(255)),2),1,2)
                 when len(cast(sj.[last_run_duration] as nvarchar(255)))=2  
            then '0'+substring(right(cast(sj.[last_run_duration] as nvarchar(255)),2),1,1)
                 else '00'
           end as [LastRunDurationString]
          ,sj.last_run_duration as LastRunDurationInt
          ,sj.[last_outcome_message] as LastOutcomeMessage
          ,j.enabled as [Enabled]
      FROM [msdb].[dbo].[sysjobservers] as sj
      inner join msdb.dbo.sysjobs_view as j on j.job_id=sj.job_id;
    
    GO

    За да направите това, използвайте екземплярите sysjobservers и sysjobs_view.

  2. Създайте таблица за съхраняване на избрани данни:
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [srv].[ShortInfoRunJobs](
        [Job_GUID] [uniqueidentifier] NOT NULL,
        [Job_Name] [nvarchar](255) NOT NULL,
        [LastFinishRunState] [nvarchar](255) NULL,
        [LastDateTime] [datetime] NOT NULL,
        [LastRunDurationString] [nvarchar](255) NULL,
        [LastRunDurationInt] [int] NULL,
        [LastOutcomeMessage] [nvarchar](255) NULL,
        [LastRunOutcome] [tinyint] NOT NULL,
        [Server] [nvarchar](255) NOT NULL,
        [InsertUTCDate] [datetime] NOT NULL,
        [ID] [int] IDENTITY(1,1) NOT NULL,
     CONSTRAINT [PK_ShortInfoRunJobs] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    ALTER TABLE [srv].[ShortInfoRunJobs] ADD  CONSTRAINT [DF_ShortInfoRunJobs_InsertUTCDate]  DEFAULT (getutcdate()) FOR [InsertUTCDate]
    GO
  3. Създайте задача в агента на SQL Server и получете информация за онези задачи, които са били изпълнявани дълго време (повече от 30 секунди) или не са били завършени. Трябва да съберете тази информация за последните два дни:
    USE [DATABASE_NAME];
    GO
    
    truncate table [srv].[ShortInfoRunJobs];
    
    INSERT INTO [srv].[ShortInfoRunJobs]
               ([Job_GUID]
               ,[Job_Name]
               ,[LastFinishRunState]
               ,[LastDateTime]
               ,[LastRunDurationString]
               ,[LastRunDurationInt]
               ,[LastOutcomeMessage]
               ,[LastRunOutcome]
               ,[Server])
        SELECT [Job_GUID]
              ,[Job_Name]
              ,[LastFinishRunState]
              ,[LastDateTime]
              ,[LastRunDurationString]
              ,[LastRunDurationInt]
              ,[LastOutcomeMessage]
              ,LastRunOutcome
              ,@@SERVERNAME
          FROM [srv].[vJobRunShortInfo]
          where [Enabled]=1
          and ([LastRunOutcome]=0
          or [LastRunDurationInt]>=30)
          and LastDateTime>=DateAdd(day,-2,getdate());
    GO

    Тук можете да зададете филтър за премахване на всички ненужни задачи. Например тези задачи, които се отнасят до репликация, тъй като отнема много повече време за завършване.

Генерирайте HTML-отчет, за да го изпратите на имейла на администраторите:

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [srv].[GetHTMLTableShortInfoRunJobs]
    @body nvarchar(max) OUTPUT
AS
BEGIN
    /*
        generates an HTML-code for the tables of completed tasks
    */
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    declare @tbl table (
                        Job_GUID                uniqueidentifier
                        ,Job_Name               nvarchar(255)
                        ,LastFinishRunState     nvarchar(255)
                        ,LastDateTime           datetime
                        ,LastRunDurationString  nvarchar(255)
                        ,LastOutcomeMessage     nvarchar(max)
                        ,[Server]               nvarchar(255)
                        ,ID                     int identity(1,1)
                       );

    declare
    @Job_GUID               uniqueidentifier
    ,@Job_Name              nvarchar(255)
    ,@LastFinishRunState    nvarchar(255)
    ,@LastDateTime          datetime
    ,@LastRunDurationString nvarchar(255)
    ,@LastOutcomeMessage    nvarchar(max)
    ,@Server                nvarchar(255)
    ,@ID                    int;

    insert into @tbl(
                        Job_GUID
                        ,Job_Name
                        ,LastFinishRunState
                        ,LastDateTime
                        ,LastRunDurationString
                        ,LastOutcomeMessage
                        ,[Server]
                    )
            select      Job_GUID
                        ,Job_Name
                        ,LastFinishRunState
                        ,LastDateTime
                        ,LastRunDurationString
                        ,LastOutcomeMessage
                        ,[Server]
            from    srv.ShortInfoRunJobs
            --order by LastRunDurationInt desc;

    if(exists(select top(1) 1 from @tbl))
    begin
        set @body='When analyzing these tasks execution, I have found out the tasks that either have failed with an error,
        or, it has taken more than 30 seconds for their execution :<br><br>'+'<TABLE BORDER=5>';

        set @[email protected]+'<TR>';

        set @[email protected]+'<TD>';
        set @[email protected]+'№ p/p';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'GUID';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'TASK';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'STATUS';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'DATE AND TIME';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'DURATION';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'MESSAGE';
        set @[email protected]+'</TD>';

        set @[email protected]+'<TD>';
        set @[email protected]+'SERVER';
        set @[email protected]+'</TD>';

        set @[email protected]+'</TR>';

        while((select top 1 1 from @tbl)>0)
        begin
            set @[email protected]+'<TR>';

            select top 1
            @ID                     =   [ID]
            ,@Job_GUID              =   Job_GUID
            ,@Job_Name              =   Job_Name                
            ,@LastFinishRunState    =   LastFinishRunState      
            ,@LastDateTime          =   LastDateTime            
            ,@LastRunDurationString =   LastRunDurationString   
            ,@LastOutcomeMessage    =   LastOutcomeMessage      
            ,@Server                =   [Server]                
            from @tbl
            order by LastRunDurationInt desc;

            set @[email protected]+'<TD>';
            set @[email protected]+cast(@ID as nvarchar(max));
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+cast(@Job_GUID as nvarchar(255));
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+coalesce(@Job_Name,'');
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+coalesce(@LastFinishRunState,'');
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+rep.GetDateFormat(@LastDateTime, default)+' '+rep.GetTimeFormat(@LastDateTime, default);--cast(@InsertDate as nvarchar(max));
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+coalesce(@LastRunDurationString,'');
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+coalesce(@LastOutcomeMessage, '');
            set @[email protected]+'</TD>';

            set @[email protected]+'<TD>';
            set @[email protected]+coalesce(@Server, '');
            set @[email protected]+'</TD>';

            delete from @tbl
            where [email protected];

            set @[email protected]+'</TR>';
        end

        set @[email protected]+'</TABLE>';
    end
    else
    begin
        set @body='The tasks, that have failed with an error or that have been executed for more than 30 seconds, have not been found';
    end

    set @[email protected]+'<br><br>For the detailed information, please refer to the table DATABASE_NAME.srv.ShortInfoRunJobs';
END

GO

Тази съхранена процедура генерира HTML-отчет за изпълнени задачи, които са били изпълнени за 30 секунди или които не са били завършени.

Резултат

В тази статия проучих на конкретен пример изпълнението на ежедневно автоматично събиране на данни за изпълнени задачи в SQL Server Agent. Тази информация помага да се определят задачи, които са били изпълнявани от дълго време или завършени с грешка. Това позволява на администратора да предприеме мерки за избягване на подобни грешки в бъдеще. Например, възможно е задачата да се изпълнява по-бързо или да зададете максимално време за посочената задача.

Това решение също помага за наблюдение на проблеми, свързани с архивирането. Все пак ще го обсъдим по-късно, тъй като не е достатъчно да уведомявате за важни задачи веднъж на ден. Необходимо е да изпращате имейли за тях незабавно и редовно, докато грешката бъде отстранена.

Ако трябва да изберете данни от няколко сървъра, тогава е възможно да комбинирате резултатите и да ги изпратите `чрез един имейл.

Препратки:

» sysjobs
» sysjobservers

Допълнително четене:

Автоматично събиране на данни за промени в схемата на базата данни в MS SQL Server

Автоматично събиране на данни:файлове с бази данни и логически устройства в MS SQL Server

Конфигуриране на известия за поща в базата данни в MS SQL Server


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Грешка на SQL Server - HRESULT E_FAIL е върнат от повикване към COM компонент

  2. Защо SQL Server губи една милисекунда?

  3. Защо и кога трябва да използвам SPARSE COLUMN? (SQL SERVER 2008)

  4. 6 начина за свързване на низ и число в SQL Server

  5. Как да конкатенирате низ и стойности NULL в SQL Server