ตัวแทน SQL จะอัพเดตค่า next_run_date / next_run_time อย่างไรและเมื่อไร?


13

ฉันทำงานกับโค้ดใน T-SQL เพื่อเพิ่มกำหนดการใหม่ให้กับงาน SQL Agent โดยใช้ sp_add_jobschedule proc ในฐานข้อมูล msdb เมื่อฉันเพิ่มกำหนดการใหม่ (โดยปกติแล้วจะเรียกใช้ครั้งเดียวในวันที่ / เวลาที่ระบุ) และดูค่าใน sysjobschedules และ sysschedules ทันทีฉันจะเห็นว่ามีการเพิ่มกำหนดการใหม่และเชื่อมโยงกับ job_id สำหรับตัวแทน SQL ของฉัน งาน. อย่างไรก็ตามค่าสำหรับ next_run_date และ next_run_time มี 0 ค่า เมื่อฉันกลับมาและดูพวกเขาอีกครั้งใน 2 หรือ 3 นาทีพวกเขายังคงแสดง 0 ในพวกเขา อย่างไรก็ตามเมื่อฉันกลับมาอีก 5 หรือ 10 นาทีต่อมาตอนนี้มันก็แสดงค่าวันที่และเวลาที่สอดคล้องกับการวิ่งตามกำหนดครั้งต่อไปได้อย่างถูกต้อง

ดังนั้นคำถามของฉันคือ:

  • ค่าเหล่านี้มีการอัปเดตบ่อยเพียงใด
  • กระบวนการใดที่ปรับปรุงค่าเหล่านี้
  • ถ้าฉันจะเพิ่มตารางเวลาที่เคยพูดว่า 1 นาทีในอนาคตนั่นหมายความว่างานจะไม่ทำงานเนื่องจาก next_run_date / เวลาครั้งถัดไปยังไม่ได้รับการอัปเดต

ตัวอย่างของรหัสที่ฉันใช้เพื่อเพิ่มกำหนดการใหม่:

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

โดยที่ @jobID เป็นไบนารี (16) ที่เก็บ job_id ของงานที่เป็นปัญหา @ScheduleRunDate และ @ScheduleRunTime เป็น INTs พร้อมวันที่และเวลาตามลำดับ


3
มีการอัพเดทผ่านงาน SQL Agent ซึ่งได้รับการอัพเดตผ่านงาน SQL Agent Recursionists รวมกัน!
Aaron Bertrand

1
ขอโทษ. ยังไม่มีโอกาสกลับไปเป็นวงกลมอีกซักพัก
BBlake

คำตอบ:


16

คำตอบสั้น ๆ

ดูเหมือนว่าข้อมูลในmsdb.dbo.sysjobschedulesจะได้รับการอัปเดตโดยเธรดพื้นหลังใน SQL Agent ซึ่งระบุว่าเป็นSQLAgent - Schedule Saverทุก ๆ 20 นาที (หรือน้อยกว่านี้หากxp_sqlagent_notifyไม่ได้รับการโทรและไม่มีงานใดทำงานในระหว่างนี้)

สำหรับข้อมูลที่ถูกต้องมากขึ้นดูที่ในnext_scheduled_run_date msdb.dbo.sysjobactivityสิ่งนี้ได้รับการปรับปรุงแบบเรียลไทม์ทุกครั้งที่มีการเปลี่ยนแปลงงานหรืองานที่ทำ ในฐานะโบนัสที่เพิ่มเข้ามานั้นจะsysjobactivityเก็บข้อมูลอย่างถูกต้อง (เป็นคอลัมน์วันที่) ทำให้การทำงานง่ายขึ้นกว่า INT ที่โง่

นั่นเป็นคำตอบสั้น ๆ :

อาจถึง 20 นาทีก่อนที่sysjobschedulesจะสะท้อนความจริง อย่างไรก็ตามsysjobactivityจะเป็นปัจจุบันเสมอ หากคุณต้องการรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งนี้หรือฉันจะหาได้ ...


คำตอบยาว ๆ

หากคุณสนใจที่จะติดตามเจ้ากระต่ายอยู่ครู่หนึ่งเมื่อคุณโทร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 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'

ดูเหมือนว่า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

ด้ายพื้นหลัง (ที่ "กำหนดการ Saver" ด้าย) ในที่สุดก็มาถึงรอบและการปรับปรุงsysjobschedules; จากการตรวจสอบครั้งแรกของฉันปรากฏว่านี่คือทุก ๆ 20 นาทีและจะเกิดขึ้นถ้าxp_sqlagent_notifyถูกเรียกเนื่องจากการเปลี่ยนแปลงที่ทำกับงานตั้งแต่ครั้งสุดท้ายที่มันทำงาน (ฉันไม่ได้ทำการทดสอบเพิ่มเติมเพื่อดูว่าเกิดอะไรขึ้นถ้างานหนึ่งได้รับ มีการเปลี่ยนแปลงและมีการเรียกใช้งานอีกครั้งหากเธรด "Schedule Saver" อัปเดตทั้งคู่ - ฉันสงสัยว่ามันจะต้องทำ

ฉันไม่แน่ใจว่าวัฏจักร 20 นาทีนั้นถูกชดเชยจากเมื่อเอเจนต์ SQL เริ่มทำงานหรือจากเที่ยงคืนหรือจากบางอย่างเฉพาะเครื่อง ในสองอินสแตนซ์ที่ต่างกันบนฟิสิคัลเซิร์ฟเวอร์เดียวกันเธรด "Schedule Saver" ได้รับการอัปเดตsysjobschedulesทั้งสองอินสแตนซ์เกือบจะในเวลาเดียวกัน - 18:31:37 & 18:51:37 ในหนึ่งและ 18:31:39 & 18:51:39 ที่อื่น ๆ ฉันไม่ได้เริ่ม SQL Server Agent พร้อมกันบนเซิร์ฟเวอร์เหล่านี้ แต่มีความเป็นไปได้ระยะไกลที่เวลาเริ่มต้นเกิดขึ้นเพื่อชดเชย 20 นาที ฉันสงสัย แต่ตอนนี้ฉันไม่มีเวลายืนยันโดยการรีสตาร์ท Agent ที่หนึ่งในนั้นและรอการอัปเดตเพิ่มเติมที่จะเกิดขึ้น

ฉันรู้ว่าใครทำและเมื่อมันเกิดขึ้นเพราะฉันวางไกที่นั่นและจับมันในกรณีที่ฉันไม่สามารถหามันได้ในร่องรอยหรือไม่ได้กรองออกโดยไม่ได้ตั้งใจ

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 Agent รับหรือบันทึกวันที่ทำงานถัดไปได้อย่างไร บางทีน่าจะมีการสอบสวนเพิ่มเติมในภายหลังเมื่อฉันมีเวลาว่าง ...


หากงานยังไม่ได้ทำงานเป็นครั้งแรก sysjobschedules จะ (ในที่สุด) แสดงค่าที่ถูกต้องสำหรับ next_run_date และ next_run_time ในขณะที่ sysjobactivity.next_scheduled_run_date ยังคงเป็นโมฆะจนกระทั่งหลังจากการประมวลผลครั้งแรก เมื่อรับค่าจาก sysjobactivity คุณต้องทำในเคียวรีย่อยที่จัดกลุ่มตาม job_id และรับ MAX (next_scheduled_run_date)
Mark Freeman

0

msdb.dbo.sp_help_jobก็จะปรากฏขึ้นเพื่อกลับไปที่เกิดขึ้นจริงที่ถูกต้อง/next_run_datenext_run_time

มันใช้ซึ่งไม่สายที่ต่อไปนี้เพื่อดึงจริงsp_get_composite_job_infonext_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

เนื่องจากปรากฏจะไม่น่าเชื่อถือผมก็จะใช้sysjobschedulesp_help_job

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.