SQL Agent next_run_date / next_run_time değerlerini nasıl ve ne zaman günceller?


13

Ben msdb veritabanında sp_add_jobschedule proc kullanarak bir SQL Agent işine yeni zamanlama eklemek için T-SQL kod üzerinde çalışıyorum. Yeni bir zamanlama eklediğimde (genellikle belirli bir tarih / saatte bir kez çalıştırılır) ve hemen sysjobschedules ve sysschedules'deki değerlere baktığımda, yeni zamanlamanın eklendiğini ve SQL Agent'ım için job_id'e bağlı olduğunu görebiliyorum iş. Ancak next_run_date ve next_run_time değerlerinde 0 vardır. Geri döndüğümde 2 ya da 3 dakika sonra tekrar baktığımda hala içlerinde 0'lar var. Ancak 5 veya 10 dakika sonra tekrar geldiğimde, bir sonraki programlı çalışmaya karşılık gelen tarih ve saat değerlerini doğru bir şekilde gösteriyor.

Yani sorularım:

  • Bu değerler ne sıklıkla güncellenir?
  • Bu değerleri güncelleyen süreç nedir?
  • Gelecekte 1 dakika gibi bir program ekleyecek olsaydım, işin next_run_date / saat henüz güncellenmediğinden bu yana çalışmayacağı anlamına mı geliyor?

Yeni bir zamanlama eklemek için kullandığım kod örneği:

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

burada @jobID, söz konusu işin job_id'ini tutan ikili (16), @ScheduleRunDate ve @ScheduleRunTime sırasıyla tarih ve saatle INT'lerdir.


3
Bir SQL Agent işi aracılığıyla güncellenir. Hangi bir SQL Agent işi ile güncellenir. Özyinelemeciler birleşiyor!
Aaron Bertrand

1
Özür. Bir süredir geri dönme şansım olmadı.
BBlake

Yanıtlar:


16

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.sysjobschedulesolarak tanımlanan SQL Agent'ta bir arka plan iş parçacığı tarafından güncellenir .SQLAgent - Schedule Saverxp_sqlagent_notify

Daha doğru bilgi, bakmak için next_scheduled_run_datein 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, sysjobactivityverileri 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 sysjobactivityhemen güncellenir ve sysjobschedulesyalnı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 sysjobactivityyukarı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_notifyson ç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 sysjobactivitydeğ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 ...


Bir iş henüz ilk kez çalıştırılmadıysa, sysjobschedules (nihayetinde) next_run_date ve next_run_time için doğru değerleri gösterirken, sysjobactivity.next_scheduled_run_date ilk yürütme sonrasına kadar boş kalır. Sysjobactivity'den değer alırken, job_id'e göre gruplanan ve MAX (sonraki_scheduled_run_date) alan bir alt sorguda yapmanız gerekir.
Mark Freeman

0

msdb.dbo.sp_help_jobher zaman doğru gerçek dönmek görünür next_run_date/ next_run_time.

sp_get_composite_job_infoGerçekten almak için aşağıdaki çağrıyı yapan kullanır next_run_date/time.

      IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
        INSERT INTO @xp_results
        EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @job_owner, @job_id
      ELSE
        INSERT INTO @xp_results
        EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @job_owner

Yana sysjobschedulegörüntülenir güvenilmez olması, sadece kullanırsınız sp_help_job.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.