SQL代理作业 - 作为队列执行

时间:2009-10-28 08:01:26

标签: sql-server scheduling sql-agent-job

我有一个SQL Server作业,它使用sp_start_job调用其他10个作业。这项工作有10个步骤,每个步骤再次调用子作业。

当我执行主要工作时,我可以看到它从步骤1开始,并在几秒钟内显示“成功完成”。

但是这些作业需要很长时间才能运行,当我验证日志信息时,它会显示所有10个步骤同时在后面运行,直到几小时后完成。

我的要求是它应该先完成第1步,然后才能开始第2步。

2 个答案:

答案 0 :(得分:1)

Microsoft Code论坛可以检查存储过程是否正在运行。您可以使用它等到作业完成:

while 1=1
    begin
    WAITFOR DELAY '000:00:10'

    if not exists (
        SELECT *
        FROM master..sysprocesses p
        JOIN msdb..sysjobs j ON 
            substring(left(j.job_id,8),7,2) + 
            substring(left(j.job_id,8),5,2) +
            substring(left(j.job_id,8),3,2) + 
            substring(left(j.job_id,8),1,2) =
            substring(p.program_name,32,8)
        WHERE j.name = 'YourJobName'
        AND program_name like 'SQLAgent - TSQL JobStep (Job %'
    )
        break
    end

这样代码的工作方式是等待10秒,然后检查作业YourJobName是否正在运行。它会重复,直到工作不再运行。你可以把它放在sp_start_job调用之间。

话虽如此,必须有一种更简单的方法。你不能存储存储过程中10个作业中的每个作业的代码吗? “主”工作可以调用10个存储过程,而不是启动10个工作。

答案 1 :(得分:0)

我的第一个答案是您可以使用上面的循环,但检查msdb中的作业历史记录表以等待前一个作业完成:

select  sj.name as job_name
from    msdb.dbo.sysjobhistory sjh
    inner join msdb.dbo.sysjobs_view sj on sj.job_id = sjh.job_id
where   sjh.step_id = 0 --Job outcome
    and sjh.run_status = 4 --In progress

谢谢Andomar提出质疑。事实证明,只有在第一步完成后才会更新sysjobhistory。只有白痴会想象,如果run_status的一个值是'进行中',那么当步骤开始时必须更新表!我四处寻找,这似乎是一个棘手的问题。某处SQL知道发生了什么,但它没有很好地公开信息。

您似乎必须在数英里之间选择复杂的代码或使用未记录的存储过程。您可以轻松找到代码答案的里程数 - 有几个 - 通过谷歌搜索sysjobhistory。我个人更喜欢xp方法:

create table #xp_results(
    job_id uniqueidentifier not null,
    last_run_date int not null,
    last_run_time int not null,
    next_run_date int not null,
    next_run_time int not null,
    next_run_schedule_id int not null,
    requested_to_run int not null, -- bool
    request_source int not null,
    request_source_id sysname collate database_default null,
    running int not null, -- bool
    current_step int not null,
    current_retry_attempt int not null,
    job_state int not null )

insert #xp_results exec master.dbo.xp_sqlagent_enum_jobs @is_sysadmin = 1, @job_owner = ''

select  sj.name
from    #xp_results xpr
    inner join msdb.dbo.sysjobs_view sj on sj.job_id = xpr.job_id
where running = 1

drop table #xp_results

我已经对此进行了测试,它似乎确实有效。使用这个xp可能有风险,但这就是Job Activity Monitor使用的 - 我用Profiler运行它 - 所以如果它改变了,它们可能会提供一些其他方法来查找这些信息。只要你将这段代码包装在一个函数或proc和文档中你依赖它,对我来说似乎是最少的祸害。