【问题标题】:sp_start_job wait for job to finish [duplicate]sp_start_job 等待作业完成[重复]
【发布时间】:2008-12-13 13:34:54
【问题描述】:

可能重复:
Executing SQL Server Agent Job from a stored procedure and returning job result

有没有办法确定使用 sp_start_job 启动的 sql 代理作业何时完成?

【问题讨论】:

    标签: sql-server sql-server-agent


    【解决方案1】:

    article 描述了一个 SP 来启动一个 sql 代理作业并等待。

    -- output from stored procedure xp_sqlagent_enum_jobs is captured in the following table
        declare @xp_results TABLE ( 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)
    
        -- start the job
        declare @r as int
        exec @r = msdb..sp_start_job @job
    
        -- quit if unable to start
        if @r<>0
            RAISERROR (N'Could not start job: %s.', 16, 2, @job)
    
        -- start with an initial delay to allow the job to appear in the job list (maybe I am missing something ?)
        WAITFOR DELAY '0:0:01';
        set @seccount = 1
    
        -- check job run state
        insert into @xp_results
        execute master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
    
        set @running= (SELECT top 1 running from @xp_results)
    
        while @running<>0
        begin
            WAITFOR DELAY '0:0:01';
            set @seccount = @seccount + 1
    
            delete from @xp_results
    
            insert into @xp_results
            execute master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
    
            set @running= (SELECT top 1 running from @xp_results)
        end
    
        -- result: not ok (=1) if still running
    
        if @running <> 0 begin
            -- still running
            return 0
        end
        else begin
    
            -- did it finish ok ?
            set @run_status = 0
    
            select @run_status=run_status
            from msdb.dbo.sysjobhistory
            where job_id=@job_id
              and cast(run_date as bigint) * 1000000 + run_time >= @start_job
    
            if @run_status=1
                return 1  --finished ok
            else  --error
                RAISERROR (N'job %s did not finish successfully.', 16, 2, @job)
    
        end
    
        END TRY
    

    【讨论】:

    • 那篇文章对我有帮助...
    【解决方案2】:

    XP_SQLAGENT_ENUM_JOBS 可以使用,但未记录。 它通常用于检测长时间运行的作业。

    当然也有sp_help_jobs或者干脆监控作业历史表

    【讨论】:

    • 我更愿意呆在有记录的土地上。我知道 sp_help_jobs,但是它有点难看,因为据我了解,我需要将结果集读入临时表,然后从中进行选择。我一直在寻找更清洁的东西,尽管这会起作用。
    【解决方案3】:
     sp_help_job   @job_name   @execution_status = 0
    

    【讨论】:

    • sp_help_job 返回几个结果集,所以多一点代码,你如何考虑在 TSQL 的 sp_help_job 中使用它来检查正在运行的作业会比三个字的代码更有帮助,那不会甚至不加修正就跑
    【解决方案4】:
    SELECT TOP 1 1 AS FinishedRunning
    FROM msdb..sysjobactivity aj
    JOIN msdb..sysjobs sj on sj.job_id = aj.job_id
    WHERE aj.stop_execution_date IS NOT NULL
    AND aj.start_execution_date IS NOT NULL
    AND sj.name = 'YourJobNameHere'
    AND NOT EXISTS
    (
        SELECT TOP 1 1
        FROM msdb..sysjobactivity New
        WHERE New.job_id = aj.job_id
        AND new.start_execution_date > aj.start_execution_date
    )
    

    【讨论】:

      【解决方案5】:

      实际上我最近不得不这样做,这就是我正在考虑实施它的方式。我正在通过 sp_add_job 和 sp_add_jobstep 创建一个临时作业,并将 @delete_level 设置为 3(总是在运行后删除)。

      我不是 100% 接受这种方法的,正如您可能从存储过程的标题中看出的那样。但是,它确实有效:

      CREATE PROCEDURE spWorkaround_checkJobExists
      
      @job_id UNIQUEIDENTIFIER   
      , @thisIteration tinyint  
      , @maxRecurse tinyint
      
      AS
      
      IF (@thisIteration <= @maxRecurse)
      BEGIN
          IF EXISTS(
          select * FROM msdb.dbo.sysjobs where job_id = @job_id
          ) 
          BEGIN
              WAITFOR DELAY '00:00:01'
              DECLARE @nextIteration int
              SET @nextIteration = @thisIteration + 1
              EXEC dbo.spWorkaround_checkJobExists  @job_id, @nextIteration, @maxRecurse
          END
      END
      

      当然,您需要输入一些代码来确保递归的最大次数,但您明白了。您还可以传入一个参数来控制递归发生的频率。就我而言,十秒钟后,结果毫无意义。

      我在这里所做的可以通过更改选择标准来检查作业的执行状态来修改不打算在执行后立即删除的作业,例如,使用 sp_help_job 传递 @job_name 或 @job_id和@execution_status = 0。

      【讨论】:

        猜你喜欢
        • 2020-01-12
        • 1970-01-01
        • 2020-09-02
        • 2015-04-17
        • 1970-01-01
        • 2015-09-02
        • 2015-10-23
        • 1970-01-01
        • 2015-11-19
        相关资源
        最近更新 更多