我有很多工作需要运行,但它们不能同时运行。每个检查的第一步都是检查是否有其他人正在运行,如果是,它会稍等片刻并再次检查。这可能导致两个作业相互等待完成的锁定情况。
内置重试不起作用,因为它们在等待重试时被认为正在运行。我可以出错并让作业每 10 分钟运行一次,检查它上次成功运行的时间以及是否有其他人正在运行。然后再次运行或出错,但这可能会导致作业发生偏离计划。
我环顾四周,但找不到任何东西,所以我不知道这是否可能,但你能设置一个时间表,比如此时从另一个工作中运行这个工作吗?
或者有没有我忽略的更好的方法?
是的,确实可以!因此,您希望完成一项工作,而该工作的最后一步是开始另一项工作?这是启动下一个作业的命令:sp_start_job
例如,第一个作业有一个时间表,作业的最后一步是运行:
《我的第二份工作》没有时间表,靠第一份工作开始。
在更多的研究和深入研究我发现并正在使用的 msdn 站点文档中。
sp_add_schedule、sp_attach_schedule 和 sp_detach_schedule、sp_delete_schedule
所以当工作看到其他人正在运行 ATM 时,我正在这样做:
然后下次运行作业时,也会这样做以删除临时计划:
使用此解决方案,您可以通过简单的选择表轻松了解队列中要运行的作业。此外,如果服务器由于某种原因出现故障,清理等待运行的作业就像截断表一样容易。而且,如果你想让它们运行,你不需要做任何事情,它们就会有条不紊地运行。
ScheduleLonelyJobsTable
)来存储有关等待单独运行的作业的信息 - 一列用于job_id
,一列用于datetime_request
。该表在每个时刻都应该很小,但您可以在最后一列上建立索引。(可选)添加一列stepToRun
。job_id
和GETDATE()
插入此表中,然后跳出(在该步骤之后退出作业)。可以选择在列中插入stepToRun
作业第二步的名称,这实际上是执行您想要在作业中执行的操作的第一步。stepToRun
,那么您无需再做任何事情。否则,给第二步起一个标准名称,如“LonelyJobStartStep
”。创建一个新作业,用于管理所有单独的作业,以所需的频率运行(例如每 10 秒)。该作业将只有一个步骤,即在 if 中执行以下查询,以检查是否没有作业正在运行:
DECLARE @job_id_torun uniqueidentifier SET @job_id_torun = ( SELECT TOP 1 job_id FROM dbo.ScheduleLonelyJobsTable ORDER BY datetime_request) IF @job_id_torun IS NOT NULL BEGIN -- If a job gets twice on the table, both entries will be removed. If this is not the desired behaviour just delete the oldest entry DELETE FROM dbo.ScheduleLonelyJobsTable WHERE job_id = @job_id_torun -- Obtain the @step_name from the ScheduleLonelyJobsTable table if you added the optional column, otherwise just use a standard name like bellow EXEC msdb.dbo.sp_start_job @job_id=@job_id_torun, @step_name = 'LonelyJobStartStep'; END