任务失败主因常是环境或上下文问题而非代码错误,需查DBA_SCHEDULER_JOB_RUN_DETAILS中ERROR#和ADDITIONAL_INFO定位根因,注意大小写、资源限制、时区错位及权限链断裂等隐蔽问题。

任务状态一直失败,大概率不是代码写错了,而是环境或上下文没对齐。
查 DBA_SCHEDULER_JOB_RUN_DETAILS 里的真实错误码
别只看 DBA_SCHEDULER_JOBS.state 显示的 FAILED —— 它只是结果,不是原因。真正有用的错误信息藏在运行日志里:
-
STATUS字段是FAILED时,必须查对应LOG_DATE最近的几条记录 - 重点看
ERROR#和ADDITIONAL_INFO:比如ORA-01031、ORA-00942、REASON="manually run"都指向不同根因 - 如果
ADDITIONAL_INFO是空或只有REASON="job disabled",说明根本没跑起来,得往前查调度条件
job_action 名字大小写不匹配是最隐蔽的失败源
Oracle 对带双引号的标识符严格区分大小写,而 DBMS_SCHEDULER.CREATE_JOB 默认把未加引号的 job_action 转成大写。一旦你用 Navicat 或 SQL Developer 创建了带双引号的存储过程(如 "Automatic_clock_in"),再用 job_action => 'Automatic_clock_in' 就会找不到对象,报 ORA-27475 或静默失败。
- 查真实过程名:
SELECT object_name FROM all_objects WHERE object_type = 'PROCEDURE' AND owner = 'YOUR_SCHEMA' - 如果名字带小写或特殊字符,
job_action必须用双引号包裹:job_action => '"Automatic_clock_in"' - 更稳妥的做法:创建存储过程时不加双引号,全程用大写命名
任务“卡住”不跑,其实是被资源限制拦住了
状态显示 DISABLED 或长期 STOPPED,但日志里没错误?十有八九是底层资源不够:
-
job_queue_processes设为 0 → 所有 Scheduler 任务直接不启动(查v$parameter确认) -
MAX_JOB_SECONDARY_PROCESSES被设了非 NULL 值 → 限制并发作业数(查DBA_SCHEDULER_GLOBAL_ATTRIBUTE) -
sessions接近上限 → 每个 Scheduler job 占用 2 个 session,容易挤占(查v$session计数) - job class 绑定的服务(
service_name)已关闭或不存在 → 任务无法分配到实例(查DBA_SCHEDULER_JOB_CLASSES和GV$ACTIVE_SERVICES)
时区错位导致“明明设了时间,却从不触发”
调度器默认时区(DEFAULT_TIMEZONE)和数据库时区(DBTIMEZONE)不一致,尤其跨夏令时变更后,start_date 和 repeat_interval 可能被解释成过去时间,任务直接跳过执行窗口。
- 查三处时区:
SELECT DBTIMEZONE FROM DUAL、SELECT value FROM DBA_SCHEDULER_GLOBAL_ATTRIBUTE WHERE attribute_name = 'DEFAULT_TIMEZONE'、SELECT SESSIONTIMEZONE FROM DUAL -
start_date用SYSTIMESTAMP或显式指定时区(如TIMESTAMP '2026-07-27 02:00:00 Asia/Shanghai'),避免隐式转换 -
repeat_interval中的BYHOUR/BYMINUTE是按DEFAULT_TIMEZONE解释的,不是服务器本地时间
真正难排查的失败,往往卡在“看起来都对”的地方:权限继承链断了、PDB 没 open、job class 指向的服务早被删了——这些不会报错,只会让任务安静地躺在 DISABLED 状态里。动手前先确认 DBA_SCHEDULER_RUNNING_JOBS 是否为空,再顺着日志往回推,比反复改 repeat_interval 有用得多。


















