更新时间:2023-12-01 GMT+08:00

创建和管理定时任务

背景信息

当客户在使用数据库过程中,如果白天执行一些耗时比较长的任务(例如:统计数据汇总之类或从其他数据库同步数据的任务),会对正常的业务有性能影响,所以客户经常选择在晚上执行,无形中增加了客户的工作量。因此数据库兼容Oracle数据库中定时任务的功能,可以由客户创建定时任务,当任务时间点到达后可以自动触发任务的执行,从而可以减少客户运维的工作量。

数据库兼容Oracle定时任务功能主要通过DBMS.JOB高级包提供的接口,可以实现定时任务的创建、任务到期自动执行、任务删除、修改任务属性(包括:任务id、任务的关闭开启、任务的触发时间、触发时间间隔、任务内容等)。

实时数仓(单机部署)暂不支持定时任务功能。

定时任务管理

  1. 创建测试表:

    1
    CREATE TABLE test(id int, time date);
    

    当结果显示为如下信息,则表示创建成功。

    1
    CREATE TABLE
    

  2. 创建自定义存储过程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE OR REPLACE PROCEDURE PRC_JOB_1()
    AS
    N_NUM integer :=1;
    BEGIN
    FOR I IN 1..1000 LOOP
    INSERT INTO test VALUES(I,SYSDATE);
    END LOOP;
    END;
    /
    

    当结果显示为如下信息,则表示创建成功。

    1
    CREATE PROCEDURE
    

  3. 创建任务:

    • 新创建的任务(未指定job_id)表示每隔1分钟执行一次存储过程PRC_JOB_1。
      1
      2
      3
      4
      5
      call dbms_job.submit('call public.prc_job_1(); ', sysdate, 'interval ''1 minute''', :a);
      job
      -----
      1
      (1 row)
      
    • 指定job_id创建任务
      1
      2
      3
      4
      5
      call dbms_job.isubmit(2,'call public.prc_job_1(); ', sysdate, 'interval ''1 minute''');
      isubmit
      ---------
      
      (1 row)
      

  4. 通过user_jobs视图查看当前用户已创建的任务信息。

    USER_JOBS视图为当前用户所属定时任务的详细信息。需要有系统管理员权限才可以访问此系统视图。

    1
    2
    3
    4
    5
    select job,dbname,start_date,last_date,this_date,next_date,broken,status,interval,failures,what from user_jobs;
    job | dbname |     start_date      |         last_date          |         this_date          |      next_date      | broken | status |      interval       | failures |           what
    -----+--------+---------------------+----------------------------+----------------------------+---------------------+--------+--------+---------------------+----------+---------------------------
    1 | gaussdb   | 2017-07-18 11:38:03 | 2017-07-18 13:53:03.607838 | 2017-07-18 13:53:03.607838 | 2017-07-18 13:54:03 | n      | s      | interval '1 minute' |        0 | call public.prc_job_1();
    (1 row)
    
    表1 USER_JOBS字段

    名字

    类型

    描述

    job

    int4

    作业ID。

    log_user

    name not null

    创建者的UserName。

    priv_user

    name not null

    作业执行者的UserName。

    dbname

    name not null

    作业创建数据库名字。

    start_date

    timestamp without time zone

    作业的开始时间。

    start_suc

    text

    作业成功执行的开始时间。

    last_date

    timestamp without time zone

    上次运行开始时间。

    last_suc

    text

    上次成功运行的开始时间。

    this_date

    timestamp without time zone

    正在运行任务的开始时间。

    this suc

    text

    正在运行任务成功的开始时间。

    next_date

    timestamp without time zone

    任务下次执行时间。

    next suc

    text

    任务下次成功执行时间。

    broken

    text

    任务状态

    如果为Y,不尝试运行此任务。

    如果为N,将尝试执行此任务。

    status

    char

    当前任务的执行状态,取值范围:('r', 's', 'f', 'd'),默认为'r',取值含义:

    • r=running
    • s=successfully finished
    • f= job failed
    • d=aborted

    interval

    text

    用来计算下次运行时间的时间表达式,如果为nul,l则表示定时任务只执行一次。

    failures

    smallint

    失败计数,作业连续执行失败16次,不再继续执行。

    what

    text

    可执行的作业。

  5. 停止任务

    1
    2
    3
    4
    5
    call dbms_job.broken(1,true);
    broken
    --------
    
    (1 row)
    

  6. 启动任务

    1
    2
    3
    4
    5
    call dbms_job.broken(1,false);
    broken
    --------
    
    (1 row)
    

  7. 修改任务属性

    • 修改JOB的Next_date参数信息
      --修改Job1的Next_date为1小时以后开始执行。
      1
      2
      3
      4
      5
      call dbms_job.next_date(1, sysdate+1.0/24);
      next_date
      -----------
      
      (1 row)
      
    • 修改JOB的Interval参数信息
      --修改Job1的Interval为每隔1小时执行一次。
      1
      2
      3
      4
      5
      call dbms_job.interval(1,'sysdate + 1.0/24');
      interval
      ----------
      
      (1 row)
      
    • 修改JOB的What参数信息
      --修改Job1的What为执行SQL语句“insert into public.test values(333, sysdate+5);”。
      1
      2
      3
      4
      5
      call dbms_job.what(1,'insert into public.test values(333, sysdate+5);');
      what
      ------
      
      (1 row)
      
    • 同时修改JOB的Next_date、Interval、What等多个参数信息
      1
      2
      3
      4
      5
      call dbms_job.change(1, 'call public.prc_job_1();', sysdate, 'interval ''1 minute''');
      change
      --------
      
      (1 row)
      

  8. 删除JOB

    1
    2
    3
    4
    5
    call dbms_job.remove(1);
    remove
    --------
    
    (1 row)
    

  9. JOB的权限控制

    • 当创建一个JOB时,该JOB会和创建该JOB的数据库和用户绑定(即:pg_job系统视图新增的JOB记录中的dbname和log_user)。
    • 如果当前用户是DBA用户、系统管理员、该JOB的创建用户(即:pg_job中的log_user),那么该用户有权限通过高级包接口remove、change、next_data、what、interval删除或修改JOB的参数信息。否则,会提示当前用户没有权限操作该JOB。
    • 如果当前数据库是该JOB创建所属的数据库(即:为pg_job系统视图中的dbname),那么连接到当前数据库上可以通过高级包接口remove、change、next_data、what、interval删除或修改JOB的参数信息。
    • 当删除JOB所属的数据库(即:为pg_job系统视图中的dbname)时,系统会关联删除该数据库从属的JOB记录。
    • 当删除JOB所属的用户(即:为pg_job系统视图中的log_user)时,系统会关联删除该用户从属的JOB记录。