dbms_scheduler
包的功能比dbms_job
包强大很多,但是很多初学者直接被它的复杂性吓跑了,跟着我,只需几分钟就会用了。
大多数人看到这个包里的函数和函数里众多的参数,就开始晕菜了,不要被这些表象迷惑了,其实这些东西都是围绕着三个基本概念,schedule
,program
和job
。oracle
是为了复用的目的,提炼出了调度的这三个要素,弄懂这三个要素,立刻豁然开朗。
schedule
表示调度计划表。调度从什么时间开始被调度,什么时候结束,以什么频度调度。使用DBMS_SCHEDULER.CREATE_SCHEDULE
过程创建schedule
。
begin
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => ¨daily_schedule¨,
start_date => SYSDATE,
repeat_interval => ¨FREQ=DAILY ; INTERVAL=1¨,
comments => ¨every one day¨);
END;
/
其中repeat_interval
参数,支持两种格式:
dbms_job
里的interval
格式,建议让这种晦涩语法见鬼去吧 linux
系统的crontab
使用的格式)日历表达式分为三部分: 第一部分是频率,也就是”FREQ
”这个关键字,它是必须指定的; 第二部分是时间间隔,也就是”INTERVAL
”这个关键字,取值范围是1-999
. 它是可选的参数; 第三部分是附加的参数,可用于精确地指定日期和时间,它也是可选的参数,下面这些值都是合法的:
BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY
BYHOUR,BYMINUTE,BYSECOND
看几个例子就会用了
每隔2小时运行一次
repeat_interval => 'FREQ=HOURLY; INTERVAL=2'
每天运行一次
repeat_interval => 'FREQ=DAILY'
每周的1,3,5运行
repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,WED,FRI"
每年的3,6,9,12月的18号运行
repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=18'
另外使用dbms_scheduler.evaluate_calendar_string
可以方便的计算出什么时候执行该调度。
program
表示调度应该做什么事情,是对程序的抽象。使用DBMS_SCHEDULER.CREATE_PROGRAM
创建program
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => ¨time_synchronization¨,
program_action => ¨/sbin/ntpdate 128.59.67.100¨,
program_type => ¨EXECUTABLE¨,
enabled => TRUE);
END;
/
调度现在可以支持调用外部程序了,这点很强大。
目前程序支持三种类型:
PL/SQL
块: PLSQL_BLOCK
, STORED_PROCEDURE
EXECUTABLE
, 外部程序可以是一个shell
脚本,也可以是操作系统级别的命令。program_action
: 根据program_type
的不同,program_action
有不同的含义。
program_type
是存储过程,就需要指定存储过程的名字; program_type
是PL/SQL
块,就需要输入完整的PL/SQL
代码; program_type
是外部程序,就需要输入script
的名称或者操作系统的指令名job
表示按照指定的schedule
,执行指定program
,完成用户指定的工作。使用DBMS_SCHEDULER.CREATE_JOB
创建job
。
SQL> BEGIN
2 DBMS_SCHEDULER.CREATE_JOB (
3 job_name => ¨time_synchron¨,
4 program_name => ¨time_synchronization¨,
5 schedule_name => ¨daily_schedule¨,
6 enabled => true);
7 END;
8 /
一般情况下是如果你设定了job
的enable
是true
的话,oracle
会按照你的计划,定时调用你的job
,不需要手动执行。如果临时需要马上调度job
也是可以的。
exec dbms_scheduler.run_job(¨time_synchron¨);
如果觉得没有必要继续执行这个job
了,可以停止该job
,让oracle
以后不要再继续调度了。
exec dbms_scheduler.stop_job(¨time_synchron¨);
Job
每执行一次,无论成功或失败,均会[DBA|ALL|USER]_SCHEDULER_JOB_LOG
中生成一条对应的记录(前提是LOGGING_LEVEL
属性值未设置为DBMS_SCHEDULER.LOGGING_OFF
),job
的详细信息可以通过[DBA|ALL|USER]_SCHEDULER_JOB_RUN_DETAILS
视图查看。
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => '"CHINA_TEST"."JOB_AUTOMODIFYINFO"',
job_type => 'STORED_PROCEDURE',
job_action => 'CHINA_TEST.AUTOMODIFYINFO',
number_of_arguments => 0,
start_date => TO_TIMESTAMP_TZ('2018-08-20 10:26:52.000000000 ASIA/SHANGHAI','YYYY-MM-DD HH24:MI:SS.FF TZR'),
repeat_interval => 'FREQ=MINUTELY;INTERVAL=2',
end_date => NULL,
enabled => FALSE,
auto_drop => FALSE,
comments => 'JOB作业说明');
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => '"CHINA_TEST"."JOB_AUTOMODIFYINFO"',
attribute => 'logging_level', value => DBMS_SCHEDULER.LOGGING_OFF);
DBMS_SCHEDULER.enable(
name => '"CHINA_TEST"."JOB_AUTOMODIFYINFO"');
END;