Kurze Antwort
Es sieht so aus, als würden die Daten in alle 20 Minuten msdb.dbo.sysjobschedules
von einem Hintergrundthread in SQL Agent aktualisiert SQLAgent - Schedule Saver
(oder seltener, wenn xp_sqlagent_notify
sie nicht aufgerufen wurden und in der Zwischenzeit keine Jobs ausgeführt wurden).
Weitere Informationen finden Sie next_scheduled_run_date
in msdb.dbo.sysjobactivity
. Dies wird in Echtzeit jedes Mal aktualisiert, wenn ein Job geändert oder ausgeführt wird. Als zusätzlichen Bonus sysjobactivity
speichert das die Daten richtig (als Datum / Uhrzeit-Spalte), wodurch es viel einfacher ist, damit zu arbeiten als mit diesen dummen INTs.
Das ist die kurze Antwort:
Es kann bis zu 20 Minuten dauern, bis Sysjobpläne die Wahrheit widerspiegeln. Die Systemaktivität ist jedoch immer auf dem neuesten Stand. Wenn Sie mehr darüber wissen wollen, oder wie ich es herausgefunden habe ...
Lange Antwort
Wenn Sie dem Kaninchen einen Moment lang folgen möchten, wenn Sie anrufen sp_add_jobschedule
, wird diese Ereigniskette in Gang gesetzt:
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
Jetzt können wir das Kaninchen nicht mehr weiter verfolgen, weil wir nicht wirklich sehen können, was es xp_sqlagent_notify
tut. Ich denke jedoch, dass wir davon ausgehen können, dass dieses erweiterte Verfahren mit dem Agentenservice interagiert und dass es eine Änderung an diesem bestimmten Job und Zeitplan gegeben hat. Indem wir einen serverseitigen Trace ausführen, können wir sofort feststellen, dass der folgende dynamische SQL-Code vom SQL-Agenten aufgerufen wird:
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'
Es scheint, dass sysjobactivity
das sofort aktualisiert wird und sysjobschedules
nur nach einem Zeitplan aktualisiert wird. Wenn wir den neuen Zeitplan auf einmal am Tag ändern, z
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
Wir sehen immer noch das sofortige Update auf sysjobactivity
wie oben und dann ein weiteres Update, nachdem der Job beendet ist. Verschiedene Updates stammen aus dem Hintergrund und anderen Threads in SQL Agent, z.
SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver
Ein Hintergrund-Thread (der "Schedule Saver" -Thread) erscheint und wird aktualisiert sysjobschedules
. meiner ersten Untersuchung zufolge ist dies alle 20 Minuten der Fall und geschieht nur, wenn xp_sqlagent_notify
ein Aufruf aufgrund einer Änderung eines Jobs seit seiner letzten Ausführung erfolgt ist (ich habe keine weiteren Tests durchgeführt, um festzustellen, was passiert, wenn ein Job ausgeführt wurde) geändert und ein anderer wurde ausgeführt, wenn der Thread "Schedule Saver" beide aktualisiert - ich vermute, es muss, überlässt dies aber dem Leser als Übung).
Ich bin nicht sicher, ob der 20-Minuten-Zyklus vom Zeitpunkt des Starts von SQL Agent, von Mitternacht oder von einem bestimmten Computer abweicht. Auf zwei verschiedenen Instanzen auf demselben physischen Server wurde der Thread "Schedule Saver" sysjobschedules
auf beiden Instanzen fast zur gleichen Zeit aktualisiert - 18:31:37 und 18:51:37 auf einer und 18:31:39. 18:51:39 auf der anderen Seite. Ich habe den SQL Server-Agenten auf diesen Servern nicht gleichzeitig gestartet, aber es besteht die Möglichkeit, dass die Startzeiten 20 Minuten versetzt sind. Ich bezweifle es, aber ich habe momentan keine Zeit, es zu bestätigen, indem ich Agent auf einem von ihnen neu starte und auf weitere Updates warte.
Ich weiß, wer es getan hat und wann es passiert ist, weil ich dort einen Abzug platziert und ihn erfasst habe, falls ich ihn nicht in der Spur finden konnte oder ich ihn versehentlich herausgefiltert habe.
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
Das heißt, es ist nicht schwer, mit einem Standard-Trace zu fangen, dieser kommt sogar als nicht-dynamisches DML durch:
UPDATE msdb.dbo.sysjobschedules
SET next_run_date = 20120817,
next_run_time = 20000
WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE
and schedule_id = 8)
Wenn Sie eine stärker gefilterte Ablaufverfolgung ausführen möchten, um dieses Verhalten über einen längeren Zeitraum nachzuverfolgen (z. B. bei einem Neustart des SQL-Agenten statt bei Bedarf), können Sie eine Ablaufverfolgung ausführen, die appname = 'SQLAgent - Schedule Saver'
... hat.
Also ich denke, wenn du die nächste Laufzeit sofort wissen willst, sieh dir das an sysjobactivity
, nicht sysjobschedules
. Diese Tabelle wird direkt vom Agenten oder seinen Hintergrundthreads ("Jobaktivität aktualisieren", "Jobmanager" und "Jobaufruf-Engine") aktualisiert, wenn eine Aktivität stattfindet oder von dieser benachrichtigt wird xp_sqlagent_notify
.
Beachten Sie jedoch, dass es sehr einfach ist, eine der beiden Tabellen auszutricksen, da es keinen Schutz gegen das Löschen von Daten aus diesen Tabellen gibt. (Wenn Sie sich beispielsweise für eine Bereinigung entschieden haben, können Sie problemlos alle Zeilen für diesen Job aus der Aktivitätstabelle entfernen.) In diesem Fall bin ich mir nicht sicher, wie der SQL Server-Agent das nächste Ausführungsdatum abruft oder speichert. Vielleicht verdient eine spätere Untersuchung mehr, wenn ich etwas Freizeit habe ...