DBMS_SCHEDULER作业需显式设置MAX_FAILURES和RESTART_ON_FAILURE才能重试,否则默认失败即停;重试时间由REPEAT_INTERVAL对齐,非立即执行,且须配合STOP_ON_WINDOW_CLOSE=>FALSE及DBLINK可用性检查。
DBMS_SCHEDULER 作业必须显式配置 MAX_FAILURES 才能重试
dbms_job 没有原生重试能力,而 dbms_scheduler 虽然支持失败后重试,但默认 max_failures 是 0——这意味着失败一次就永久停摆,不会自动重试。不手动设置,和 dbms_job 实际表现一样。
实操建议:
- 创建作业时必须显式调用
DBMS_SCHEDULER.SET_ATTRIBUTE设置MAX_FAILURES,例如:DBMS_SCHEDULER.SET_ATTRIBUTE('MV_REFRESH_JOB', 'MAX_FAILURES', 3) -
RESTART_ON_FAILURE => TRUE必须同时启用,否则即使设了MAX_FAILURES也不会触发重试 - 别依赖
REPEAT_INTERVAL自动兜底:它只控制“下一次正常调度”,不接管失败后的重试节奏;重试间隔由RESTART_ON_FAILURE和底层调度窗口决定
RESTART_ON_FAILURE = TRUE 不等于立即重跑
很多人误以为开启 RESTART_ON_FAILURE 就会秒级重试,其实 Oracle 的重试是“按原定时间点对齐”的:失败后不是立刻重跑,而是等待下一个符合 REPEAT_INTERVAL 的合法调度时刻再尝试。
实操建议:
- 若需 5 分钟内重试,
REPEAT_INTERVAL必须设为FREQ=MINUTELY; INTERVAL=5,不能写成DAILY或HOURLY - 凌晨 2:00 的作业失败后,即使设了
RESTART_ON_FAILURE => TRUE,下一次尝试仍是 2:05,不是 2:00:05 - 务必配合
STOP_ON_WINDOW_CLOSE => FALSE,否则维护窗口(如MAINTENANCE_WINDOW)关闭会导致作业被强制终止且不再重试
DBLINK 断开时 DBMS_SCHEDULER 也静默失败,不重试
DBMS_MVIEW.REFRESH 本身不感知 DBLINK 状态,也不抛出异常——它直接跳过刷新、不更新 LAST_REFRESH_DATE、不记录错误到 DBA_MVIEW_REFRESH_LOGS。DBMS_SCHEDULER 只是执行这个函数,无法绕过这个限制。
实操建议:
- 查真实失败记录只能去
USER_SCHEDULER_JOB_LOG,过滤STATUS = 'FAILED'(注意不是'ERROR') - 验证 DBLINK 是否真实可用,必须执行
SELECT * FROM DUAL@your_dblink,不能只查DBA_DB_LINKS - 没有“连接池”或“超时重试”参数可配;唯一可行的兜底是:在 scheduler job 的
WHAT中包装一层 PL/SQL 块,先做ping再调REFRESH,并捕获ORA-02019或ORA-02068
自动重试掩盖日志缺失等根本问题,必须前置检查
盲目开启重试,可能让 MLOG$_xxx 日志堆积、STALENESS = 'UNUSABLE' 长期不暴露,最终导致 COMPLETE 刷新卡死或锁表数小时。
实操建议:
- 每次重试前,应检查
USER_MVIEW_LOGS中对应基表的SEQUENCE和ROWIDS是否为'YES';若为'NO',FAST必失败,重试无意义 - 查
DBA_MVIEWS.STALENESS,若值为'UNUSABLE'或'NEEDS_COMPILE',必须先ALTER MATERIALIZED VIEW ... COMPILE - 用
DBMS_MVIEW.EXPLAIN_MVIEW+MVIEW_EXCEPTIONS提前验证 FAST 可行性,比靠重试撞墙更可靠











