web-dev-qa-db-ja.com

なぜジョブのnext_run_timeが間違っているのですか?

ジョブの統計に関する問題が発生しました。したがって、次のスケジュールのジョブがあります:毎日5分ごとに午前12:00:00から午後11:59:59まで発生します。スケジュールは2017年12月13日から使用されます。

11:27 AM 2019-10-20 2つのスクリプトを実行して、last_run_timeとnext_run_timeを取得しました。以下は、スクリプトとそれに対応する結果です。

USE msdb
GO
SELECT J.Name                     AS 'Job Name'
         ,'Job Enabled' =        
          CASE J.Enabled
                 WHEN 1 THEN 'Yes'
                 WHEN 0 THEN 'No'
          END
         ,STUFF(
          STUFF(CAST([active_start_date] AS VARCHAR(8)), 5, 0, '-')
          , 8, 0, '-')                   AS 'Job Schedule Start Date'
         ,STUFF(
          STUFF(CAST([active_end_date] AS VARCHAR(8)), 5, 0, '-')
          , 8, 0, '-')                   AS 'Job Schedule End Date'
         ,'Job Frequency' =
          CASE S.freq_type
                 WHEN 1 THEN 'Once'
                 WHEN 4 THEN 'Daily'
                 WHEN 8 THEN 'Weekly'
                 WHEN 16 THEN 'Monthly'
                 WHEN 32 THEN 'Monthly relative'
                 WHEN 64 THEN 'When SQLServer Agent starts'
          END
         ,'Last Run Date' = CONVERT(DATETIME, RTRIM(LASTRUN.run_date) + ' '
          + STUFF(STUFF(REPLACE(STR(RTRIM(LASTRUN.run_time), 6, 0),
          ' ', '0'), 3, 0, ':'), 6, 0, ':'))
         , 'Last Run Status' =
          CASE
                 WHEN LASTRUN.run_status = 0 THEN 'Failed'
                 WHEN LASTRUN.run_status = 1 THEN 'Succeeded'
                 WHEN LASTRUN.run_status = 2 THEN 'Retry'
                 WHEN LASTRUN.run_status = 3 THEN 'Cancelled'
                 ELSE 'Unknown'
          END                           
         ,'Last Run Message' = LASTRUN.message
FROM dbo.sysjobs J
LEFT OUTER JOIN dbo.sysjobschedules JS
       ON J.job_id = JS.job_id
LEFT OUTER JOIN dbo.sysschedules S
       ON JS.schedule_id = S.schedule_id
LEFT OUTER JOIN (SELECT
              job_id
          ,MAX(run_duration) AS RUN_DURATION
       FROM dbo.sysjobhistory
       GROUP BY job_id) MAXDUR
       ON J.job_id = MAXDUR.job_id
LEFT OUTER JOIN (SELECT
              J1.job_id
          ,J1.RUN_DURATION
          ,J1.run_date
          ,J1.run_time
          ,J1.message
          ,J1.run_status
       FROM dbo.sysjobhistory J1
       WHERE instance_id = (SELECT
                     MAX(instance_id)
              FROM dbo.sysjobhistory J2
              WHERE J2.job_id = J1.job_id)) LASTRUN
       ON J.job_id = LASTRUN.job_id
ORDER BY 'Job Name'

enter image description here

use msdb
go
Select [job name] = jb.name 
    , [schedule name] = sc.name
    , [next run date] = js.next_run_date
    , [next run time] = js.next_run_time
From dbo.sysjobs as jb
Inner Join dbo.sysjobschedules as js on js.job_id = jb.job_id
Inner Join dbo.sysschedules as sc on js.schedule_id = sc.schedule_id

enter image description here

したがって、写真によると、next_run_dateは11:15 AMではなく11:30 AMになるはずです。このような現象に直面したことがありますか?これを理解してくれませんか。

4
RaufDBA

sysjobschedulesのドキュメント 内部のデータが20分ごとに更新されることがわかります。

注:sysjobschedulesテーブルは20分ごとに更新されます。これは、sp_help_jobscheduleストアドプロシージャによって返される値に影響を与える可能性があります。

_next_run_date_および_next_run_time_列に古いデータが表示されるのはこのためです。

はるかに長い答えと詳細については。チェックアウト この答えAaron Bertrand

彼は_dbo.sysjobactivity_の使用について語っています。

このdmvの日時列である_next_scheduled_run_date_を使用できます。

クエリの例:

_SELECT sj.Name, 
next_scheduled_run_date
FROM msdb.dbo.sysjobs sj
JOIN msdb.dbo.sysjobactivity sja
ON sj.job_id = sja.job_id
WHERE session_id = (
    SELECT MAX(session_id) FROM msdb.dbo.sysjobactivity); 
_

エージェントが再起動するたびに新しいセッションを開始するため、max(session)を使用します。

これは

_Name                            next_scheduled_run_date
LSAlert_My_machine              2019-10-20 11:34:00.000
LSRestore_My_machine_Test42     2019-10-20 11:45:00.000
LSCopy_My_machine_Test42        2019-10-20 11:45:00.000
syspolicy_purge_history         2019-10-21 02:00:00.000
_

[〜#〜] ssms [〜#〜]

ジョブアクティビティモニターを呼び出すときにジョブ情報を取得するためにSSMSが実行していることをトレースするとき。 last_run_dateとlast_run_timeは、カーソルごとに_xp_sqlagent_enum_jobs_プロシージャから取得されます。

この手順を使用して、ジョブ情報を取得し、その上にカーソルを置くことができます。

1つのジョブの情報を取得する例:

_DECLARE @job_id uniqueidentifier
DECLARE @job_owner varchar(255)
SELECT @job_owner = SUSER_SNAME()

SELECT @job_id=job_id FROM msdb..sysjobs 
WHERE name = 'LSAlert_My_machine'
    EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id;
_

プロシージャによって返される2番目から5番目の列:

_Last Run Date   Last Run Time   Next Run Date   Next Run Time
20191020        114400          20191020        114600
_

すべてのジョブに対してプロシージャを実行する場合:

_DECLARE @job_id uniqueidentifier, @job_name varchar(255)
DECLARE @job_owner varchar(255)
SELECT @job_owner = SUSER_SNAME()
DECLARE @xp_results TABLE(Job_name varchar(255),Job_Id varbinary(16),last_run_date varchar(10),last_run_time varchar(10),next_run_date varchar(10), next_run_time varchar(10), next_run_schedule_id int, requested_to_run bit,request_source int, request_source_id int, running bit, current_step int, current_retry_attempt int, [State] int)

DECLARE C CURSOR FAST_FORWARD READ_ONLY FOR 
SELECT [name],job_id FROM msdb..sysjobs 
OPEN C
FETCH NEXT FROM C INTO @job_name,@job_id
WHILE @@FETCH_STATUS = 0
BEGIN

INSERT INTO @xp_results(Job_Id,last_run_date ,last_run_time ,next_run_date , next_run_time , next_run_schedule_id , requested_to_run ,request_source , request_source_id , running , current_step , current_retry_attempt , [State] )
    EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id;

UPDATE @xp_results
SET Job_name = @job_name
WHERE Job_Id = @job_id;

FETCH NEXT FROM C INTO @job_name,@job_id
END
CLOSE C
DEALLOCATE C
SELECT Job_name,last_run_date,last_run_time,next_run_date,next_run_time 
FROM @xp_results;
_

出力例

_Job_name                        last_run_date   last_run_time   next_run_date   next_run_time
LSAlert_My_machine              20191020        115800          20191020        120000
LSCopy_My_machine_Test42        20191020        114500          20191020        120000
LSRestore_My_machine_Test42     20191020        114500          20191020        120000
_
5
Randi Vertongen