【转】调度作业(Oracle Scheduler)
Oracle Scheduler可以帮助DBA或者数据库用户自动调度和运行各种类型的作业,比如数据库备份、收集优化器统计信息、生成各种报表或者执行业务流程等等,也可以把Schedule和Resource Manager结合起来通过时间窗口激活指定的Resource Plan,完成企业在资源管理和作业调度上的各种复杂需求,在10g之前可以通过DBMS_JOB工具来实现类似的功能,但毫无疑问,DBMS_SCHEDULER的灵活性和多样性比起老版本工具都有了极大的提升。
一. 功能概述
Oracle Scheduler到底可以实现那些具体功能呢?来看一下官方文档给出的解释:
Run database program units
可以在本地或者远程数据库执行的数据库程序包括:PL/SQL 匿名块、PL/SQL 存储过程、JAVA 存储过程以及链
Run external executables, (executables that are external to the database)
执行外部的可执行文件,包括应用程序、Shell脚本、Windows批处理文件,如果要在远程主机执行外部作业,远程主机只需要安装Agent而不需要Database
Schedule job execution using the following methods:
Time-based scheduling
You can schedule a job to run at a particular date and time, either once or on a repeating basis.
Event-based scheduling
You can start
jobs in response to system or business events. Your applications can
detect events and then signal the Scheduler. Depending on the type of signal sent, the Scheduler starts a specific job.
Dependency scheduling
You can set
the Scheduler to run tasks based on the outcome of one or more previous
tasks. You can define complex dependency chains that include branching and nested chains.
Prioritize jobs based on business requirements.
Controlling Resources by Job Class
把有相同特性的Job指定到一个Job Class,再把Job Class映射到Resource Consumer Group,实现对调度作业的资源分配控制
Controlling Job Prioritization based on Schedules
通过时间窗口改变作业的优先等级,创建Window在一个时间范围激活相应的 Resource Plan 来控制不同作业在不同时段的优先等级
Manage and monitor jobs
Execute and manage jobs in a clustered environment
二. 基本概念
Oracle Scheduler包含的主要对象包括:Schedule,Program,Job,Job Class,Chain,Window,Database Destination,File Watcher,Credential ...具体介绍如下:
Schedule (时间表)
通过 DBMS_SCHEDULER 包中的过程 CREATE_SCHEDULE 定义调度的开始时间,结束时间以及重复间隔
CREATE_EVENT_SCHEDULE 过程用来创建由事件触发的时间表,由一个特定时间段内的一个事件调起一项任务
Program (程序)
定义了作业的形式及内容,作业形式可以是PL/SQL 匿名块,也可以是存储过程或者外部可执行文件,执行的存储过程带有输入参数时必须以匿名块运行
Job (作业)
通过CREATE_JOB创建一个作业,这个存储过程使用了重载,所以输入参数的选择可以非常灵活,既可以独立设置作业的时间、内容、Job Class,也可以引用已经存在的Schedule 和 Program 来简化作业的创建
Job Class (作业类)
说白了就是一系列的作业通过链来建立起一套依赖关系,大概的思路是这样的:先使 CREATE_CHAIN 创建一个链,再通过 DEFINE_CHAIN_STEP 和 DEFINE_CHAIN_EVENT_STEP 给要链接的 Program、Sub Chain、Event Condition、Event Schedule 分别定义一个别名(step_name),然后拿 DEFINE_CHAIN_RULE 定义这些 Step 的依赖规则,一通判断、分支、嵌套之后,链就算创建完成了,在 CREATE_JOB 时 (job_type => 'CHAIN',job_action => 'chain_name') 就可以了,做人得讲究,这个必须上图:
![](http://blog.chinaunix.net/attachment/201304/16/26190993_13660472979ASa.bmp)
Window (窗口)
窗口指的是一个介于开始时间和结束时间之间的时间段,(为什么这么简单的一个概念被我说的如此绕口,我的小学语文老师呢?您有话要说吗。。),通常用来调 起作业,或者在不同的时间段激活不同的 Resource Plan 以调整作业之间的资源分配,文档中还提到了 Overlapping Windows ,暂不研究了,来吧,有图有真相:
![](http://blog.chinaunix.net/attachment/201304/16/26190993_1366045369baza.bmp)
Database Destination (数据库路径)
通过 CREATE_DATABASE_DESTINATION 创建,在 CREATE_JOB 中作为一个输入参数,用来执行远程调度
Credential (证书)
证书用来保存OS或者数据库的用户密码,在执行External Job 或者远程数据库作业时使用
File Watcher (文件监视器)
这个好玩。。可以用来检测一个OS文件是否存在,根据文件大小判断传输是否完成,继而触发一个 Event Schedule
Lightweight Job (轻量级作业)
11gR1之前不被支持,通过 job_style 指定,轻量级作业并不是一个调度器对象,它适用于多个频繁执行的小作业,看看官方文档的介绍:
-
Unlike regular jobs, they are not schema objects.
-
They have significantly better create and drop times over regular jobs because they do not have the overhead of creating a schema object.
-
They have lower average session create time than regular jobs.
-
They have a small footprint on disk for job metadata and run-time data.
1. 创建调度作业执行一个 Shell 脚本
1 [oracle@ASM ~]$ cat /tmp/job.sh 2 #!/bin/bash 3 /bin/touch /tmp/abc.txt
1 SQL> exec dbms_scheduler.create_credential('CRE1','user1','abcd1234') 2 PL/SQL procedure successfully completed. 3 SQL> exec dbms_scheduler.create_job(dbms_scheduler.generate_job_name,'EXECUTABLE','/tmp/job.sh',0,'','','','DEFAULT_JOB_CLASS',TRUE,FALSE,'Test.','CRE1') 4 PL/SQL procedure successfully completed. 5 SQL> select job_name,state,run_count,failure_count,raise_events from dba_scheduler_jobs where comments='Test.'; 6 JOB_NAME STATE RUN_COUNT FAILURE_COUNT RAISE_EVENTS 7 ---------- --------------- ---------- ------------- -------------------- 8 JOB$_127 SUCCEEDED 1 0 9 SQL> select JOB_NAME,STATUS,CREDENTIAL_NAME,ADDITIONAL_INFO from dba_scheduler_job_run_details where job_name='JOB$_127'; 10 JOB_NAME STATUS CREDENTIAL ADDITIONAL_INFO 11 ---------- ---------- ---------- -------------------------------------------------------------------------------- 12 JOB$_127 SUCCEEDED CRE1 EXTERNAL_LOG_ID="job_74659_457", USERNAME="user1"
1 [oracle@ASM ~]$ ls /tmp/abc.txt 2 /tmp/abc.txt
2. 分别执行SQL语句、匿名块、PL/SQL 存储过程
1 SQL> exec dbms_scheduler.create_job(dbms_scheduler.generate_job_name,'PLSQL_BLOCK','insert into scott.t1(dname) values(''BLOCK'');',0,'','','','DEFAULT_JOB_CLASS',TRUE,FALSE,'Test_1') 2 PL/SQL procedure successfully completed. 3 SQL> exec dbms_scheduler.create_job(dbms_scheduler.generate_job_name,'PLSQL_BLOCK','BEGIN p2(''50'',''t'',''t''); END;',0,'','','','DEFAULT_JOB_CLASS',TRUE,FALSE,'Test_3') 4 PL/SQL procedure successfully completed. 5 SQL> exec dbms_scheduler.create_job(dbms_scheduler.generate_job_name,'STORED_PROCEDURE','p1',0,'','','','DEFAULT_JOB_CLASS',TRUE,FALSE,'Test_2') 6 PL/SQL procedure successfully completed.
3. 创建 Program 并在 Job 中引用
1 SQL> exec dbms_scheduler.create_program('TEST1','PLSQL_BLOCK','BEGIN p2(''50'',''t'',''t''); END;',0,TRUE,'Pro_1') 2 PL/SQL procedure successfully completed. 3 SQL> exec dbms_scheduler.create_job(dbms_scheduler.generate_job_name,program_name => 'TEST1',repeat_interval => '',end_date => '',enabled => TRUE ,auto_drop => FALSE,comments => 'Test_9') 4 PL/SQL procedure successfully completed.
4. 创建 Job 时分别引用 Program 和 Schedule
1 SQL> BEGIN 2 DBMS_SCHEDULER.CREATE_SCHEDULE( 3 SCHEDULE_NAME => 'sch1', 4 START_DATE => sysdate, 5 END_DATE => sysdate+3650, 6 REPEAT_INTERVAL => 'freq=yearly; bymonth=jan,apr,jul,oct; bymonthday=2', --10年时间里每年每个季度的第一个月的第二天执行作业 7 COMMENTS => 'Quarterly Report.' 8 ); 9 END; 10 / 11 PL/SQL procedure successfully completed. 12 13 SQL> BEGIN 14 DBMS_SCHEDULER.CREATE_JOB( 15 dbms_scheduler.generate_job_name, 16 PROGRAM_NAME=>'TEST1', 17 SCHEDULE_NAME=>'sch1', 18 ENABLED=>TRUE, 19 AUTO_DROP=>FALSE, 20 COMMENTS=>'Test_99' 21 ); 22 END; 23 / 24 PL/SQL procedure successfully completed.