oracle 19c中dbms_scheduler任务失败后默认不自动重试,需查dba_scheduler_job_log和dba_scheduler_running_jobs视图定位问题,修复根源(如权限、编译失效)后enable并手动run_job验证,或建任务时配置max_failures、restartable、retry_delay实现自动重试。

Oracle 19c 中 DBMS_SCHEDULER 任务失败后不会自动重启,必须人工干预或提前配置重试策略;监控靠查视图,重启靠 DBMS_SCHEDULER.ENABLE 或手动触发,但直接 ENABLE 不解决根本问题。
查不到失败任务?先确认你查的是哪个视图
DBA_SCHEDULER_JOB_LOG 和 DBA_SCHEDULER_RUNNING_JOBS 是唯二能反映真实运行状态的视图,DBA_JOBS 里完全看不到 DBMS_SCHEDULER 创建的任务——这是最常踩的坑。
-
DBA_SCHEDULER_JOB_LOG记录每次执行的STATUS(SUCCEEDED / FAILED)、ERROR#(如 ORA-00942)、LOG_DATE,按job_name+log_date DESC查最近 5 条最有效 -
DBA_SCHEDULER_RUNNING_JOBS只显示“正在跑”的任务,卡住的(比如长时间没更新SESSION_ID)大概率已 hang 住,不是慢,是死锁或阻塞 - 别查
DBA_JOBS或USER_JOBS——那是给DBMS_JOB用的,和DBMS_SCHEDULER完全隔离
任务状态是 DISABLED 或 STOPPED,不能只靠 ENABLE
ENABLE 只是把开关拨回 ON,但如果任务之前因权限缺失、存储过程编译失效或对象被删而失败过,再 ENABLE 会立刻再次失败。
- 先查
DBA_SCHEDULER_JOBS的STATE字段:如果是DISABLED,说明被手动停过;如果是STOPPED,大概率是运行中异常中断(比如被SHUTDOWN IMMEDIATE中断) - 再看同一行的
LAST_START_DATE和NEXT_RUN_DATE:如果NEXT_RUN_DATE是空或远在将来,说明调度链已断裂,光ENABLE没用 - 真正要做的:先修复根源(比如用
ALTER PROCEDURE pkg_clean.upd_stats COMPILE重编译),再EXEC DBMS_SCHEDULER.ENABLE('DAILY_STATS_UPDATE'),最后手动触发一次验证:EXEC DBMS_SCHEDULER.RUN_JOB('DAILY_STATS_UPDATE')
ORA-01031 或 ORA-00942 错误反复出现?权限不是当前用户的问题
DBMS_SCHEDULER 任务以 job owner 身份运行,不是你登录时的用户。即使你有 DBA 角色,job owner 没有 SELECT 权限,照样报 ORA-00942。
- 查 job owner:
SELECT owner FROM DBA_SCHEDULER_JOBS WHERE job_name = 'DAILY_STATS_UPDATE' - 如果 owner 是
SCOTT,就用SCOTT用户登录,执行GRANT SELECT ON hr.employees TO scott(假设过程里查了hr.employees) - 注意 AUTHID:存储过程必须是
AUTHID CURRENT_USER才能继承调用者权限;如果是AUTHID DEFINER(默认),那权限只看 owner 自身拥有的角色和对象权限,连 DBA 角色都不自动继承 - 临时验证法:用 owner 用户登录,直接
EXEC pkg_clean.upd_stats,如果报错,说明权限链断在最底层
想让失败任务自动重试?别依赖默认行为
DBMS_SCHEDULER 默认不重试。失败一次就停在 STOPPED 状态,下次到点也不会跑——这不是 bug,是设计如此。
- 必须显式设置重试逻辑:
max_failures+restartable+retry_delay - 建 job 时加参数:
max_failures => 3, restartable => TRUE, retry_delay => 300(失败后等 5 分钟重试,最多试 3 次) - 已有 job 修改:用
DBMS_SCHEDULER.SET_ATTRIBUTE,例如DBMS_SCHEDULER.SET_ATTRIBUTE('DAILY_STATS_UPDATE', 'max_failures', 3) - 注意:重试只对运行时错误生效(如 ORA-01403),对编译错误、权限错误、对象不存在等“启动前失败”无效——这类错误连 job 进程都进不去,直接卡在
STOPPED
最易被忽略的点:时区。19c 默认用数据库时区(DBTIMEZONE),但 start_date 如果写成 SYSTIMESTAMP,实际按服务器 OS 时区解析;两者不一致会导致 NEXT_RUN_DATE 偏移甚至为 NULL。查 DBTIMEZONE 和 SELECT SESSIONTIMEZONE FROM DUAL 对齐后再调整 job。











