Я работал над кодом в T-SQL, чтобы добавить новые расписания в задание агента SQL с помощью процедуры sp_add_jobschedule в базе данных msdb. Когда я добавляю новое расписание (как правило, запускается один раз в определенную дату / время) и сразу же проверяю значения в sysjobschedules и sysschedules, я вижу, что новое расписание было добавлено и привязано к job_id для моего агента SQL работа. Однако значения для 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 - это двоичный файл (16), который содержит job_id рассматриваемого задания, @ScheduleRunDate и @ScheduleRunTime - INT с датой и временем соответственно.
Ответы:
Короткий ответ
Похоже, что данные в
msdb.dbo.sysjobschedules
обновляются фоновым потоком в агенте SQL, который идентифицируется какSQLAgent - Schedule Saver
каждые 20 минут (или реже, еслиxp_sqlagent_notify
он не был вызван и в это время не выполнялись никакие задания).Для более точной информации, посмотрите
next_scheduled_run_date
вmsdb.dbo.sysjobactivity
. Он обновляется в режиме реального времени при каждом изменении задания или выполнении задания. В качестве дополнительного бонусаsysjobactivity
данные хранятся правильно (в виде столбца даты и времени), что делает работу с ними намного проще, чем с этими глупыми INT.Вот краткий ответ:
Длинный ответ
Если вам захочется проследить за кроликом на мгновение, когда вы позвоните
sp_add_jobschedule
, эта цепочка событий запускается:Теперь, мы не можем преследовать кролика дальше, потому что мы не можем действительно заглянуть в то, что
xp_sqlagent_notify
делает. Но я думаю, что мы можем предположить, что эта расширенная процедура взаимодействует со службой агента и сообщает, что в этой конкретной работе и расписании произошли изменения. Запустив трассировку на стороне сервера, мы увидим, что агент SQL немедленно вызывает следующий динамический SQL:Кажется, что
sysjobactivity
он обновляется немедленно иsysjobschedules
обновляется только по расписанию. Если мы изменим новое расписание на один раз в день, напримерМы по-прежнему видим немедленное обновление,
sysjobactivity
как указано выше, а затем еще одно обновление после завершения работы. Различные обновления происходят из фона и других потоков в агенте SQL, например:Фоновый поток (поток «Schedule Saver») в конце концов появляется и обновляется
sysjobschedules
; из моего первоначального исследования выясняется, что это происходит каждые 20 минут и происходит только в том случае, еслиxp_sqlagent_notify
он был вызван из-за изменения, внесенного в задание с момента его последнего запуска (я не проводил никаких дальнейших проверок, чтобы увидеть, что произойдет, если одно задание было изменился, и другой был запущен, если поток «Schedule Saver» обновляет оба - я подозреваю, что должен, но оставит это как упражнение для читателя).Я не уверен, смещен ли 20-минутный цикл с момента запуска агента SQL, или с полуночи, или с чего-то конкретного компьютера. В двух разных экземплярах на одном физическом сервере поток «Расписание по расписанию» обновлялся
sysjobschedules
в обоих случаях практически в одно и то же время - 18:31:37 & 18:51:37 на одном и 18:31:39 & 18:51:39 с другой. Я не запускал агент SQL Server одновременно на этих серверах, но существует вероятность того, что время запуска смещено на 20 минут. Я сомневаюсь в этом, но у меня нет времени, чтобы подтвердить это, перезапустив Агент на одном из них и ожидая, пока не произойдет больше обновлений.Я знаю, кто это сделал, и когда это произошло, потому что я поместил там триггер и захватил его, на случай, если я не смог найти его в трассировке или я случайно отфильтровал его.
Тем не менее, это не трудно поймать со стандартной трассировкой, этот даже выглядит как нединамический DML:
Если вы хотите запустить более отфильтрованную трассировку, чтобы отслеживать это поведение с течением времени (например, сохранение через перезапуск агента SQL вместо запроса по требованию), вы можете запустить тот, который имеет appname =
'SQLAgent - Schedule Saver'
...Поэтому я думаю, что если вы хотите узнать время следующего запуска сразу, посмотрите
sysjobactivity
, нетsysjobschedules
. Эта таблица напрямую обновляется Агентом или его фоновыми потоками («Активность обновления задания», «Диспетчер заданий» и «Механизм вызова задания») по мере того, как происходит действие или когда оно получает уведомлениеxp_sqlagent_notify
.Имейте в виду, однако, что очень легко испортить любую из таблиц - поскольку нет защиты от удаления данных из этих таблиц. (Поэтому, если вы решили очистить, например, вы можете легко удалить все строки для этого задания из таблицы действий.) В этом случае я не совсем уверен, каким образом агент SQL Server получает или сохраняет следующую дату выполнения. Возможно, стоит провести дополнительное расследование позже, когда у меня будет немного свободного времени ...
источник
msdb.dbo.sp_help_job
всегда появляется, чтобы вернуть правильный фактnext_run_date
/next_run_time
.Он использует
sp_get_composite_job_info
, что делает следующий вызов для фактического полученияnext_run_date/time
.Так как
sysjobschedule
кажется ненадежным, я бы просто использовалsp_help_job
.источник