DBMS_JOB在Oracle 19c已退化为DBMS_SCHEDULER兼容层,迁移是强制要求;两者元数据隔离、权限模型不同,须用对应视图查询和操作;推荐内联创建job,注意时间时区、执行权限及RAC调度控制。

DBMS_JOB 在 Oracle 10g 就被标记为 deprecated,12c 起新任务必须用 DBMS_SCHEDULER;不是“不推荐”,而是架构级替代——DBMS_JOB 在 19c 实际已退化为 DBMS_SCHEDULER 的兼容层,所有 job 都转成 scheduler 对象存储。迁移不是可选项,是版本升级后的事实要求。
ORA-27475 或查不到 job:视图和对象完全隔离
DBMS_JOB 创建的 job 只出现在 DBA_JOBS、USER_JOBS 中;DBMS_SCHEDULER 创建的 job 只在 DBA_SCHEDULER_JOBS、ALL_SCHEDULER_JOBS 里可见。两者元数据互不可见,权限模型也不同。
- 误用
SELECT * FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME = 'MYJOB'查 DBMS_JOB 创建的任务 → 返回空,不是没建成功,是根本不在这个视图里 - 用
DBMS_SCHEDULER.ENABLE操作一个 DBMS_JOB 名字 → 报ORA-27475: "MYJOB" must be a job,因为 scheduler 找不到该对象 - 权限上:
CREATE JOB系统权限才能建 scheduler job;而 DBMS_JOB 只需对象执行权,且不校验角色继承
最简迁移写法:别套三层对象,先用 inline 模式跑通
很多团队卡在“要不要先建 PROGRAM 和 SCHEDULE”,其实大可不必。对大多数日更、小时级任务,直接用 CREATE_JOB 内联定义最稳,避免对象依赖和清理麻烦。
-
job_type选'STORED_PROCEDURE'时,job_action只写过程名,不带括号和参数,例如'pkg_clean.upd_stats' - 要传参?必须切到
'PLSQL_BLOCK',且块内语句结尾要加分号,例如'BEGIN pkg_clean.upd_stats(SYSDATE-1, SYSDATE); END;' -
start_date别写SYSDATE,否则 job 创建完立刻执行一次——常见“刚建就跑两次”问题根源 -
repeat_interval是 RFC 2445 格式,不是 cron:'FREQ=DAILY; BYHOUR=2; BYMINUTE=0'合法,'0 0 * * *直接报ORA-27467
权限与运行身份:创建者 ≠ 执行者
DBMS_SCHEDULER job 默认以 job owner 身份运行,但真正能执行成功,取决于 owner 是否有目标对象的 EXECUTE 权限——不是当前登录用户,也不是通过角色授予的权限。
- 如果 job 调用
pkg_clean.upd_stats,owner 必须显式被授予EXECUTE ON pkg_clean.upd_stats,不能靠DBA角色隐含获得 - job 在 RAC 环境下可能跨实例调度,
job_class若未指定,默认走DEFAULT_JOB_CLASS,其关联的 service 和 instance affinity 可能导致执行不稳定 - 旧 DBMS_JOB 任务若依赖
DBMS_JOB.INSTANCE绑定节点,迁移到 scheduler 后得改用job_class+ service 控制,不能留空
真正容易被忽略的是时间表达式的“隐式截断”:比如 TRUNC(SYSDATE) + 2/24 看似稳妥,但在跨时区数据库或 session 时区非 UTC 时,start_date 存入字典会按数据库时区解释,后续 repeat_interval 却按服务器时区计算——同一 job 在不同环境表现可能不一致。务必统一用 TIMESTAMP WITH TIME ZONE 显式声明时区,而不是依赖默认行为。


















