dbms_scheduler作业默认不重试——max_failures默认为0,需显式设置该值及retry_delay才启用失败后重试;restartable仅影响中断续跑,与失败重试无关。
dbms_scheduler 作业失败后不自动重试?默认就不重试
oracle dbms_scheduler 的作业(job)默认**完全不重试**——哪怕执行中抛出异常、进程被 kill、甚至数据库短暂宕机,只要没显式配置,作业就停在 failed 状态,不会自动再跑一次。
这不是 bug,是设计:它把“是否重试”“重试几次”“间隔多久”全交由 DBA 显式控制,避免隐式行为掩盖真实问题。所以看到作业状态变成 FAILED 且没后续动作,第一反应不是修调度,而是确认是否开了重试。
-
RESTARTABLE属性只影响「作业运行中途被中断」(如实例崩溃、会话断开)能否从断点续跑,和失败后的重试无关 - 真正控制失败后重试的是
MAX_FAILURES和RETRY_DELAY两个属性,必须手动设置 - 即使设置了重试,也不会无限循环;达到
MAX_FAILURES次后状态变为BROKEN,彻底停止
如何启用并配置失败重试:set_attribute 是关键
重试能力不能在 CREATE_JOB 时一并写死(12c 以前版本不支持),必须用 DBMS_SCHEDULER.set_attribute 单独设置。常见组合如下:
EXEC DBMS_SCHEDULER.set_attribute( name => 'MY_STATS_JOB', attribute => 'MAX_FAILURES', value => 3 ); EXEC DBMS_SCHEDULER.set_attribute( name => 'MY_STATS_JOB', attribute => 'RETRY_DELAY', value => 300 -- 单位:秒,即5分钟 );
-
MAX_FAILURES设为0表示禁用重试(默认值),设为正整数才生效 -
RETRY_DELAY可以是固定秒数,也可以是 PL/SQL 表达式,比如'SYSTIMESTAMP + INTERVAL ''10'' MINUTE',但注意表达式每次求值必须返回时间戳 - 修改后无需重启作业或刷新状态,下次失败立即按新规则触发重试
为什么 GATHER_STATS_JOB 看似“不重试”?它压根没开 MAX_FAILURES
系统自带的 GATHER_STATS_JOB(尤其绑定 MAINTENANCE_WINDOW_GROUP 的)默认 MAX_FAILURES = 0。这意味着:哪怕统计信息收集因锁表、空间不足、对象不存在等失败,它只记一条日志进 DBA_SCHEDULER_JOB_LOG,然后停住,不再尝试。
- 查当前值:
SELECT job_name, max_failures, retry_delay FROM dba_scheduler_jobs WHERE job_name = 'GATHER_STATS_JOB'; - 它依赖维护窗口(
MAINTENANCE_WINDOW)的周期性触发,而不是靠单次作业内部重试来兜底 - 如果你发现
SCHEDULER_JOB_LOG里连失败记录都没有,大概率是作业根本没被窗口激活——先确认窗口是否ENABLED且当前时段在窗口内(DBA_SCHEDULER_WINDOWS查ACTIVE列)
重试逻辑的隐藏限制:只对“运行时失败”有效
MAX_FAILURES 不是万能开关。以下情况它完全不干预:
- 作业状态是
DISABLED或STOPPED:根本不会启动,谈不上失败重试 - 调度(
SCHEDULE)本身失效,比如引用的WINDOW被删了,作业卡在NOT_STARTED或SCHEDULED,不会触发任何重试 - PL/SQL 程序体里用了
RAISE_APPLICATION_ERROR但没捕获,属于“运行中失败”,会走重试;但如果程序体一开始就RETURN或EXIT,没抛异常,Scheduler 认为执行成功,也不重试
真正容易被忽略的是:重试只发生在「作业已开始执行、过程中报错退出」这一窄带场景。所有前置条件检查(权限、对象存在性、窗口可用性)失败,都不算在 MAX_FAILURES 的范畴里。











