通过schedule调度program的执行的job,看到这样的形容是不是让你彻底晕头了,就说明你还是没搞明白10g中SCHEDULERS特性管理的jobs的含意,让三思更直白地给你描述描述。10g版本中SCHEDULER将JOB分成了多个部分,program负责做什么,schedule负责啥时候做,job就简单了,一个字:做。
前面几个小节,三思已经分别演示了创建管理Jobs,创建管理Programs以及创建和管理Schedules,下面我们通过实例来演示,如何创建通过schedule调度program的执行的job吧。
首先,创建一个program,操作如下:
SQL> BEGIN
2 DBMS_SCHEDULER.CREATE_PROGRAM (
3 program_name => ¨my_program1¨,
4 program_action => ¨/bin/date¨,
5 program_type => ¨EXECUTABLE¨,
6 enabled => TRUE);
7 END;
8 /
PL/SQL procedure successfully completed.通过上述语句,我们定义了一个program,执行操作系统命令date,并输入到dt.log文件中。
接下来定义一个schedule,操作如下:
SQL> begin
2 DBMS_SCHEDULER.CREATE_SCHEDULE (
3 schedule_name => ¨my_first_schedule¨,
4 start_date => SYSDATE,
5 repeat_interval => ¨FREQ= DAILY ; INTERVAL=1¨,
6 comments => ¨Every 1 weeks¨);
7 END;
8 /
PL/SQL procedure successfully completed.定义调试为每周执行一次。此处repeat_interval可根据实现情况进行修改。
最后,创建job,按照指定的schedule,执行program,操作如下:
SQL> BEGIN
2 DBMS_SCHEDULER.CREATE_JOB (
3 job_name => ¨execOScmd¨,
4 program_name => ¨my_program1¨,
5 schedule_name => ¨my_first_schedule¨,
6 enabled => true);
7 END;
8 /
PL/SQL procedure successfully completed.1.创建job
可以有两种方式来定义"计划":
1) 使用DBMS_SCHDULER.CREATE_SCHEDULE 定义一个计划;
2) 调用DBMS_SCHDULER.CREATE_JOBE过程直接指定
job_type: 目前支持三种类型:
PL/SQL块: PLSQL_BLOCK,
存储过程: STORED_PROCEDURE
外部程序: EXECUTABLE (外部程序可以是一个shell脚本,也可以是操作系统级别的指令).
job_action: 根据job_type的不同,job_action有不同的含义.
如果job_type指定的是存储过程,就需要指定存储过程的名字;
如果job_type指定的是PL/SQL块,就需要输入完整的PL/SQL代码;
如果job_type指定的外部程序,就需要输入script的名称或者操作系统的指令名
enabled: 上面已经说过了,指定job创建完毕是否自动激活
comments: 对于job的简单说明
2. 指定job的执行频率
如果我们创建了一个job,并且希望它按照我们指定的日期和时间来运行,就需要定义job的重复频度了. 例如每天运行,每周日的22:00运行, 每周一,三,五运行,每年的最后一个星期天运行等等.
(说明:10G以前的版本,与操作系统的交互方面,实现的不是很好。例如要实现一个定期的rman备份任务,就需要结合OS的命令来实现,在UNIX下可以用crontab实现,在windows下用AT命令来实现)
10G 在这方面有了很大的增强,因为创建job时可以直接指定操作系统的命令或者脚本,再合理的定义job的执行频率,可以很轻松地完成复杂的调度任务.
10G 支持两种模式的repeat_interval,一种是PL/SQL表达式,这也是dbms_job包中所使用的,例如SYSDATE+1, SYSDATE + 30/24*60; 另一种就是日历表达式。
例如MON表示星期一,SUN表示星期天,DAY表示每天,WEEK表示每周等等. 下面来看几个使用日历表达式的例子:
repeat_interval => 'FREQ=HOURLY; INTERVAL=2'
每隔2小时运行一次job
repeat_interval => 'FREQ=DAILY'
每天运行一次job
repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,WED,FRI"
每周的1,3,5运行job
repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=30'
每年的3,6,9,12月的30号运行job
用过crontab的人应该都有种似曾相识的感觉吧,呵呵
下面再说说使用日历表达式的规则:
日历表达式基本分为三部分: 第一部分是频率,也就是"FREQ"这个关键字,它是必须指定的; 第二部分是时间间隔,也就是"INTERVAL"这个关键字,取值范围是1-999. 它是可选的参数; 最后一部分是附加的参数,可用于精确地指定日期和时间,它也是可选的参数,例如下面这些值都是合法的:
BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY
BYHOUR,BYMINUTE,BYSECOND
详细的参数说明请参考 dbms_scheduler的使用说明.
既然说到了repeat_interval,你可能要问:"有没有一种简便的方法来得出,或者说是评估出job的每次运行时间,以及下一次的运行时间呢?"
dbms_scheduler包提供了一个过程evaluate_calendar_string,可以很方便地完成这个需求.
创建job时,start_date,repeat_interval,job_action等均无须指定,因为这些参数将由program和schedule来控制。
这样,操作完成后,ORACLE就会自动定时(当前设置为每周执行一次)program中定义的操作。
虽然说jobs大多都应该是自动执行,不过经过前面的示例,大家想必也认识到了,并不是说创建了jobs它就会自动执行,是否能够真正自动执行并不是由你的主观意愿就能直接决定,而是由jobs自身的多个相关属性决定。
关于jobs自动执行的话题相信看完前面的内容后,应该都知道如何设置,下面主要演示,如何手动调用jobs并执行,这其中,当然少不了DBMS_SCHEDULER包。例如,手动执行前面刚刚创建的job:INSERT_TEST_TBL:
SQL> exec dbms_scheduler.run_job(¨INSERT_TEST_TBL¨);
PL/SQL procedure successfully completedJobs 每执行一次,无论成功或失败,均会在*_SCHEDULER_JOB_LOG中生成一条对应的记录(前提是LOGGING_LEVEL属性值未设置为DBMS_SCHEDULER.LOGGING_OFF),同时,用户也可以通过*_SCHEDULER_JOB_RUN_DETAILS视图查询job执行的详细信息。
停止job可以使用DMBS_SCHEDULER.STOP_JOB过程,例如:
SQL> exec dbms_scheduler.stop_job(¨INSERT_TEST_TBL¨);
PL/SQL procedure successfully completed注意,STOP_JOB过程不仅仅是更新job的状态,而是停止当前正在执行的任务,如果你处理的任务当前未在运行的话,那么执行STOP_JOB过程,会触发ORA-27366错误。
停止Jobs也会触发一条任务的日志信息,对于执行停止操作的job,其*_SCHEDULER_JOB_LOG视图的OPERATION会记录为¨STOPPED¨,ADDITIONAL_INFO列中记录的信息类似¨REASON="Stop job called by user: username"¨。
要查看当前的执行情况,通过*_scheduler_job_run_details即可查询(*_scheduler_job_log也可以,不过该视图中信息不如detail中全面)。例如,查看刚刚创建的"EXECOSCMD"任务的执行情况,执行命令如下:
SQL> select log_id, log_date, status, additional_info
2 from user_scheduler_job_run_details
3 where job_name = ¨EXECOSCMD¨
4 ;
LOG_ID LOG_DATE STATUS ADDITIONAL_INFO
---------- -------------------- ---------- ------------------------------
13760 17-AUG-09 02.47.53.7 SUCCEEDED
34050 PM +08:00看完这个示例之后,你是否对10g中的SCHEDULER特性多了些了解呢?千万表自满,SCHEDULER特性的功能还多着哪,接着往下看吧。
============================================================================================
只用DBMS_SCHDULER.CREATE_JOB来创建job:
grant exexcute on dbms_scheduler to u1;
grant create job,create externale job to u1;
begin
dbms_scheduler.create_job
(
job_name => 'job1',
job_type => 'EXECUTABLE',
repeat_interval => 'freq=daily;interval=1',
job_action => '/home/dbtools/move_arcs.sh',
enabled => true,
comments => 'Move Archived Logs to a Different Directory'
);
end;
/
手动执行一次: exec dbms_scheduler.run_job('job1');
exec dbms_scheduler.stop_job('job1');
删除job : exec dbms_scheduler.drop_job('job1');
查看相关表 : select * from dbms_sheduler_jobs;
select * from dbms_scheduler_job_run_details;