Kısa cevap
Görünüşe göre, veriler her 20 dakikada bir (veya çağrılmadıysa ve bu arada hiçbir iş çalıştırılmadıysa) msdb.dbo.sysjobschedules
olarak tanımlanan SQL Agent'ta bir arka plan iş parçacığı tarafından güncellenir .SQLAgent - Schedule Saver
xp_sqlagent_notify
Daha doğru bilgi, bakmak için next_scheduled_run_date
in msdb.dbo.sysjobactivity
. Bu, bir iş değiştirildiğinde veya bir iş yürütüldüğünde gerçek zamanlı olarak güncellenir. Ek bir avantaj olarak, sysjobactivity
verileri doğru şekilde saklar (datetime sütunu olarak), bu aptal INT'lerden daha kolay çalışılmasını sağlar.
Kısa cevap budur:
Sisjobschedüllerin gerçeği yansıtması 20 dakikaya kadar sürebilir ; bununla birlikte, sisapaktivite her zaman güncel olacaktır. Bununla ilgili daha fazla ayrıntı veya nasıl anladığımı öğrenmek isterseniz ...
Uzun cevap
Tavşanı bir an için takip etmek isterseniz, aradığınızda sp_add_jobschedule
, bu olaylar zinciri harekete geçirilir:
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
Şimdi, tavşanı daha fazla kovalayamayız, çünkü ne yaptığına gerçekten bakamayız xp_sqlagent_notify
. Ancak, bu uzatılmış prosedürün Ajan hizmeti ile etkileşime girdiğini ve bu özel iş ve programda bir değişiklik olduğunu söyleyebileceğimizi düşünüyorum. Bir sunucu tarafı izlemesi çalıştırarak, hemen aşağıdaki dinamik SQL'in SQL Agent tarafından çağrıldığını görebiliriz:
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'
O görünüyor sysjobactivity
hemen güncellenir ve sysjobschedules
yalnızca bir programa göre güncellenir. Yeni programı günde bir kez değiştirirsek, ör.
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
Yine de sysjobactivity
yukarıdaki gibi güncellemeyi ve iş bittikten sonra başka bir güncellemeyi görüyoruz . SQL Agent içindeki arka plan ve diğer iş parçacıklarından çeşitli güncellemeler gelir, örneğin:
SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver
Bir arka plan iş parçacığı ("Zamanlama Tasarrufu" iş parçacığı) sonunda gelir ve güncellenir sysjobschedules
; ilk araştırmamdan itibaren bu her 20 dakikada bir görünüyor ve sadece xp_sqlagent_notify
son çalıştığından beri bir işte yapılan bir değişiklik nedeniyle çağrıldıysa gerçekleşir (bir iş yapıldıysa ne olduğunu görmek için başka test yapmadım "Schedule Saver" iş parçacığı her ikisini de güncelleştirirse, başka bir program çalıştırıldı.
20 dakikalık döngü SQL Agent başladığında, gece yarısı veya makineye özgü bir şey ofset olup olmadığını emin değilim. Aynı fiziksel sunucudaki iki farklı örnekte, "Zamanlama Tasarrufu" iş parçacığı sysjobschedules
, her iki örnekte de neredeyse aynı anda güncellendi - 18:31:37 & 18:51:37 bir ve 18:31:39 & 18:51:39 diğer yandan. SQL Server Agent'ı aynı anda bu sunucularda başlatmadım, ancak başlangıç sürelerinin 20 dakika ofset olması uzak bir olasılık. Şüpheliyim, ancak şu anda bir tanesinde Agent'ı yeniden başlatarak ve daha fazla güncelleme olmasını bekleyerek onaylamak için zamanım yok.
Kimin yaptığını ve ne zaman gerçekleştiğini biliyorum, çünkü oraya bir tetikleyici yerleştirdim ve yakaladım, izinde bulamamıştım ya da yanlışlıkla filtreledim.
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
Bununla birlikte, standart bir iz ile yakalamak zor değil, bu dinamik olmayan bir DML olarak bile geliyor:
UPDATE msdb.dbo.sysjobschedules
SET next_run_date = 20120817,
next_run_time = 20000
WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE
and schedule_id = 8)
Zaman içinde bu davranışı izlemek için daha filtrelenmiş bir iz çalıştırmak istiyorsanız (örneğin, isteğe bağlı yerine SQL Agent yeniden başlatılırken devam etmek), appname = 'SQLAgent - Schedule Saver'
...
Bu yüzden sanırım bir sonraki çalışma zamanını hemen bilmek istiyorsanız, bakın sysjobactivity
değil sysjobschedules
. Bu tablo, etkinlik gerçekleştikçe veya bildirimde bulunduğu şekilde Aracı veya arka plan iş parçacıkları ("İş etkinliğini güncelle", "İş Yöneticisi" ve "İş çağırma motoru") tarafından doğrudan güncellenir xp_sqlagent_notify
.
Bununla birlikte, bu tablolardan veri silmeye karşı herhangi bir koruma olmadığından, her iki tabloyu da yapıştırmanın çok kolay olduğunu unutmayın. (Örneğin, temizlemeye karar verdiyseniz, o iş için tüm satırları etkinlik tablosundan kolayca kaldırabilirsiniz.) Bu durumda, SQL Server Agent'ın bir sonraki çalıştırma tarihini nasıl aldığını veya kaydedeceğini tam olarak bilmiyorum. Belki de boş zamanım olduğunda daha sonraki bir tarihte daha fazla araştırmaya değer ...