4

我有几个应该按顺序运行的 SQL Server 代理作业。为了对应该执行的作业有一个很好的概述,我创建了一个主作业,它通过调用EXEC msdb.dbo.sp_start_job N'TEST1'. 立即完成(作业步骤 1),但我希望我的sp_start_job主要作业等到作业TEST1完成后再调用下一个作业。

所以我编写了这个小脚本,它在调用作业后立即开始执行(作业步骤 2),并强制主作业等到子作业完成:

WHILE 1 = 1
  BEGIN
    WAITFOR DELAY '00:05:00.000';

    SELECT *
    INTO   #jobs
    FROM   OPENROWSET('SQLNCLI', 'Server=TESTSERVER;Trusted_Connection=yes;',
           'EXEC msdb.dbo.sp_help_job @job_name = N''TEST1'',
           @execution_status = 0, @job_aspect = N''JOB''');

    IF NOT (EXISTS (SELECT top 1 * FROM #jobs))
      BEGIN
        BREAK
      END;

    DROP TABLE #jobs;

  END;

这工作得很好。但我觉得更聪明和/或更安全(WHILE 1 = 1?)的解决方案应该是可能的。

我对以下事情感到好奇,希望您能给我一些见解:

  • 这种方法有什么问题?
  • 你能建议一个更好的方法来做到这一点吗?

(我也在dba.stackexchange.com上发布了这个问题,也是为了从少编程多 dba 的观点中获利。)

4

2 回答 2

3

如果您选择轮询表,那么您需要查看 msdb.dbo.sysjobhistory 并等到run_status不是 4。不过仍然会很烦。

对于作业的最后一步(失败或成功),可能有一种不同的方法,在该过程已完成的“主”作业服务器上创建一个条目,然后您只需在本地查看。通过在集中式作业服务器上合并开始和停止,还可以更轻松地追踪“到底发生了什么”。

第三种也是更强大的方法是使用Service Broker之类的东西来处理进程之间的通信和信令。这将需要更多的设置,但它将是进程之间通信的最机制。

于 2012-07-13T21:41:39.453 回答
0

方法没有问题。我所做的只是有点像您的要求,并且由于其他一些原因,我使用了 msdb 中的 sysjobhistory 表来查看运行状态。

回到您的问题,请使用相同的方法参考 msdb.dbo.sp_start_job 存储过程,并且它已被一个默认 Microsoft BizTalk 作业“MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb”用于调用另一个相关的默认 biztalk 作业“MessageBox_Message_Cleanup_BizTalkMsgBoxDb”。甚至在 BizTalk 消息框中有一个存储过程来检查作业的状态。请参阅 BizTalk 消息框中的“int_IsAgentJobRunning”。

于 2013-01-31T07:14:22.593 回答