SQL 에이전트는 언제 어떻게 next_run_date / next_run_time 값을 업데이트합니까?


13

msdb 데이터베이스의 sp_add_jobschedule proc을 사용하여 SQL 에이전트 작업에 새로운 일정을 추가하기 위해 T-SQL의 코드를 작업하고 있습니다. 새 일정 (일반적으로 특정 날짜 / 시간에 한 번 실행)을 추가하고 sysjobschedules 및 sysschedules의 값을 즉시 보면 새 일정이 추가되었고 SQL 에이전트의 job_id에 연결되어 있음을 알 수 있습니다. 일. 그러나 next_run_date 및 next_run_time의 값은 0입니다. 다시 돌아와서 2 ~ 3 분 후에 다시 보면 여전히 0이 표시됩니다. 그러나 5 분 또는 10 분 후에 다시 돌아 오면 이제 다음 예약 된 실행에 해당하는 날짜 및 시간 값이 올바르게 표시됩니다.

그래서 내 질문은 :

  • 이 값은 얼마나 자주 업데이트됩니까?
  • 이러한 값을 업데이트하는 프로세스는 무엇입니까?
  • 예를 들어, 1 분 후에 스케줄을 추가 할 경우 next_run_date / time이 아직 업데이트되지 않은 이후에 작업이 실행되지 않습니까?

새 일정을 추가하는 데 사용하는 코드의 예 :

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는 해당 작업의 job_id를 보유하는 binary (16)이며 @ScheduleRunDate 및 @ScheduleRunTime은 각각 날짜와 시간이있는 INT입니다.


3
SQL 에이전트 작업을 통해 업데이트됩니다. SQL 에이전트 작업을 통해 업데이트됩니다. 재귀 론자들의 연합!
Aaron Bertrand

1
사과. 잠시 후 다시 돌아올 기회가 없었습니다.
BBlake

답변:


16

짧은 답변

20 분마다 (또는 호출되지 않았으며 그 동안 작업이 실행되지 않은 경우 덜 빈번한) msdb.dbo.sysjobschedulesSQL 에이전트의 백그라운드 스레드에 의해 데이터 가 업데이트되는 것처럼 보입니다 .SQLAgent - Schedule Saverxp_sqlagent_notify

보다 정확한 정보를 봐 위해 next_scheduled_run_date에서 msdb.dbo.sysjobactivity. 작업이 변경되거나 작업이 실행될 때마다 실시간으로 업데이트됩니다. 또한 보너스 sysjobactivity는 데이터를 올바른 방식으로 (날짜 / 시간 열) 저장하므로 어리석은 INT보다 작업하기가 훨씬 쉽습니다.

그것은 짧은 대답입니다.

sysjobschedules 가 진실을 반영 하기까지 최대 20 분이 소요될 수 있습니다 . 그러나 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 에이전트가 다음 동적 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'

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 에이전트 내의 백그라운드 및 기타 스레드에서 제공됩니다. 예 :

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

백그라운드 스레드 ( "Schedule 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 에이전트를 동시에 시작하지 않았지만 시작 시간이 20 분 오프셋 될 수있는 원격 가능성이 있습니다. 의심 스럽지만 지금은 에이전트 중 하나에서 에이전트를 다시 시작하고 더 많은 업데이트가 발생할 때까지 기다리는 것으로 확인할 시간이 없습니다.

트레이스에서 트리거를 찾을 수 없거나 실수로 필터링하지 않은 경우 트리거를 배치하고 캡처했기 때문에 누가 그랬는지, 언제 발생했는지 알고 있습니다.

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 에이전트 다시 시작을 통해 지속) appname = 'SQLAgent - Schedule Saver'...

난 당신이 바로 봐 다음 실행 시간을 알고 싶다면 생각 그래서 sysjobactivity하지를 sysjobschedules. 이 테이블은 활동이 발생하거나로 통지 될 때 에이전트 또는 백그라운드 스레드 ( "작업 작업 업데이트", "작업 관리자"및 "작업 호출 엔진")에 의해 직접 업데이트됩니다 xp_sqlagent_notify.

그러나 이러한 테이블에서 데이터를 삭제하는 것에 대한 보호 기능이 없으므로 두 테이블을 모두 정리하는 것이 매우 쉽습니다. (예를 들어 정리하기로 결정한 경우 활동 테이블에서 해당 작업의 모든 행을 쉽게 제거 할 수 있습니다.)이 경우 SQL Server 에이전트가 다음 실행 날짜를 가져 오거나 저장하는 방법을 정확히 알 수 없습니다. 아마도 자유 시간이있을 때 나중에 더 많은 조사를 할만한 가치가있을 것입니다 ...


작업이 아직 처음으로 실행되지 않은 경우 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_date/ 를 반환하는 것으로 보입니다 next_run_time.

을 사용 sp_get_composite_job_info하여 실제로 다음을 호출하여을 검색합니다 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

때문에 sysjobschedule나타납니다 신뢰할 수, 난 그냥 사용합니다 sp_help_job.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.