PolarDB提供DBMS_JOB包调度与管理定时任务。本文为您介绍如何创建、管理和删除一个定时任务。
前提条件
- DBMS_JOB支持用户自行通过配置参数开启。方法如下:
- 登录PolarDB控制台,找到目标集群。
- 在左侧导航栏中,选择 。
- 在shared_preload_libraries参数的插件列表中添加
dbms_job
。
- PolarDB集群的内核版本为V1.1.7及以上版本。如何查看内核版本,请参见新版本更新说明。
注意事项
- DBMS_JOB仅支持高权限用户使用。如何创建高权限账号,请参见创建数据库账号。
- 由于安全原因,DBMS_JOB插件暂时不支持用户手动创建,如有需要,请前往配额中心,在配额名称PolarDB PG dbms_job使用的操作列,单击申请,申请创建。
- 如果之前安装过DBMS_JOB相关插件,需要先删除相关插件,然后参考本文重新安装。删除插件语法如下:警告 删除插件会同时删除相关定时任务,请务必提前备份。
drop extension dbms_job;
- 目前仅支持在
postgres
库中创建DBMS_JOB插件,如果您需要在其他库中使用定时任务,可以在postgres
库中配置跨库任务。具体操作,请参见跨库执行定时任务。
准备测试数据
说明 测试数据仅适用本文中的操作示例。
创建一张名为
jobrun
的表用于测试,示例如下:CREATE TABLE jobrun (
id serial NOT NULL PRIMARY KEY,
runtime VARCHAR2(40)
);
创建一个名为
job_proc
的存储过程,示例如下:CREATE PROCEDURE job_proc
IS
BEGIN
INSERT INTO jobrun(runtime) VALUES ('job_proc run at ' || TO_CHAR(SYSDATE, 'yyyy-mm-dd hh24:mi:ss'));
END;
删除插件
警告 删除插件时会删除所有已有的用户任务。
删除插件语法如下:
DROP EXTENSION dbms_job CASCADE;
创建定时任务
语法
调用
SUBMIT(job OUT BINARY_INTEGER, what VARCHAR2
[, next_date DATE [, interval VARCHAR2 ]])
参数 | 说明 |
---|---|
job | 请传入jobid ,用于返回本次提交任务的ID。该ID自动生成且对每个任务都唯一。 |
what | 调用存储过程名称,不可为空。本次示例中使用了job_proc 存储过程。 |
next_date | 定时任务的开始时间,如果不传入则默认为当前时间。 |
interval | 定时任务的执行间隔。具体内容,请参见INTERVAL参考。 |
定时任务执行间隔 | 示例 |
---|---|
每分钟执行 |
|
每天定时执行 | 每天凌晨1点执行:
|
每周定时执行 | 每周一凌晨1点执行:
|
每月定时执行 | 每月1日凌晨1点执行:
|
每季度定时执行 | 每季度的第一天凌晨1点执行:
|
每年定时执行 | 每年1月1日凌晨1点执行:
|
固定时间点执行 | 每天早上的8点10分运行:
|
固定时间间隔执行 | 每个小时的第15分钟运行,例如8点15分、9点15分、10点15分等。
|
job_proc
存储过程创建一个定时任务,示例如下:DECLARE
jobid INTEGER;
BEGIN
DBMS_JOB.SUBMIT(jobid,'job_proc;', SYSDATE, 'SYSDATE + 1/(24 * 60)');
END;
说明 如果定时任务中的时间使用了单引号,这种嵌套会导致语法错误,错误示例如下:
DBMS_JOB.SUBMIT(jobid,'job_proc;', SYSDATE, 'TRUNC(sysdate,'mi') + 1/(24*60)');
您需要将对应的参数改为$$
的形式来避免这种错误,正确示例如下:
DBMS_JOB.SUBMIT(jobid,'job_proc;', SYSDATE, $$TRUNC(sysdate,'mi') + 1/(24*60)$$);
修改定时任务的内容、执行时间和执行间隔
语法
修改任务ID为1的定时任务,调用的存储过程不变,定时任务开始时间修改为2020年12月29日,任务执行间隔设置为每个小时的15分执行一次。示例如下:
CHANGE(job BINARY_INTEGER what VARCHAR2, next_date DATE,interval VARCHAR2)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
what | 调用存储过程名称。 说明 如果保持当前值不变,可将此参数设置为 NULL 。 |
next_date | 定时任务的开始时间。 说明 如果保持当前值不变,可将此参数设置为 NULL 。 |
interval | 定时任务的执行间隔。具体内容,请参见INTERVAL参考。 说明 如果保持当前值不变,可将此参数设置为 NULL 。 |
BEGIN
DBMS_JOB.CHANGE(1,NULL,TO_DATE('29-DEC-20','DD-MON-YY'),$$Trunc(sysdate,'hh') + (60+15)/(24*60)$$);
END;
修改定时任务的执行间隔
语法
修改任务ID为1的定时任务,任务执行间隔修改为每天凌晨1点执行一次。示例如下:
INTERVAL(job BINARY_INTEGER, interval VARCHAR2)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
interval | 定时任务的执行间隔。具体内容,请参见INTERVAL参考。 |
BEGIN
DBMS_JOB.INTERVAL(1,'TRUNC(sysdate) + 1 + 1/(24)');
END;
修改定时任务的执行时间
语法
修改任务ID为1的定时任务,定时任务开始时间设置为2020年12月30日。示例如下:
NEXT_DATE(job BINARY_INTEGER, next_date DATE)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
next_date | 定时任务的开始时间。 |
BEGIN
DBMS_JOB.NEXT_DATE(1, TO_DATE('30-DEC-20','DD-MON-YY'));
END;
修改定时任务的内容
语法
修改任务ID为1的定时任务,将调用的存储过程改为
WHAT(job BINARY_INTEGER, what VARCHAR2)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
what | 调用的存储过程名称。 |
job_proc2
。示例如下:BEGIN
DBMS_JOB.WHAT(1,'job_proc2');
END;
停止和启动定时任务
语法
将任务ID为1的定时任务设置为已损坏状态。示例如下:
BROKEN(job BINARY_INTEGER, broken BOOLEAN [, next_date DATE ])
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
broken | 定时任务的状态,取值如下:
|
next_date | 定时任务的开始时间,如果不传入则默认为当前时间。 |
BEGIN
DBMS_JOB.BROKEN(1,true);
END;
将任务ID为1的定时任务设置为正常运行状态。示例如下:BEGIN
DBMS_JOB.BROKEN(1,false);
END;
强制启动定时任务
语法
强制启动任务ID为1的定时任务。示例如下:
RUN(job BINARY_INTEGER)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
BEGIN
DBMS_JOB.RUN(1);
END;
删除定时任务
语法
删除任务ID为1的定时任务。示例如下:
REMOVE(job BINARY_INTEGER)
参数 | 说明 |
---|---|
job | 任务ID,如何查看请参见查看定时任务。 |
BEGIN
DBMS_JOB.REMOVE(1);
END;
查看定时任务
您可以通过如下语句查看当前用户创建的定时任务列表:
select * from sys.user_jobs;
查看任务执行记录
您可以通过如下语句查看定时任务的执行记录:
select * from dbmsjob.pga_joblog;
跨库执行定时任务
由于DBMS_JOB只能配置在postgres
库,其他库如果需要设置定时任务则需要进行跨库任务。
以下示例中,DBMS_JOB的配置库为postgres
,运行库为test
,需要在test
库中的某张表每分钟插入一条数据。如何创建数据库,请参见创建数据库。
- 在
test
库中创建一个名为jobrun
的表和一个名为job_proc
的存储过程。- 创建名为
jobrun
的表,命令如下:CREATE TABLE public.jobrun ( id serial NOT NULL PRIMARY KEY, runtime VARCHAR2(40) );
- 创建名为
job_proc
的存储过程,命令如下:CREATE PROCEDURE public.job_proc IS BEGIN INSERT INTO jobrun(runtime) VALUES ('job_proc run at ' || TO_CHAR(SYSDATE, 'yyyy-mm-dd hh24:mi:ss')); END;
- 创建名为
- 切换到
postgres
库,创建定时任务。您需要在
DBMS_JOB.SUBMIT()
函数中添加目标库,本例中目标库名为test
。其他参数请参见创建定时任务。示例如下:DECLARE jobid INTEGER; BEGIN DBMS_JOB.SUBMIT(jobid,'job_proc;', SYSDATE, 'SYSDATE + 1/(24 * 60)','test'); END;
- 在
postgres
中查看定时任务的状态和执行记录。- 查看定时任务:
返回结果如下:select * from sys.user_jobs;
job | jobloguser | job_user | database | job_created | job_changed | last_date | last_sec | next_date | next_sec | total_time | broken | interval | failures | what | instance -----+------------+----------+----------+----------------------------------+----------------------------------+----------------------------------+----------+---------------------------+----------+-----------------+--------+------------------------------------------+----------+-----------------------------------------------------------------------------------------------------------------+---------- 1 | DBUSER | dbuser | postgres | 29-OCT-20 02:38:49.478494 +00:00 | 29-OCT-20 02:38:49.478494 +00:00 | 29-OCT-20 02:51:12.025001 +00:00 | 02:51:12 | 29-OCT-20 02:53:12 +00:00 | 02:53:12 | 00:00:00.243224 | N | BEGIN return SYSDATE + 1/(24 * 30); END; | 0 | BEGIN EXECUTE IMMEDIATE 'SELECT dbmsjob.dbms_job_internal_job_link(''BEGIN job_proc; END;'', ''test'');' ; END | 0
- 查看执行记录:
返回结果如下:select * from dbmsjob.pga_joblog;
jlgid | jlgjobid | jlgstatus | jlgstart | jlgduration -------+----------+-----------+----------------------------------+----------------- 1 | 1 | s | 29-OCT-20 02:38:49.762995 +00:00 | 00:00:00.017495 2 | 1 | s | 29-OCT-20 02:39:50.061113 +00:00 | 00:00:00.016463 3 | 1 | s | 29-OCT-20 02:40:50.062331 +00:00 | 00:00:00.016244
- 查看定时任务:
- 切换到
test
库,查看表中数据。查询命令如下:
查询结果如下:select * from jobrun;
id | runtime ----+------------------------------------- 1 | job_proc run at 2020-10-29 02:38:50 2 | job_proc run at 2020-10-29 02:39:50 3 | job_proc run at 2020-10-29 02:40:50
说明 如果您需要修改跨库任务的信息,需要在修改函数时附加对应的数据库名称。例如将上述示例中每分钟运行一次的计划改为每两分钟运行一次,示例如下:
BEGIN
DBMS_JOB.CHANGE(1,NULL,SYSDATE,'SYSDATE + 1/(24 * 30)','test');
END;