Réponse courte
Il semble que les données msdb.dbo.sysjobschedules
soient mises à jour par un thread d'arrière-plan dans l'Agent SQL, identifié comme SQLAgent - Schedule Saver
, toutes les 20 minutes (ou moins fréquemment, s'il xp_sqlagent_notify
n'a pas été appelé et qu'aucune tâche n'a été exécutée entre-temps).
Pour des informations plus précises, regardez next_scheduled_run_date
dans msdb.dbo.sysjobactivity
. Il est mis à jour en temps réel chaque fois qu'un travail est modifié ou qu'un travail est exécuté. En prime, le sysjobactivity
stocke les données dans le bon sens (sous forme de colonne datetime), ce qui le rend beaucoup plus facile à utiliser que ces stupides INT.
Voilà la réponse courte:
Cela pourrait prendre jusqu'à 20 minutes avant que sysjobschedules reflète la vérité; cependant, sysjobactivity sera toujours à jour. Si vous voulez beaucoup plus de détails à ce sujet, ou comment je l'ai compris ...
Longue réponse
Si vous souhaitez suivre le lapin un instant, lorsque vous appelez sp_add_jobschedule
, cette chaîne d'événements est mise en mouvement:
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
Maintenant, nous ne pouvons plus poursuivre le lapin, car nous ne pouvons pas vraiment voir ce qui se xp_sqlagent_notify
passe. Mais je pense que nous pouvons présumer que cette procédure étendue interagit avec le service d'agent et lui indique qu'il y a eu un changement dans ce travail et ce calendrier spécifiques. En exécutant une trace côté serveur, nous pouvons voir que, immédiatement, le SQL dynamique suivant est appelé par l'Agent 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'
Il semble que la sysjobactivity
mise à jour soit immédiate et sysjobschedules
ne soit mise à jour que selon un calendrier. Si nous modifions le nouvel horaire pour qu'il soit une fois par jour, par exemple
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
Nous voyons toujours la mise à jour immédiate sysjobactivity
comme ci-dessus, puis une autre mise à jour une fois le travail terminé. Diverses mises à jour proviennent de l'arrière-plan et d'autres threads dans SQL Agent, par exemple:
SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver
Un thread d'arrière-plan (le thread "Schedule Saver") finit par arriver et se met à jour sysjobschedules
; d'après mon enquête initiale, il semble que ce soit toutes les 20 minutes, et ne se produit que si xp_sqlagent_notify
a été appelé en raison d'un changement apporté à un travail depuis la dernière exécution (je n'ai effectué aucun test supplémentaire pour voir ce qui se passe si un travail a été changé et un autre a été exécuté, si le fil de discussion "Schedule Saver" met à jour les deux - je soupçonne que cela doit, mais laissera cela comme un exercice au lecteur).
Je ne sais pas si le cycle de 20 minutes est décalé par rapport au démarrage de SQL Agent, ou à partir de minuit, ou par quelque chose de spécifique à la machine. Sur deux instances différentes sur le même serveur physique, le thread "Schedule Saver" a été mis à jour sysjobschedules
, sur les deux instances, presque en même temps - 18:31:37 & 18:51:37 sur une seule, et 18:31:39 & 18:51:39 de l'autre. Je n'ai pas démarré SQL Server Agent en même temps sur ces serveurs, mais il est possible que les heures de démarrage soient décalées de 20 minutes à distance. J'en doute, mais je n'ai pas le temps pour le moment de confirmer en redémarrant l'agent sur l'un d'eux et en attendant que d'autres mises à jour se produisent.
Je sais qui l'a fait et quand cela s'est produit, parce que j'ai placé un déclencheur là-bas et l'ai capturé, au cas où je ne le trouverais pas dans la trace, ou que je l'ai filtré par inadvertance.
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
Cela dit, il n'est pas difficile d'attraper avec une trace standard, celle-ci apparaît même en tant que DML non dynamique:
UPDATE msdb.dbo.sysjobschedules
SET next_run_date = 20120817,
next_run_time = 20000
WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE
and schedule_id = 8)
Si vous souhaitez exécuter une trace plus filtrée pour suivre ce comportement au fil du temps (par exemple, persister pendant les redémarrages de l'Agent SQL au lieu de sur demande), vous pouvez en exécuter une qui a appname = 'SQLAgent - Schedule Saver'
...
Je pense donc que si vous voulez connaître immédiatement la prochaine exécution, regardez sysjobactivity
, non sysjobschedules
. Ce tableau est directement mis à jour par l'agent ou ses threads d'arrière-plan ("Mettre à jour l'activité de travail", "Gestionnaire de travaux" et "Moteur d'invocation de travaux") au fur et à mesure que l'activité se produit ou comme il est notifié par xp_sqlagent_notify
.
Sachez cependant qu'il est très facile de nettoyer les deux tables, car il n'y a aucune protection contre la suppression de données de ces tables. (Ainsi, si vous avez décidé de nettoyer, par exemple, vous pouvez facilement supprimer toutes les lignes de ce travail de la table d'activité.) Dans ce cas, je ne sais pas exactement comment l'Agent SQL Server obtient ou enregistre la prochaine date d'exécution. Peut-être digne d'une enquête plus approfondie à une date ultérieure lorsque j'aurai du temps libre ...