SQLエージェントはnext_run_date / next_run_time値をいつどのように更新しますか?


13

msdbデータベースのsp_add_jobscheduleプロシージャを使用して、SQLエージェントジョブに新しいスケジュールを追加するために、T-SQLのコードに取り組んでいます。新しいスケジュール(通常は特定の日時に1回だけ)を追加し、すぐにsysjobschedulesとsysschedulesの値を見ると、新しいスケジュールが追加され、SQLエージェントのjob_idに関連付けられていることがわかりますジョブ。ただし、next_run_dateおよびnext_run_timeの値には0が含まれています。私が戻ってきて、2、3分後に再びそれらを見ると、彼らはまだそれらに0を示しています。ただし、さらに5分または10分後に戻ってくると、次にスケジュールされた実行に対応する日付と時刻の値が正しく表示されるようになりました。

だから私の質問は:

  • これらの値はどのくらいの頻度で更新されますか?
  • これらの値を更新するプロセスは何ですか?
  • たとえば、1分後のスケジュールを追加する場合、next_run_date / timeがまだ更新されていないため、ジョブが実行されないということですか?

新しいスケジュールを追加するために使用するコードの例:

exec msdb.dbo.sp_add_jobschedule @job_id = @jobID
                    , @name = @JobName
                    , @enabled = 1
                    , @freq_type = 1
                    , @freq_interval = 0
                    , @freq_subday_type = 0
                    , @freq_subday_interval = 0
                    , @freq_relative_interval = 0
                    , @freq_recurrence_factor = 0
                    , @active_start_date = @ScheduleRunDate
                    , @active_end_date = 99991231
                    , @active_start_time = @ScheduleRunTime
                    , @active_end_time = 235959

ここで、@ jobIDは問題のジョブのjob_idを保持するbinary(16)であり、@ ScheduleRunDateと@ScheduleRunTimeはそれぞれ日付と時刻のINTです。


3
SQLエージェントジョブを介して更新されます。これは、SQLエージェントジョブを通じて更新されます。再帰主義者が団結!
アーロンバートランド

1
謝罪。しばらく戻って回る機会がありませんでした。
BBlake

回答:


16

短い答え

のデータmsdb.dbo.sysjobschedulesは、SQLエージェントのバックグラウンドスレッドによって更新され、SQLAgent - Schedule Saver20分ごとに(またはxp_sqlagent_notify呼び出されておらず、その間にジョブが実行されていない場合は頻度が低くなります)識別されます。

より正確な情報については、見てnext_scheduled_run_dateの中でmsdb.dbo.sysjobactivity。これは、ジョブが変更されるかジョブが実行されるたびにリアルタイムで更新されます。追加のボーナスとして、sysjobactivityデータは正しい方法で(日付時刻列として)保存されるため、これらの愚かなINTよりも作業がはるかに簡単になります。

それは簡単な答えです:

sysjobschedulesが真実を反映するまでに最大20分かかる場合があります。ただし、sysjobactivityは常に最新です。これについてさらに詳細を知りたい場合、または私がそれをどのように理解したか...


ロングアンサー

ウサギをしばらく追跡したい場合、を呼び出すとsp_add_jobschedule、この一連のイベントが動き始めます。

msdb.dbo.sp_add_jobschedule == calls ==> msdb.dbo.sp_add_schedule
                                         msdb.dbo.sp_attach_schedule

msdb.dbo.sp_attach_schedule == calls ==> msdb.dbo.sp_sqlagent_notify

msdb.dbo.sp_sqlagent_notify == calls ==> msdb.dbo.xp_sqlagent_notify

さて、これ以上うさぎを追いかけることはできませんxp_sqlagent_notify。何をするのかを実際に覗くことができないからです。しかし、この拡張手順はエージェントサービスとやり取りし、この特定のジョブとスケジュールに変更があったことを伝えていると推測できます。サーバー側のトレースを実行すると、すぐに次の動的SQLがSQLエージェントによって呼び出されることがわかります。

exec sp_executesql N'DECLARE @nextScheduledRunDate DATETIME 
  SET @nextScheduledRunDate = msdb.dbo.agent_datetime(@P1, @P2) 
  UPDATE msdb.dbo.sysjobactivity 
    SET next_scheduled_run_date = @nextScheduledRunDate 
    WHERE session_id = @P3 AND job_id = @P4',
N'@P1 int,@P2 int,@P3 int,@P4 uniqueidentifier',
20120819,181600,5,'36924B24-9706-4FD7-8B3A-1F9F0BECB52C'

と思われsysjobactivity、すぐに更新され、sysjobschedules唯一のスケジュールで更新されます。新しいスケジュールを1日1回に変更した場合、たとえば

@freq_type=4, 
@freq_interval=1, 
@freq_subday_type=1, 
@freq_subday_interval=0, 
@freq_relative_interval=0, 
@freq_recurrence_factor=1, 

sysjobactivity上記のようにすぐに更新が行われ、ジョブの終了後に別の更新が行われます。さまざまな更新は、SQLエージェント内のバックグラウンドおよびその他のスレッドから行われます。例:

SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver

バックグラウンドスレッド(「スケジュールセーバー」スレッド)が最終的に登場し、更新されますsysjobschedules。私の最初の調査から、これは20分ごとでありxp_sqlagent_notify、最後に実行されてからジョブに加えられた変更のために呼び出された場合にのみ発生します「スケジュールセーバー」スレッドが両方を更新する場合、変更され、別のスレッドが実行されます-必要と思われますが、読者への演習として残します)。

20分サイクルが、SQLエージェントの起動時から、または深夜から、またはマシン固有の何かからオフセットされているかどうかはわかりません。同じ物理サーバー上の2つの異なるインスタンスで、「スケジュールセーバー」スレッドが更新されsysjobschedules、両方のインスタンスでほぼ同時に-1つは18:31:37&18:51:37、1つは18:31:39&他方の18:51:39。これらのサーバーでSQL Serverエージェントを同時に起動しませんでしたが、開始時間が20分のオフセットになる可能性がわずかにあります。疑いがありますが、現時点でエージェントのいずれかでエージェントを再起動し、さらに更新が行われるのを待つ時間はありません。

誰がそれをしたのか、それがいつ起こったのかを知っています。これは、トレース内でトリガーを見つけられなかった場合、または不注意でフィルターした場合に備えて、トリガーを配置してキャプチャしたためです。

CREATE TABLE dbo.JobAudit
(
  [action] CHAR(1),
  [table] CHAR(1), 
  hostname SYSNAME NOT NULL DEFAULT HOST_NAME(), 
  appname SYSNAME  NOT NULL DEFAULT PROGRAM_NAME(),
  dt DATETIME2     NOT NULL DEFAULT SYSDATETIME()
);

CREATE TRIGGER dbo.schedule1 ON dbo.sysjobactivity FOR INSERT
AS
  INSERT dbo.JobAudit([action], [table] SELECT 'I', 'A';
GO
CREATE TRIGGER dbo.schedule2 ON dbo.sysjobactivity FOR UPDATE
AS
  INSERT dbo.JobAudit([action], [table] SELECT 'U', 'A';
GO
CREATE TRIGGER dbo.schedule3 ON dbo.sysjobschedules FOR INSERT
AS
  INSERT dbo.JobAudit([action], [table] SELECT 'I', 'S';
GO
CREATE TRIGGER dbo.schedule4 ON dbo.sysjobschedules FOR UPDATE
AS
  INSERT dbo.JobAudit([action], [table] SELECT 'U', 'S';
GO

とは言っても、標準のトレースでキャッチするのは難しくありません。これは、動的でないDMLとしても実現します。

UPDATE msdb.dbo.sysjobschedules 
  SET next_run_date = 20120817, 
      next_run_time = 20000 
 WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE 
 and schedule_id = 8)

フィルター処理されたトレースを実行して、この動作を経時的に追跡する場合(たとえば、オンデマンドではなくSQLエージェントの再起動を通じて持続する場合)、appname = 'SQLAgent - Schedule Saver'... を持つトレースを実行できます。

したがって、次の実行時間をすぐに知りたい場合はsysjobactivity、ではなく、を見てくださいsysjobschedules。このテーブルは、アクティビティが発生したとき、または通知されたときに、エージェントまたはそのバックグラウンドスレッド(「ジョブアクティビティの更新」、「ジョブマネージャ」、「ジョブ呼び出しエンジン」)によって直接更新されxp_sqlagent_notifyます。

ただし、これらのテーブルからデータを削除することに対する保護がないため、どちらかのテーブルを非常に簡単に作成することに注意してください。(たとえば、クリーンアップすることにした場合、アクティビティテーブルからそのジョブのすべての行を簡単に削除できます。)この場合、SQL Serverエージェントが次の実行日を取得または保存する方法が正確にわかりません。後日、自由時間があるときにもっと調査する価値があるかもしれません...


ジョブがまだ最初に実行されていない場合、sysjobschedulesはnext_run_dateおよびnext_run_timeの正しい値を(最終的に)表示しますが、sysjobactivity.next_scheduled_run_dateは最初の実行までnullのままです。sysjobactivityから値を取得する場合、job_idでグループ化し、MAX(next_scheduled_run_date)を取得するサブクエリでそうする必要があります。
マークフリーマン14

0

msdb.dbo.sp_help_jobは常に正しい実際のnext_run_date/ を返すように見えますnext_run_time

を使用しますsp_get_composite_job_info。これは、実際にを取得するために次の呼び出しを行いnext_run_date/timeます。

      IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
        INSERT INTO @xp_results
        EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @job_owner, @job_id
      ELSE
        INSERT INTO @xp_results
        EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @job_owner

sysjobschedule信頼性がないように見えるので、私は単に使用しますsp_help_job

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.