Oralce调度 揭开job,scheduler,program,chain,job_class,window,window_group神秘面纱

今天和大家分享一下

1.作业(job),2.调度(scheduler),3.程序(program),4.链(chain),4.作业类(job_class),5.窗口(window),6.窗口组(window_group)

彻底揭开他们神秘的面纱。

在oracle 8i,9i中使用dbms_job方式留作业。其限制有二。
一是调度的时间不好控制,不太灵活,对时间的间隔难于把握。
二是不能调度操作系统的脚本,只能调度数据库内的程序或者语句。
随着技术的发展,oracle在10g,11g 中推出了新的一代调度程序dbms_scheduler,这个程序克服了上面的两个缺点。
下面我们介绍如何使用调度程序dbms_scheduler。

我们首先了解一下时间间隔的问题。
repeat_interval => 'FREQ=MINUTELY; INTERVAL=30'
这句话的含义为:每30分钟运行重复运行一次!
repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=30'  
这句话的含义为:每年的3,6,9,12月的30号运行job
一眼看上去格式有点乱,没有章法,不如以前的时间间隔明白。因为我们不知道格式的含义。
日历表达式基本分为三部分:
第一部分是频率,也就是"FREQ"这个关键字,它是必须指定的;
第二部分是时间间隔,也就是"INTERVAL"这个关键字,取值范围是1-999. 它是可选的参数;
最后一部分是附加的参数,可用于精确地指定日期和时间,它也是可选的参数,例如下面这些值都是合法的:
BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY,BYHOUR,BYMINUTE,BYSECOND
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,你可能要问:“有没有一种简便的方法来得出,或者说是评估出job的每次运行时间,以及下一次的运行时间呢?”
dbms_scheduler包提供了一个过程evaluate_calendar_string,可以很方便地完成这个需求. 来看下面的例子:

declare
L_start_date TIMESTAMP;    --声明需要的变量
l_next_date TIMESTAMP;
l_return_date TIMESTAMP;
begin
l_start_date := trunc(SYSTIMESTAMP); --取当前的时间
l_return_date := l_start_date;
for ctr in 1..10 loop      --循环10次
dbms_scheduler.evaluate_calendar_string(
'FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=7,15',
l_start_date, l_return_date, l_next_date);
dbms_output.put_line('Next Run on: ' ||
to_char(l_next_date,'mm/dd/yyyy hh24:mi:ss')); --打印下次运行的时间
l_return_date := l_next_date;
end loop;
end;
/


结果如下:
Next Run on: 08/08/2014 07:00:00
Next Run on: 08/08/2014 15:00:00
Next Run on: 08/11/2014 07:00:00
Next Run on: 08/11/2014 15:00:00
Next Run on: 08/12/2014 07:00:00
Next Run on: 08/12/2014 15:00:00
Next Run on: 08/13/2014 07:00:00
Next Run on: 08/13/2014 15:00:00
Next Run on: 08/14/2014 07:00:00
Next Run on: 08/14/2014 15:00:00

我们看一下数据库自己带的调度的时间间隔。

SQL>select job_name,repeat_interval from dba_scheduler_jobs;
JOB_NAME                       REPEAT_INTERVAL
------------------------------ ------------------------------------------
AUTO_SPACE_ADVISOR_JOB
GATHER_STATS_JOB
FGR$AUTOPURGE_JOB              freq=daily;byhour=0;byminute=0;bysecond=0
PURGE_LOG
RLM$SCHDNEGACTION              FREQ=MINUTELY;INTERVAL=60
RLM$EVTCLEANUP                 FREQ = HOURLY; INTERVAL = 1
 

已选择6行。
我们发现有6个作业存在,但只有3个有时间的间隔。
很好理解,每天0点运行,其它的为间隔1小时运行,但为什么有3个没有时间间隔呢?

col SCHEDULE_NAME for a25
SQL> select JOB_NAME,REPEAT_INTERVAL,SCHEDULE_NAME from DBA_SCHEDULER_JOBS;
 
JOB_NAME                REPEAT_INTERVAL                               SCHEDULE_NAME
----------------------- --------------------------------------------- ------------------------
AUTO_SPACE_ADVISOR_JOB                                                MAINTENANCE_WINDOW_GROUP
GATHER_STATS_JOB                                                      MAINTENANCE_WINDOW_GROUP
FGR$AUTOPURGE_JOB       freq=daily;byhour=0;byminute=0;bysecond=0
PURGE_LOG                                                             DAILY_PURGE_SCHEDULE
RLM$SCHDNEGACTION       FREQ=MINUTELY;INTERVAL=60
RLM$EVTCLEANUP          FREQ = HOURLY; INTERVAL = 1
 

已选择6行。
我们看到一个现象,有时间间隔的没有调度的名称,有调度名称的就没有时间间隔。
那什么是调度呢?数据库为常用的时间间隔编写一个程序策略。叫做调度(scheduler)。
例如:
一个任务计划执行的时间策略.比如我们想要创建一个晚上3点执行的任务计划,就可以创建一个调度,凡是符合这个调度要求的,都可以调用这个我们预先创建好的调度.可以用dbms_scheduler.create_schedule来创建一个调度.

比如我创建一个名字叫MYTEST_SCHEDULE的调度,每天4:00执行.

  dbms_scheduler.create_schedule(
   repeat_interval => 'FREQ=DAILY;BYHOUR=4;BYMINUTE=0;BYSECOND=0',
  start_date => systimestamp at time zone 'PRC',
   comments => '---this is my test schedule---',
  schedule_name => 'MYTEST_SCHEDULE');
END;
/

上面我们看到PURGE_LOG的作业调度为DAILY_PURGE_SCHEDULE。

 2 SCHEDULE_NAME='DAILY_PURGE_SCHEDULE';
 
REPEAT_INTERVAL
---------------------------------------------
freq=daily;byhour=3;byminute=0;bysecond=0

我们看到了该策略为每天3点运行。
但GATHER_STATS_JOB的调度为MAINTENANCE_WINDOW_GROUP,这又是什么呢?
这是窗口组!

 
WINDOW_GROUP_NAME              WINDOW_NAME
------------------------------ -------------------
MAINTENANCE_WINDOW_GROUP       WEEKNIGHT_WINDOW
MAINTENANCE_WINDOW_GROUP       WEEKEND_WINDOW

我们看到维护窗口组MAINTENANCE_WINDOW_GROUP中有两个窗口。
窗口又是什么呢?

SQL> COL REPEAT_INTERVAL FOR A79
SQL> SELECT WINDOW_NAME,REPEAT_INTERVAL FROM DBA_SCHEDULER_WINDOWS;
WINDOW_NAME          REPEAT_INTERVAL
-------------------- ---------------------------------------------------------------------
WEEKNIGHT_WINDOW     freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0
WEEKEND_WINDOW       freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0

平时每天晚上10点运行,周六0点运行!

窗口(window):

可以看成是一个更高功能的调度,窗口可以调用系统中存在的调度(也可以自行定义执行时间),而且,具有资源计划限制功能,窗口可以归属于某个窗口组.

可以使用DBMS_SCHEDULER.CREATE_WINDOW来创建一个窗口.

例如我创建了一个名为mytest_windows_1的窗口,采用DAILY_PURGE_SCHEDULE的调度方式,资源计划限制方案为 SYSTEM_PLAN,持续时间为4小时.

  DBMS_SCHEDULER.CREATE_WINDOW(
   window_name=>'mytest_windows_1',
   resource_plan=>'SYSTEM_PLAN',
   schedule_name=>'SYS.DAILY_PURGE_SCHEDULE',
   duration=>numtodsinterval(240, 'minute'),
   window_priority=>'LOW',
  comments=>'');
  END;
/

窗口组(window_group):

一个/几个窗口的集合.10g默认的自动采集统计信息的调度就是一个窗口组的形式,譬如,设置两个窗口,窗口一指定任务周日-----周五,晚上12点执行,而窗口二设定周六凌晨3点执行,这两个窗口组成了一个窗口组,形成了这个job的执行调度策略.

可以使用DBMS_SCHEDULER.CREATE_WINDOW_GROUP来创建一个窗口组.

  DBMS_SCHEDULER.CREATE_WINDOW_GROUP(
   group_name=>'mytest_window_group',
   window_list=>'MYTEST_WINDOWS_1,WEEKEND_WINDOW');
  END;
/

关于调度时间的问题我们搞清楚了,现在我们看一下调度的内容问题!

SQL> select JOB_NAME,PROGRAM_NAME from DBA_SCHEDULER_JOBS;
 
JOB_NAME                PROGRAM_NAME
----------------------- --------------------------------------
AUTO_SPACE_ADVISOR_JOB AUTO_SPACE_ADVISOR_PROG
GATHER_STATS_JOB        GATHER_STATS_PROG
FGR$AUTOPURGE_JOB
PURGE_LOG               PURGE_LOG_PROG
RLM$SCHDNEGACTION
RLM$EVTCLEANUP
 

已选择6行。
我们还研究GATHER_STATS_JOB这个作业,这个作业做什么?是一个程序,叫做GATHER_STATS_PROG,GATHER_STATS_PROG内容是什么呢?

where PROGRAM_NAME='GATHER_STATS_PROG';
 
PROGRAM_ACTION
---------------------------------------------------------------------
dbms_stats.gather_database_stats_job_proc

啊,原来就是一个存储过程。我们一步步的把调度的神秘面纱剥掉了!
现在我总结一下:有个程序GATHER_STATS_PROG,该程序调用了一个存储过程。
有个窗口组MAINTENANCE_WINDOW_GROUP,其内含有平时和周末两个策略。
我们的作业GATHER_STATS_JOB就是在MAINTENANCE_WINDOW_GROUP窗口组的时间内运行程序GATHER_STATS_PROG。搞的挺复杂,其实不难!
调度中还有两个概念我们没有讲到。一个为链(chain),一个为作业类(job_class)。
链(chain):
  链可以看作是一个/几个program/event scheduler的集合,为了维护需要,我们可能需要将很多不同的program放到一起依次执行,按照以前的模式,要么将这几个program能整合成一个大的整体,要么分开几个job来单独执行,这无疑加重了维护负担,而chain的出现,可以优化这个问题,我们将实现定义好的program集合到一起,然后统一制定一个job来执行,可以使用dbms_scheduler.create_chain来创建一个chain.

比如,在我的系统中,我分别创建了一个EXECUTABLE类型的和一个STORED PROCEDURE类型的program,我需要他们顺次执行,于是我可以这么做:

  dbms_scheduler.create_chain( chain_name =>'MYTEST_CHAIN');
  dbms_scheduler.define_chain_step(chain_name =>'MYTEST_CHAIN', step_name =>'mytest_chain_1',program_name =>'P_1');
   dbms_scheduler.alter_chain(chain_name =>'MYTEST_CHAIN', step_name =>'mytest_chain_1',attribute=>'skip',value=>FALSE);
   dbms_scheduler.define_chain_step(chain_name =>'MYTEST_CHAIN',step_name =>'mytest_chain_2',program_name =>'P_2');
   dbms_scheduler.alter_chain(chain_name =>'MYTEST_CHAIN',step_name =>'mytest_chain_2',attribute=>'skip', value=>FALSE);
  dbms_scheduler.enable('MYTEST_CHAIN');
   END;
/
 

作业类(job_class):

定义了运行作业的资源使用者组.通过使用窗口中的资源计划,我们可以在不同资源组和不同作业类之间分配资源.可以使用 dbms_scheduler.create_job_class创建一个作业类.

  dbms_scheduler.create_job_class(
   logging_level => DBMS_SCHEDULER.LOGGING_RUNS,
   log_history => 100,
   resource_consumer_group => 'AUTO_TASK_CONSUMER_GROUP',
   job_class_name => 'MYTEST_JOB_CLASS');
  END;
/

调度的概念都讲解完了,我们总结一下:

  1. 作业(job),2.调度(scheduler),3.程序(program),4.链(chain),4.作业类(job_class),5.窗口(window),6.窗口组(window_group)
    

这些不是必须的。我们可以直接留作业,和以前dbms_job一样,而且可以运行操作系统的脚本。

  dbms_scheduler.create_job
  (
  job_name => 'ARC_MOVE',
 repeat_interval => 'FREQ=MINUTELY; INTERVAL=30',
  job_type => 'EXECUTABLE',
  job_action => '/home/dbtools/move_arcs.sh',
  enabled => true,
  comments => 'Move Archived Logs to a Different Directory'
  );
  end;
/

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12798004/viewspace-1247636/,如需转载,请注明出处,否则将追究法律责任。

总结:

调度.png

拓展阅读

Oracle 定时执行计划任务

                          部分截取自互联网,如有侵权请与我联系。
                          wechat: 704012932
                          email:  pkweibu@163.com
                          CSDN:   https://blog.csdn.net/weixin_37423880
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DBMS_SCHEDULER.CREATE_JOB过程是用于创建作业的一个子程序。它可以创建多种类型的作业,如单次作业、循环作业、链式作业等。下面是DBMS_SCHEDULER.CREATE_JOB的详细用法: 语法: ``` DBMS_SCHEDULER.CREATE_JOB ( job_name IN VARCHAR2, job_type IN VARCHAR2, job_action IN VARCHAR2, number_of_arguments IN PLS_INTEGER DEFAULT 0, start_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL, repeat_interval IN VARCHAR2 DEFAULT NULL, end_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL, job_class IN VARCHAR2 DEFAULT 'DEFAULT_JOB_CLASS', enabled IN BOOLEAN DEFAULT TRUE, auto_drop IN BOOLEAN DEFAULT FALSE, comments IN VARCHAR2 DEFAULT NULL, credential_name IN VARCHAR2 DEFAULT NULL, destination_name IN VARCHAR2 DEFAULT NULL, job_style IN VARCHAR2 DEFAULT 'REGULAR', restartable IN BOOLEAN DEFAULT FALSE); ``` 参数说明: - job_name:作业名称,必填项。 - job_type:作业类型,可选值为'PLSQL_BLOCK'、'STORED_PROCEDURE'、'EXECUTABLE'、'CHAIN'、'SQL_SCRIPT'、'BACKUP_SCRIPT'、'COPY_SCRIPT'、'DELETE_FILES'、'EXTERNAL_SCRIPT'、'IN_MEMORY_SCRIPT'、'MANAGE_FILES'、'MOVE_FILES'、'RESTORE_SCRIPT'、'UPDATE_INDEXES'、'UPDATE_STATISTICS',必填项。 - job_action:作业所执行的动作,必填项。根据不同的作业类型,job_action的值也有所不同。如对于PLSQL_BLOCK类型的作业,job_action可以是一个PL/SQL代码块;对于EXECUTABLE类型的作业,job_action可以是一个可执行文件的路径;对于CHAIN类型的作业,job_action可以是一个链名称等。 - number_of_arguments:作业所需的参数个数,默认为0。 - start_date:作业的开始时间,可以是一个时间戳或一个时间字符串,默认为NULL。 - repeat_interval:作业的重复间隔,可以是一个时间字符串或时间间隔表达式,默认为NULL。 - end_date:作业的结束时间,可以是一个时间戳或一个时间字符串,默认为NULL。 - job_class:作业所属的作业类别,必须是先前用DBMS_SCHEDULER.CREATE_JOB_CLASS创建的类别之一。默认为'DEFAULT_JOB_CLASS'。 - enabled:作业是否启用,可选值为TRUE或FALSE,默认为TRUE。 - auto_drop:作业是否自动删除,可选值为TRUE或FALSE,默认为FALSE。 - comments:作业的注释,可选。 - credential_name:作业所使用的凭证名称,可选。 - destination_name:作业所使用的目标名称,可选。 - job_style:作业类型,可选值为'REGULAR'或'LIGHTWEIGHT',默认为'REGULAR'。 - restartable:作业是否可重启,可选值为TRUE或FALSE,默认为FALSE。 示例: 下面是一个使用DBMS_SCHEDULER.CREATE_JOB创建PL/SQL_BLOCK类型作业的示例: ``` DECLARE job_name VARCHAR2(30) := 'MY_JOB'; job_type VARCHAR2(30) := 'PLSQL_BLOCK'; job_action VARCHAR2(4000) := 'BEGIN DBMS_OUTPUT.PUT_LINE(''Hello World!''); END;'; BEGIN DBMS_SCHEDULER.CREATE_JOB( job_name => job_name, job_type => job_type, job_action => job_action, enabled => TRUE, auto_drop => FALSE, comments => 'This is my first job' ); END; ``` 在上面的示例中,我们创建了一个名为'MY_JOB'的作业,作业类型为'PLSQL_BLOCK',作业动作为一个简单的PL/SQL代码块,输出一个'Hello World!'的字符串。作业启用并且不会自动删除,同时添加了一条注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值