sql >> データベース >  >> RDS >> Sqlserver

MSSQLServerで完了したタスクに関する自動データ収集

    はじめに

    データベース管理者は、どのタスクとそれらがどのように完了したかを知ることが重要です。このプロセスを簡素化するには、手動で実行するのではなく、自動化することをお勧めします。

    この記事では、SQLServerエージェントの完了したタスクに関するデータを自動的に収集する方法を特定の例で分析します。

    ソリューション

    アルゴリズム:

    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秒以上)実行されたタスクまたは完了できなかったタスクに関する情報を取得します。過去2日間、この情報を収集する必要があります。
      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
    を参照してください。

    このストアドプロシージャは、30秒間実行されたタスク、または完了できなかったタスクに関するHTMLレポートを生成します。

    結果

    この記事では、特定の例で、SQLServerエージェントで完了したタスクに関する毎日の自動データ収集の実装について説明しました。この情報は、長期間実行されたタスク、またはエラーで完了したタスクを判別するのに役立ちます。これにより、管理者は将来このような間違いを回避するための対策を講じることができます。たとえば、タスクの実行速度を上げたり、指定したタスクの最大時間を設定したりできます。

    このソリューションは、バックアップに関連する問題の監視にも役立ちます。それでも、重要なタスクについて1日1回通知するだけでは不十分なため、後で説明します。エラーが修正されるまで、すぐに定期的にメールで送信する必要があります。

    複数のサーバーからデータを選択する必要がある場合は、結果を組み合わせて「1通のメールで」送信することができます。

    参照:

    »sysjobs
    »sysjobservers

    参考資料:

    MSSQLServerでのデータベーススキーマ変更の自動データ収集

    自動データ収集:MSSQLServerのデータベースファイルと論理ドライブ

    MSSQLServerでのデータベースメール通知の構成


    1. OracleODP.netマネージドドライバーとアンマネージドドライバー

    2. SELECT * FROM table_name;のMySQL行の順序は何ですか?

    3. 初心者のためのSQLUPDATE

    4. 32ビットExcelおよび64ビットSQLServer