Krótka odpowiedź
Wygląda na to, że dane w msdb.dbo.sysjobschedules
są aktualizowane przez wątek w tle w SQL Agent, identyfikowany jako SQLAgent - Schedule Saver
co 20 minut (lub rzadziej, jeśli xp_sqlagent_notify
nie został wywołany i w międzyczasie nie uruchomiono żadnych zadań).
W celu uzyskania bardziej dokładnych informacji, spójrz na next_scheduled_run_date
IN msdb.dbo.sysjobactivity
. Jest on aktualizowany w czasie rzeczywistym za każdym razem, gdy zadanie zostanie zmienione lub zadanie zostanie uruchomione. Jako dodatkowy bonus, sysjobactivity
przechowuje dane we właściwy sposób (jako kolumnę daty i godziny), co znacznie ułatwia pracę z tymi głupimi INT.
Oto krótka odpowiedź:
Może potrwać do 20 minut, zanim sysjobschedules odzwierciedla prawdę; jednak aktywność sysjob będzie zawsze aktualna. Jeśli chcesz o wiele więcej szczegółów na ten temat lub jak to wymyśliłem ...
Długa odpowiedź
Jeśli chcesz przez chwilę podążać za królikiem, kiedy zadzwonisz sp_add_jobschedule
, ten łańcuch wydarzeń zostanie uruchomiony:
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
Teraz nie możemy już gonić królika, ponieważ nie możemy tak naprawdę zajrzeć do tego, co xp_sqlagent_notify
robi. Ale myślę, że możemy założyć, że ta rozszerzona procedura współdziała z usługą agenta i informuje ją, że nastąpiła zmiana w tym konkretnym zadaniu i harmonogramie. Po uruchomieniu śledzenia po stronie serwera możemy natychmiast zobaczyć, że następujący dynamiczny SQL jest wywoływany przez agenta 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'
Wygląda na sysjobactivity
to, że jest aktualizowany natychmiast i sysjobschedules
jest aktualizowany tylko zgodnie z harmonogramem. Jeśli zmienimy nowy harmonogram na raz dziennie, np
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
Nadal widzimy natychmiastową aktualizację do sysjobactivity
powyższej, a następnie kolejną aktualizację po zakończeniu zadania. Różne aktualizacje pochodzą z tła i innych wątków w SQL Agent, np .:
SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver
W końcu pojawia się wątek (wątek „Schedule Saver”) i aktualizuje się sysjobschedules
; z mojego wstępnego dochodzenia wydaje się, że odbywa się to co 20 minut i dzieje się tak tylko wtedy, gdy xp_sqlagent_notify
został wywołany ze względu na zmianę wprowadzoną w zadaniu od ostatniego uruchomienia (nie wykonałem żadnych dalszych testów, aby zobaczyć, co się stanie, jeśli jedno zadanie zostało wykonane zmieniono i uruchomiono inny, jeśli wątek „Schedule Saver” zaktualizuje oba - podejrzewam, że musi, ale pozostawi to jako ćwiczenie czytelnikowi).
Nie jestem pewien, czy 20-minutowy cykl jest przesunięty w stosunku do momentu uruchomienia agenta SQL, czy od północy, czy od czegoś specyficznego dla maszyny. W dwóch różnych instancjach na tym samym serwerze fizycznym wątek „Schedule Saver” został zaktualizowany sysjobschedules
, w obu instancjach, prawie dokładnie w tym samym czasie - 18:31:37 i 18:51:37 na jednym oraz 18:31:39 & 18:51:39 z drugiej strony. Nie uruchomiłem agenta programu SQL Server w tym samym czasie na tych serwerach, ale istnieje zdalna możliwość, że czasy rozpoczęcia były przesunięte o 20 minut. Wątpię, ale nie mam teraz czasu na potwierdzenie, uruchamiając ponownie Agenta na jednym z nich i czekając na kolejne aktualizacje.
Wiem, kto to zrobił, i kiedy to się stało, ponieważ umieściłem tam spust i złapałem go, na wypadek, gdy nie mogłem go znaleźć w śladzie lub przypadkowo go odfiltrowałem.
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
To powiedziawszy, nie jest trudno złapać za pomocą standardowego śledzenia, ten pojawia się nawet jako niedynamiczny DML:
UPDATE msdb.dbo.sysjobschedules
SET next_run_date = 20120817,
next_run_time = 20000
WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE
and schedule_id = 8)
Jeśli chcesz uruchomić bardziej przefiltrowane dane śledzenia w celu śledzenia tego zachowania w czasie (np. Utrzymywanie się przez SQL Agent uruchamia się ponownie zamiast na żądanie), możesz uruchomić taki, który ma appname = 'SQLAgent - Schedule Saver'
...
Myślę więc, że jeśli chcesz natychmiast poznać następny czas wykonywania, spójrz na sysjobactivity
nie sysjobschedules
. Ta tabela jest aktualizowana bezpośrednio przez Agenta lub jego wątki w tle („Aktualizuj aktywność zadania”, „Menedżer zadań” i „Mechanizm wywoływania zadań”) w miarę występowania aktywności lub powiadamiania przez nią xp_sqlagent_notify
.
Pamiętaj jednak, że bardzo łatwo jest zrównać obie tabele - ponieważ nie ma żadnych zabezpieczeń przed usunięciem danych z tych tabel. (Jeśli na przykład zdecydujesz się wyczyścić, możesz łatwo usunąć wszystkie wiersze dla tego zadania z tabeli działań.) W tym przypadku nie jestem do końca pewien, w jaki sposób SQL Server Agent pobiera lub zapisuje datę następnego uruchomienia. Być może warte dalszych badań w późniejszym terminie, kiedy będę miał trochę wolnego czasu ...