J'ai travaillé sur du code dans T-SQL pour ajouter de nouvelles planifications à un travail d'agent SQL en utilisant le proc sp_add_jobschedule dans la base de données msdb. Lorsque j'ajoute une nouvelle planification (généralement une exécution unique à une date / heure spécifique) et que je regarde immédiatement les valeurs dans sysjobschedules et sysschedules, je peux voir que la nouvelle planification a été ajoutée et est liée au job_id de mon agent SQL emploi. Cependant, les valeurs de next_run_date et next_run_time contiennent 0. Quand je reviens et les regarde à nouveau dans 2 ou 3 minutes, ils montrent toujours des 0 en eux. Cependant, lorsque je reviens 5 ou 10 minutes plus tard, il affiche désormais correctement les valeurs de date et d'heure correspondant à la prochaine exécution planifiée.
Mes questions sont donc:
- À quelle fréquence ces valeurs sont-elles mises à jour?
- Quel processus met à jour ces valeurs?
- Si je devais ajouter un calendrier qui serait, disons, d'une minute dans le futur, cela signifie-t-il que le travail ne s'exécutera pas puisque la date_prochaine_exécution / heure n'a pas encore été mise à jour?
Exemple de code que j'utilise pour ajouter un nouveau planning:
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
où @jobID est un binaire (16) contenant le job_id du travail en question, @ScheduleRunDate et @ScheduleRunTime sont des INT avec la date et l'heure respectivement.
Réponses:
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é commeSQLAgent - Schedule Saver
, toutes les 20 minutes (ou moins fréquemment, s'ilxp_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
dansmsdb.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, lesysjobactivity
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:
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: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:Il semble que la
sysjobactivity
mise à jour soit immédiate etsysjobschedules
ne soit mise à jour que selon un calendrier. Si nous modifions le nouvel horaire pour qu'il soit une fois par jour, par exempleNous 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: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 sixp_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.
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:
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
, nonsysjobschedules
. 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é parxp_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 ...
la source
msdb.dbo.sp_help_job
semble toujours renvoyer le correctnext_run_date
/next_run_time
.Il utilise
sp_get_composite_job_info
, qui effectue l'appel suivant pour récupérer réellement le fichiernext_run_date/time
.Puisqu'il ne
sysjobschedule
semble pas fiable, je voudrais simplement l'utilisersp_help_job
.la source