SQL Server 2014中能否在作业步骤失败时重试整个作业?
在SQL Server 2014中实现作业失败后从头重试的方案
好问题!SQL Server 2014的Agent作业确实没有直接的内置选项,让任意步骤失败时自动从头重试整个作业,但咱们可以通过几种变通方法实现这个需求,下面给你详细拆解:
方法1:利用作业步骤的跳转逻辑+重试计数器
这种方法是在现有作业里加个「控制步骤」,用计数器来管理重试次数:
- 先给你的作业加一个初始控制步骤(比如步骤0),用来初始化和检查重试次数。这个步骤用TSQL编写,逻辑是:统计当前重试次数,没到上限就转到步骤1开始执行,到上限就直接失败退出。
- 把原来的11个SSIS步骤依次排好,每个步骤的失败时操作都设置为「转到步骤0」,而不是默认的退出作业。
- 步骤0的「成功时操作」设置为「转到步骤1」,这样每次重试都会从头开始。
举个步骤0的TSQL示例(你可以根据实际调整):
-- 初始化重试计数器,这里用作业步骤的命令本身来存储计数(也可以用专门的表) DECLARE @RetryCount INT = 0 -- 从当前步骤的命令里提取已有的重试次数 IF CHARINDEX('DECLARE @RetryCount INT = ', @@PROCID) > 0 BEGIN SET @RetryCount = CAST(SUBSTRING(@@PROCID, CHARINDEX('=', @@PROCID)+1, 2) AS INT) END SET @RetryCount = @RetryCount + 1 -- 更新步骤0的命令,把新的计数写回去 EXEC msdb.dbo.sp_update_jobstep @job_name = N'你的作业名称', @step_id = 0, @command = N'DECLARE @RetryCount INT = ' + CAST(@RetryCount AS VARCHAR(10)) + ' -- 检查重试次数 IF @RetryCount <= 3 -- 最多重试3次 BEGIN RAISERROR(''开始第 %d 次重试,从头执行作业'', 10, 1, @RetryCount) WITH NOWAIT RETURN 0 -- 步骤成功,转到步骤1 END ELSE BEGIN RAISERROR(''已达最大重试次数,作业终止'', 16, 1) RETURN 1 END' -- 执行检查逻辑 IF @RetryCount <= 3 BEGIN RETURN 0 END ELSE BEGIN RAISERROR('已达最大重试次数,作业终止', 16, 1) RETURN 1 END
方法2:创建一个专门的重试代理作业
这种思路是把「重试触发」逻辑放到另一个独立作业里:
- 新建一个重试作业,它的唯一步骤就是用TSQL启动你的主作业,同时加个失败次数检查,避免无限重试。
- 回到你的主作业,把每个步骤的失败时操作设置为「启动另一个作业」,选择你刚创建的重试作业,还可以设置延迟(比如5分钟后再重试)。
重试作业的TSQL示例:
DECLARE @MainJobName NVARCHAR(128) = N'你的主作业名称' DECLARE @MaxRetries INT = 3 DECLARE @FailedToday INT -- 统计今日主作业的失败次数 SELECT @FailedToday = COUNT(*) FROM msdb.dbo.sysjobhistory jh JOIN msdb.dbo.sysjobs j ON jh.job_id = j.job_id WHERE j.name = @MainJobName AND jh.run_status = 0 -- 0代表作业失败 AND CONVERT(DATE, jh.run_date) = CONVERT(DATE, GETDATE()) IF @FailedToday <= @MaxRetries BEGIN -- 延迟5分钟后重试 WAITFOR DELAY '00:05:00' EXEC msdb.dbo.sp_start_job @job_name = @MainJobName PRINT '主作业失败,已触发第 ' + CAST(@FailedToday AS VARCHAR(10)) + ' 次重试' END ELSE BEGIN RAISERROR('主作业今日失败次数已达上限,停止重试', 16, 1) END
方法3:在SSIS包内部加循环控制
如果你的11个步骤是SSIS包里的任务,那可以直接在包内做文章:
- 给SSIS包加两个变量:
RetryCount(int类型,默认0)和IsPackageSuccess(bool类型,默认False)。 - 添加一个For Loop容器,把所有11个任务都放进这个容器里。
- 设置循环的条件:
@RetryCount < 3 && @IsPackageSuccess == False,循环每次执行后把RetryCount加1。 - 配置每个任务的失败规则:只要有一个任务失败,就把
IsPackageSuccess设为False,循环会重新执行所有任务;当所有任务都成功时,把IsPackageSuccess设为True,循环结束。
重要注意事项
不管用哪种方法,都要注意:
- 数据幂等性:如果作业步骤涉及数据写入(比如插入、更新),一定要确保步骤重复执行不会导致重复数据或逻辑错误(比如用唯一键约束、先删后插等方式保证幂等)。
- 重试阈值:设置合理的重试次数和延迟,避免无限重试占用系统资源,也不要太频繁重试导致雪上加霜。
内容的提问来源于stack exchange,提问作者user3115933
相关产品推荐
相关产品推荐

