Коротка відповідь
Схоже, дані в msdb.dbo.sysjobschedulesоновлюються фоновою ниткою в SQL Agent, ідентифікованої як SQLAgent - Schedule Saverкожні 20 хвилин (або рідше, якщо xp_sqlagent_notifyне було викликано і тим часом жодні завдання не виконувались тим часом).
Для більш точної інформації дивіться next_scheduled_run_dateв msdb.dbo.sysjobactivity. Він оновлюється в режимі реального часу будь-коли, коли змінено роботу або виконано роботу. Як додатковий бонус, вони sysjobactivityзберігають дані правильним способом (як стовпець дати), що робить його набагато простіше працювати з тими дурними INT.
Ось така коротка відповідь:
Це може пройти до 20 хвилин, перш ніж систематичні графіки відображають істину; однак систематичність завжди буде актуальною. Якщо ви хочете набагато детальніше про це, або як я це зрозумів ...
Довга відповідь
Якщо ви хочете на мить слідкувати за кроликом, коли ви телефонуєте 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 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'
Здається, sysjobactivityоновляється одразу, і sysjobschedulesоновлюється лише за розкладом. Якщо ми змінимо новий графік, щоб бути раз на день, наприклад
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
Ми все ще бачимо негайне оновлення, sysjobactivityяк зазначено вище, а потім ще одне оновлення після завершення завдання. Різні оновлення надходять із фонових та інших потоків у SQL Agent, наприклад:
SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver
Фоновий потік (нитка "Захист розкладу") врешті-решт з’являється та оновлюється sysjobschedules; з мого первинного розслідування виявляється, що це кожні 20 хвилин, і це відбувається лише в тому випадку, якщо xp_sqlagent_notifyмені було викликано через зміни, внесені до роботи з моменту останнього запуску (я не проводив ніяких додаткових тестувань, щоб побачити, що станеться, якщо одна робота була змінився і інший запустився, якщо потік "Захист розкладу" оновлює і те, і інше - я підозрюю, що він повинен, але це залишить читачеві як вправу).
Я не впевнений, чи зміщений 20-хвилинний цикл з моменту запуску агента SQL, або з півночі, або з чогось конкретного машинного. На двох різних примірниках на одному фізичному сервері потік " sysjobschedulesЗахист розкладу" оновлювався в обох випадках майже в один і той же час - 18:31:37 і 18:51:37 на одному, і 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 Agent замість запиту на замовлення), ви можете запустити той, який має appname = 'SQLAgent - Schedule Saver'...
Тому я думаю, що якщо ви хочете дізнатися наступний час запуску, подивіться sysjobactivity, ні sysjobschedules. Ця таблиця безпосередньо оновлюється Агентом або його потоковими потоками ("Оновити завдання роботи", "Менеджер завдань" та "Двигун викликів робіт"), коли відбувається діяльність або як повідомляється xp_sqlagent_notify.
Однак майте на увазі, що дуже легко вилучити будь-яку таблицю - оскільки немає захисту від видалення даних з цих таблиць. (Отже, якщо ви вирішили очистити, наприклад, ви можете легко видалити всі рядки для цієї роботи з таблиці активності.) У цьому випадку я точно не впевнений, як агент SQL Server отримує або зберігає наступну дату запуску. Можливо, вартих більшого розслідування в більш пізні терміни, коли у мене є вільний час ...