首页 > 数据库 >如何调用PL/SQL系统包_DBMS_JOB与DBMS_SCHEDULER定时任务

如何调用PL/SQL系统包_DBMS_JOB与DBMS_SCHEDULER定时任务

来源:互联网 2026-04-15 19:10:33

DBMS_JOB 还在用?先看 Oracle 版本和停用风险 如果你维护的数据库版本较旧,或负责一些历史遗留系统,那么对 DBMS_JOB 包一定很熟悉。但关键信息是:自 Oracle 10g 起,DBMS_JOB 已被官方标记为“弃用”。 这意味着它虽能运行,但已非技术发展的主流方向。 在 19c

DBMS_JOB 还在用?先看 Oracle 版本和停用风险

如果你维护的数据库版本较旧,或负责一些历史遗留系统,那么对 DBMS_JOB 包一定很熟悉。但关键信息是:自 Oracle 10g 起,DBMS_JOB 已被官方标记为“弃用”。 这意味着它虽能运行,但已非技术发展的主流方向。

在 19c 及更高版本中,你或许仍可调用它,但官方明确不推荐在新项目中使用。更重要的是,它缺失了许多现代调度所需的关键功能,例如基于时间窗口的执行、与资源计划的集成,以及更完善的日志跟踪。因此,如果你的数据库已是 12c 或更高版本,且无必须维护旧脚本的硬性要求,最佳实践是:直接跳过 DBMS_JOB,从 DBMS_SCHEDULER 开始学习和使用。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

值得注意的是,这两个调度器之间存在“互不可见”的特性,常引发混淆。一个典型错误是报错:ORA-27475: “JOB_NAME” must be a job。这通常是因为开发者误将 DBMS_JOB 创建的作业当作 DBMS_SCHEDULER 的对象去查询。例如,查询 DBA_SCHEDULER_JOBS 视图却找不到任务;反之,DBA_JOBS 视图也看不到任何由 DBMS_SCHEDULER 创建的作业。

  • Oracle 10g–11g:可继续使用 DBMS_JOB 维持现有系统,但强烈建议不再为其设计新的业务逻辑。
  • Oracle 12c 及以上:所有新任务应使用 DBMS_SCHEDULER。迁移旧任务时需注意权限变更——DBMS_SCHEDULER 要求明确的 CREATE JOB 系统权限,取代了原先 DBMS_JOBCREATE PROCEDURE 权限的隐式依赖。
  • 视图隔离DBMS_JOB 创建的作业不会出现在任何 DBA_SCHEDULER_* 视图中,反之亦然,两者是完全独立的管理体系。

DBMS_SCHEDULER.CREATE_JOB 最简可用写法

初次接触 DBMS_SCHEDULER,易被其众多参数和组件(如 Schedule、Program、Job Class)困扰。其实,对于大多数一次性或简单的周期性任务,有一种更直接、不易出错的方法:内联(Inline)方式。 无需一开始就拆分组件,可先用最简写法跑通流程。

以一个典型场景为例:需每天凌晨2点执行名为 pkg_clean.upd_stats 的存储过程。使用内联方式创建作业的代码如下:

BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name        => 'DAILY_STATS_UPDATE',
    job_type        => 'STORED_PROCEDURE',
    job_action      => 'pkg_clean.upd_stats',
    start_date      => TRUNC(SYSDATE) + 2/24,
    repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0',
    enabled         => TRUE,
    comments        => 'Daily stats refresh'
  );
END;

这段代码虽简单,但几个细节至关重要:

  • job_type 的坑:该参数常见值主要有三个:'PLSQL_BLOCK'(用于执行匿名块,块内容需以分号结尾)、'STORED_PROCEDURE'(只写存储过程名,不要带括号和参数)、'EXECUTABLE'(调用操作系统命令,需额外配置凭证)。选错类型将直接导致作业失败。
  • repeat_interval 的语法:它遵循 IETF RFC 2445 标准,并非 Linux 的 cron 表达式。写 BYDAY=MON,WED,FRI 是合法的,但若写成 0 0 * * 1,3,5,则会立即收到 ORA-27467 错误。
  • start_date 的陷阱:若该参数简单写为 SYSDATE,作业会在创建成功后立即触发执行一次。许多开发者遇到的“为何刚建的作业就跑了两次?”问题,根源常在于此。

权限、所有者与运行上下文易错三处

作业创建成功,但一运行就报权限错误?这可能是 DBMS_SCHEDULER 最令人头疼的问题之一。其核心原则是:作业默认以创建者(所有者)的身份和权限在后台运行,而非以当前启用或修改它的用户身份。

常见的错误现象是:作业日志报 ORA-01031: insufficient privileges,或存储过程执行时报 ORA-00942: table or view does not exist,但手动登录该用户执行却成功。

  • 创建权限:创建作业的用户必须拥有 CREATE JOB 系统权限。DBA 角色包含此权限,但普通开发账号通常没有,需单独授权。
  • 执行权限:作业执行时,使用作业所有者的权限。关键在于:通过角色授予的权限在存储过程中无效。例如,若用户 SCOTT 创建了作业,但作业调用的过程 pkg_clean.upd_stats 内部需查询 HR.EMPLOYEES 表,则 SCOTT 必须被直接授予(Direct Grant)HR.EMPLOYEES 表的 SELECT 权限,仅通过角色拥有无效。
  • 对象引用:当作业调用的存储过程不在当前用户 Schema 下时,job_action 参数必须写全限定名。例如,应写 'hr.pkg_clean.upd_stats',仅写 'pkg_clean.upd_stats' 会导致 ORA-27477 错误。

查状态、改时间、停任务的实用命令

作业部署上线后,日常运维离不开监控和调整。无需翻阅大量官方文档,记住以下几个最实用的命令和视图即可:

  • 查看状态:想了解作业是否启用、上次运行时间、有无出错?可查询此视图:
    SELECT job_name, enabled, last_start_date, state, failure_count, additional_info
    FROM dba_scheduler_jobs
    WHERE job_name = 'DAILY_STATS_UPDATE';
  • 临时停用与恢复:想暂停作业但保留定义?使用 DBMS_SCHEDULER.DISABLE('DAILY_STATS_UPDATE');。需要时再启用:DBMS_SCHEDULER.ENABLE('DAILY_STATS_UPDATE');
  • 修改下次运行时间(慎用):DBMS_SCHEDULER.SET_ATTRIBUTE('DAILY_STATS_UPDATE', 'start_date', SYSTIMESTAMP + INTERVAL '1' HOUR);。需注意,此操作仅影响后续的调度计划点,对已生成在队列中的运行实例无效。

真正棘手的问题,常是 repeat_interval 参数写错导致作业“静默”失效。例如,本想每小时运行一次,却写成了 'FREQ=HOURLY' 而漏掉关键的 INTERVAL=1。这种情况下,Oracle 可能会静默忽略整个重复规则,作业状态显示为 ENABLED,但再也不会被触发。遇到作业不按预期运行的情况,第一步应是查询 dba_scheduler_job_log 视图,检查最近是否有 FAILEDSTOPPED 的记录,那里通常藏着问题的线索。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。