Bagaimana dan kapan SQL Agent memperbarui nilai next_run_date / next_run_time?


13

Saya telah mengerjakan kode dalam T-SQL untuk menambahkan jadwal baru ke pekerjaan SQL Agent menggunakan sp_add_jobschedule proc dalam database msdb. Ketika saya menambahkan jadwal baru (biasanya sekali jalan pada tanggal / waktu tertentu) dan segera melihat nilai-nilai dalam sysjobschedules dan sysschedules, saya dapat melihat bahwa jadwal baru telah ditambahkan dan terkait dengan job_id untuk Agen SQL saya. pekerjaan. Namun, nilai untuk next_run_date dan next_run_time memiliki 0 di dalamnya. Ketika saya kembali dan melihat mereka lagi dalam 2 atau 3 menit, mereka masih menunjukkan 0 di dalamnya. Namun ketika saya kembali lagi 5 atau 10 menit kemudian, sekarang dengan benar menunjukkan nilai tanggal dan waktu yang sesuai dengan proses yang dijadwalkan berikutnya.

Jadi pertanyaan saya adalah:

  • Seberapa sering nilai-nilai ini diperbarui?
  • Proses apa yang memperbarui nilai-nilai ini?
  • Jika saya menambahkan jadwal yang, katakanlah, 1 menit di masa depan, apakah itu berarti pekerjaan itu tidak akan berjalan karena next_run_date / waktu belum diperbarui?

Contoh kode yang saya gunakan untuk menambahkan jadwal baru:

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

di mana @jobID adalah biner (16) yang menyimpan job_id dari pekerjaan tersebut, @ScheduleRunDate dan @ScheduleRunTime adalah INT dengan tanggal dan waktu masing-masing.


3
Ini diperbarui melalui pekerjaan SQL Agent. Yang diperbarui melalui pekerjaan SQL Agent. Rekursionis bersatu!
Aaron Bertrand

1
Permintaan maaf. Belum sempat berputar kembali dalam beberapa saat.
BBlake

Jawaban:


16

Jawaban singkat

Sepertinya data dalam msdb.dbo.sysjobschedulesdiperbarui oleh utas latar belakang di SQL Agent, diidentifikasi sebagai SQLAgent - Schedule Saver, setiap 20 menit (atau kurang sering, jika xp_sqlagent_notifybelum dipanggil dan tidak ada pekerjaan yang berjalan sementara itu).

Untuk informasi yang lebih akurat, lihat next_scheduled_run_datedi msdb.dbo.sysjobactivity. Ini diperbarui secara waktu-nyata kapan saja suatu pekerjaan diubah atau pekerjaan telah berjalan. Sebagai bonus tambahan, sysjobactivitymenyimpan data dengan cara yang benar (sebagai kolom datetime), membuatnya jauh lebih mudah untuk digunakan dibandingkan dengan INT yang bodoh itu.

Itulah jawaban singkatnya:

Mungkin sampai 20 menit sebelum jadwal sysjobsch mencerminkan kebenaran; Namun, aktivitas sysjob akan selalu terkini. Jika Anda ingin lebih detail tentang ini, atau bagaimana saya mengetahuinya ...


Jawaban panjang

Jika Anda ingin mengikuti kelinci sejenak, saat Anda menelepon sp_add_jobschedule, rangkaian peristiwa ini mulai bergerak:

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

Sekarang, kita tidak bisa mengejar kelinci lebih jauh lagi, karena kita tidak bisa mengintip ke dalamnya xp_sqlagent_notify. Tetapi saya pikir kita dapat menganggap bahwa prosedur yang diperluas ini berinteraksi dengan layanan Agen dan memberi tahu bahwa telah ada perubahan pada pekerjaan dan jadwal spesifik ini. Dengan menjalankan jejak sisi server kita dapat melihat bahwa, segera, SQL dinamis berikut ini disebut oleh SQL Agent:

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'

Tampaknya sysjobactivitydiperbarui segera, dan sysjobscheduleshanya diperbarui sesuai jadwal. Jika kita mengubah jadwal baru menjadi sekali sehari, mis

@freq_type=4, 
@freq_interval=1, 
@freq_subday_type=1, 
@freq_subday_interval=0, 
@freq_relative_interval=0, 
@freq_recurrence_factor=1, 

Kami masih melihat pembaruan langsung sysjobactivityseperti di atas, dan kemudian pembaruan lain setelah pekerjaan selesai. Berbagai pembaruan berasal dari latar belakang dan utas lainnya dalam SQL Agent, misalnya:

SQLAgent - Job Manager
SQLAgent - Update job activity
SQLAgent - Job invocation engine
SQLAgent - Schedule Saver

Utas latar belakang (utas "Penghemat Jadwal") akhirnya muncul dan diperbarui sysjobschedules; dari penyelidikan awal saya tampaknya ini setiap 20 menit, dan hanya terjadi jika xp_sqlagent_notifytelah dipanggil karena ada perubahan pada pekerjaan sejak terakhir kali dijalankan (saya tidak melakukan pengujian lebih lanjut untuk melihat apa yang terjadi jika satu pekerjaan telah dilakukan diubah dan yang lain telah dijalankan, jika "Jadwal Saver" utas memperbarui keduanya - saya kira itu harus, tetapi akan meninggalkan itu sebagai latihan untuk pembaca).

Saya tidak yakin apakah siklus 20 menit diimbangi dari saat SQL Agent dimulai, atau mulai tengah malam, atau dari sesuatu yang spesifik mesin. Pada dua contoh berbeda pada server fisik yang sama, utas "Schedule Saver" diperbarui sysjobschedules, pada kedua contoh, pada waktu yang hampir bersamaan - 18:31:37 & 18:51:37 pada satu, dan 18:31:39 & 18:51:39 di sisi lain. Saya tidak memulai SQL Server Agent pada saat yang sama pada server ini, tetapi ada kemungkinan jarak jauh bahwa waktu mulai kebetulan adalah 20 menit offset. Saya ragu, tetapi saya tidak punya waktu sekarang untuk mengonfirmasi dengan memulai kembali Agen pada salah satu dari mereka dan menunggu lebih banyak pembaruan terjadi.

Saya tahu siapa yang melakukannya, dan kapan itu terjadi, karena saya meletakkan pelatuk di sana dan menangkapnya, kalau-kalau saya tidak bisa menemukannya di jejak, atau saya tidak sengaja menyaringnya.

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

Yang mengatakan, tidak sulit untuk menangkap dengan jejak standar, ini bahkan disebut sebagai DML non-dinamis:

UPDATE msdb.dbo.sysjobschedules 
  SET next_run_date = 20120817, 
      next_run_time = 20000 
 WHERE (job_id = 0xB87B329BFBF7BA40B30D9B27E0B120DE 
 and schedule_id = 8)

Jika Anda ingin menjalankan jejak yang lebih difilter untuk melacak perilaku ini dari waktu ke waktu (mis. Bertahan melalui restart Agen SQL alih-alih sesuai permintaan), Anda dapat menjalankan yang memiliki appname = 'SQLAgent - Schedule Saver'...

Jadi saya pikir jika Anda ingin segera mengetahui jangka waktu berikutnya, lihatlah sysjobactivity, tidak sysjobschedules. Tabel ini diperbarui secara langsung oleh Agen atau utas latar belakangnya ("Perbarui aktivitas pekerjaan", "Manajer Pekerjaan", dan "Mesin Doa Pekerjaan") saat aktivitas terjadi atau saat diberitahukan oleh xp_sqlagent_notify.

Perlu diketahui, bahwa sangat mudah untuk membuat tabel baik - karena tidak ada perlindungan terhadap penghapusan data dari tabel ini. (Jadi, jika Anda memutuskan untuk membersihkan, misalnya, Anda dapat dengan mudah menghapus semua baris untuk pekerjaan itu dari tabel aktivitas.) Dalam hal ini saya tidak yakin bagaimana SQL Server Agent mendapatkan atau menyimpan tanggal menjalankan berikutnya. Mungkin layak untuk diselidiki lebih lanjut di kemudian hari ketika saya memiliki waktu luang ...


Jika suatu pekerjaan belum berjalan untuk pertama kalinya, sysjobschedules akan (akhirnya) menampilkan nilai yang benar untuk next_run_date dan next_run_time, sedangkan sysjobactivity.next_scheduled_run_date tetap nol sampai setelah eksekusi pertama. Ketika mendapatkan nilai dari sysjobactivity Anda perlu melakukannya di subquery yang dikelompokkan oleh job_id dan mendapatkan MAX (next_scheduled_run_date).
Mark Freeman

0

msdb.dbo.sp_help_jobselalu muncul untuk mengembalikan yang sebenarnya next_run_date/ next_run_time.

Menggunakan sp_get_composite_job_info, yang melakukan panggilan berikut untuk benar-benar mengambil 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

Karena sysjobscheduletampaknya tidak dapat diandalkan, saya hanya akan menggunakan sp_help_job.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.