DBMS_JOB.SUBMIT 默认 broken=TRUE 导致任务不执行,需显式设 broken=>FALSE;interval 必须为带引号的PL/SQL表达式字符串;job_queue_processes=0 时任务静默失效;DBMS_JOB 与 DBMS_SCHEDULER 互不兼容。
DBMS_JOB.SUBMIT 提交后任务不执行?先查 broken 状态
oracle 旧版定时任务常卡在 broken = true,哪怕提交成功也永远不会跑。这不是调度器坏了,而是 dbms_job.submit 默认把 broken 参数设为 true —— 它只注册任务,不启动。
- 提交时显式传
broken => FALSE,否则得手动调DBMS_JOB.BROKEN(job => ..., broken => FALSE) - 检查状态用:
SELECT job, broken, last_date, next_date FROM user_jobs,别只看job编号是否存在 -
next_date为空或远超预期,大概率是broken = TRUE或interval表达式语法错(比如漏了单引号、用了中文标点)
interval 参数写法错误导致间隔失效
interval 不是秒数,也不是 cron 表达式,而是每次执行后计算下一次时间的 PL/SQL 表达式,返回 DATE 类型。写成 'sysdate + 1' 是对的,但写成 sysdate + 1(没引号)就会报错或静默失败。
- 必须用字符串包裹,且内容要能被 Oracle 当作表达式求值:
'SYSDATE + 1/24'(一小时后)、'TRUNC(SYSDATE) + 23/24'(每天22点) - 避免用
NEXT_DAY这类依赖 NLS 设置的函数,不同会话可能解析出错;优先用TRUNC+ 加减 - 如果 interval 表达式运行时报错(如除零、无效日期),该 job 会被自动置为
broken = TRUE,且不再重试
DBMS_JOB 和 DBMS_SCHEDULER 混用时 job 被静默忽略
Oracle 10g 起默认启用 DBMS_SCHEDULER,而 DBMS_JOB 是兼容层。当数据库参数 job_queue_processes = 0 时,DBMS_JOB 任务完全不触发——但不会报错,user_jobs 里仍显示正常。
- 确认参数值:
SHOW PARAMETER job_queue_processes,必须 > 0(通常设为 1000 或更高) -
DBMS_SCHEDULER的 job 不会出现在user_jobs视图里,查它要用user_scheduler_jobs;两个系统互不感知,别指望一个停掉另一个还能跑 - 新项目别碰
DBMS_JOB,老系统维护时注意:DBMS_JOB.REMOVE不会清理DBMS_SCHEDULER创建的任务
修改已提交 job 的 interval 或 what 很容易丢任务
DBMS_JOB.CHANGE 看似安全,但若在 job 正在运行时调用,可能造成逻辑冲突;更危险的是,它不校验 what 内容合法性——拼错过程名、少写分号,下次执行直接失败并置为 broken。
- 改
interval前先DBMS_JOB.BROKEN(job => ..., broken => TRUE),改完再设回FALSE,避免中间态触发 - 改
what必须确保字符串完整、结尾有分号、所有引用对象存在且权限足够;建议先在匿名块里单独执行一遍what对应的代码 - 没有“原子更新”机制:change 是两步(停+改),期间 job 可能被其他会话
run一次,导致状态混乱
真正麻烦的不是怎么写 interval,而是 job 执行体内部异常没捕获,又没日志,失败后连什么时候断的都查不到。留个 DBMS_OUTPUT.PUT_LINE 或写表日志,比反复猜 broken 原因快得多。










