SQL代理作业调度执行时无法触发依赖作业问题咨询
我创建了名为Test_Monitor Job的SQL代理作业:
- 步骤1:检查
ANOTHER_JOB是否已完成步骤1,若已完成则调用存储过程sp_start_job触发Test Steps Email completion作业; - 步骤2:延迟10分钟后检查
Test Steps Email completion作业是否已启动或完成步骤1,若未满足则发送告警邮件。
手动执行Test_Monitor Job时,所有步骤均成功,Test Steps Email completion作业也能正常触发并执行。但将其设置为每日6:15自动调度执行后,该作业本身步骤显示成功,却未触发Test Steps Email completion作业,此问题在两台服务器上均出现,请问问题出在哪里?
JOB 1: Test_Monitor Job
步骤1
BEGIN /* SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.*/ SET NOCOUNT ON; /****CHECKING TO SEE IF STEP 1 OF ANOTHER JOB IS COMPLETE ****/ /* Body */ IF EXISTS( SELECT Job.name AS JobName, Job.enabled AS ActiveStatus, JobStep.step_name AS JobStepName, JobStep.command AS JobCommand, CAST(sja.last_executed_step_date as date) lastExStepDate, sja.last_executed_step_id AS lastStep, CAST(GETDATE() AS DATE) DATE FROM EDW1.msdb.dbo.sysjobs Job INNER JOIN SERVER.msdb.dbo.sysjobsteps JobStep --table ON Job.job_id = JobStep.job_id JOIN SERVER.msdb.dbo.[sysjobactivity] sja ON Job.job_id = sja.[job_id] WHERE job.name = 'ANOTHER_JOB' AND CAST(sja.last_executed_step_date as date) = CAST(GETDATE() AS DATE) AND sja.last_executed_step_id >1) /****IF STEP 1 IS COMPLETE KICK OFF THE 'Test Steps Email completion' JOB ****/ BEGIN EXEC msdb.dbo.sp_start_job @job_name = N'Test Steps Email completion'; END /*============= Restore the count notifications --=============*/ SET NOCOUNT OFF; END
步骤2
/**Step 2-Need to pause for the time it is to take for the job to START step 1 OF 'Test Steps Email completion' ***/ WAITFOR DELAY '00:10:00.000' BEGIN /* SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.*/ SET NOCOUNT ON; /****CHECKING TO SEE IF STEP 1 OF 'Test Steps Email completion' IS COMPLETE OR STARTED ****/ /* Body */ IF NOT EXISTS( SELECT Job.name AS JobName, Job.enabled AS ActiveStatus, JobStep.step_name AS JobStepName, JobStep.command AS JobCommand, CAST(sja.last_executed_step_date as date) lastExStepDate, sja.last_executed_step_id AS lastStep, CAST(GETDATE() AS DATE) DATE FROM msdb.dbo.sysjobs Job INNER JOIN msdb.dbo.sysjobsteps JobStep --table ON Job.job_id = JobStep.job_id JOIN msdb.dbo.[sysjobactivity] sja ON Job.job_id = sja.[job_id] WHERE job.name = 'Test Steps Email completion' AND CAST(sja.last_executed_step_date as date) = CAST(GETDATE() AS DATE) AND sja.last_executed_step_id >=1) /****IF STEP 1 OF 'Test Steps Email completion' IS NOT STARTED OR COMPLETE SEND EMAIL TO DBA'S ****/ BEGIN EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Notifier Email Profile', @recipients = 'MY_EMAIL;', @body = 'DBAs the Test Steps Email completion job has not started. DBAs Please log into Server and Manually start job Test Steps Email completion!', @subject = 'ALERT!! DBAs Need to Manually start Job Test Steps Email completion on Server ASAP!' ; ; END /*============= Restore the count notifications --=============*/ SET NOCOUNT OFF; END
JOB 2: Test Steps Email completion
步骤1
EXEC msdb.dbo.sp_SQLNotify @MailTo = 'EMAIL', @Subject = 'Testing Solution for ANOTHER_JOB and Test_Monitor Job.', @Priority = 'High'
1. 核心判断条件逻辑错误
步骤1中判断ANOTHER_JOB步骤1是否完成的条件sja.last_executed_step_id >1存在问题:
- 如果
ANOTHER_JOB的步骤1对应的step_id是1(默认第一个步骤的step_id为1),那么该步骤执行完成后,last_executed_step_id的值就是1,条件>1永远不满足,自然不会触发后续作业。 - 手动执行时可能
ANOTHER_JOB已经执行到了步骤2及以后,所以条件成立;但自动调度时ANOTHER_JOB仅完成了步骤1,导致条件不触发。
解决办法:将条件改为sja.last_executed_step_id >=1,或者根据ANOTHER_JOB的实际步骤ID调整判断值,确保步骤1完成时条件能命中。
2. 远程服务器引用权限/上下文问题
步骤1的查询中使用了EDW1.msdb.dbo.sysjobs、SERVER.msdb.dbo.sysjobsteps这类四部分名称:
- 手动执行时,当前用户可能有访问远程服务器
EDW1/SERVER的权限,且上下文正确;但自动调度的作业执行账户可能没有对应的远程登录权限,或者无法解析服务器名称,导致查询返回空结果,条件不成立。 - 如果
ANOTHER_JOB实际在本地服务器,完全不需要添加服务器前缀,直接使用msdb.dbo.sysjobs、msdb.dbo.sysjobsteps即可。
解决办法:
- 确认
ANOTHER_JOB所在服务器,若在本地则去掉查询中的服务器前缀; - 若确实是远程服务器,确保作业执行账户有访问远程服务器msdb库的权限(配置链接服务器并赋予对应权限)。
3. sysjobactivity表数据读取不精确
sysjobactivity表会保留多个作业活动记录,若未筛选最新的会话记录,可能读取到旧的执行数据:
- 自动调度时,可能查询到的是之前的作业活动记录,导致日期或步骤ID判断错误。
解决办法:修改查询,加入最新会话的筛选条件,比如:
JOIN SERVER.msdb.dbo.[sysjobactivity] sja ON Job.job_id = sja.[job_id] WHERE sja.session_id = (SELECT MAX(session_id) FROM SERVER.msdb.dbo.sysjobactivity) -- 同时保留原有其他条件
4. 作业执行账户权限不足
手动执行时使用的是当前登录用户(通常是有较高权限的DBA账户),而自动调度的作业执行账户可能权限不足:
- 没有读取
msdb.dbo.sysjobs、sysjobsteps、sysjobactivity表的权限; - 没有执行
msdb.dbo.sp_start_job的权限。
解决办法:
- 将作业执行账户添加到
msdb库的SQLAgentOperatorRole角色中,该角色拥有管理作业的基本权限; - 或者单独赋予账户读取相关系统表和执行
sp_start_job的权限。
5. 时间条件的边界问题
CAST(sja.last_executed_step_date as date) = CAST(GETDATE() AS DATE)的判断可能遇到边界情况:
- 若
ANOTHER_JOB的步骤1在当天0点前执行(比如跨天执行),自动调度6:15检查时日期条件不满足;但手动执行时可能是在当天执行完ANOTHER_JOB后操作,所以条件成立。
解决办法:根据ANOTHER_JOB的实际执行时间调整日期判断逻辑,比如允许检查最近24小时内的执行记录:
AND sja.last_executed_step_date >= DATEADD(DAY, -1, GETDATE())
内容的提问来源于stack exchange,提问作者Elizabeth

