OCA/OCP Oracle 数据库12c考试指南读书笔记:第21章: The Scheduler

Scheduler可自动运行任务,这些任务可以是数据库中的过程,或操作系统中的命令和脚本。可以运行在本地或远程的数据库或服务器。运行可基于日程,或基于上一个任务的结果,或响应时间。Scheduler集成在资源管理中。
老的方法是使用DBMS_JOB,Enterprise Manager和操作系统也有任务调度,不过Scheduler更复杂也能力更强。

使用Oracle Scheduler简化管理任务

Scheduler包括很多对象,最基本的是job,job等级,还有程序,日程,时间窗等。

Scheduler 架构

所有Scheduler Job存于数据字典中的DBA_SCHEDULER_JOBS视图。由后台进程CJQ0调度,由Jnnn运行任务队列。最大任务队列数由JOB_QUEUE_PROCESSES决定,最大为1000,如果是0,则禁用任务调度。

SQL> show parameter JOB_QUEUE_PROCESSES

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
job_queue_processes                  integer     40

查看运行中的进程,以下显示只有任务调度器,而没有任务队列:

SQL> select program from v$process where program like '%J%';

PROGRAM
------------------------------------------------
oracle@oracle-19c-vagrant (CJQ0)

Job就是数据库中的过程或操作系统命令和脚本。Job的运行可基于时间(单次或重复)或事件(当满足某条件时)。Job也可以连接以形成工作流。
Scheduler可以与资源管理配合,例如使用Scheduler 激活资源管理计划(RESOURCE_MANAGER_PLAN参数或DBMS_RESOURCE_MANAGER.SWITCH_PLAN过程),例如让Job以某一优先级运行。
DBMS_SCHEDULER是管理Scheduler的API,Enterprise Manager提供图形界面。

Scheduler 对象

最基本的对象是Job。

Job

Job定义了做什么和何时做。做什么可以是存储过程,操作系统脚本,或远程的Job。何时做可以是指定时间,周期运行或基于事件。
使用DBMS_SCHEDULER.CREATE_JOB创建任务。
任务必需包括唯一的任务名,JOB_NAME。
任务类型包括:

  • PLSQL_BLOCK
  • STORED_PROCEDURE
  • EXECUTABLE 操作系统命令
  • CHAIN Job链
  • EXTERNAL_SCRIPT 操作系统脚本
  • SQL_SCRIPT SQL*Plus脚本
  • BACKUP_SCRIPT RMAN脚本

JOB_ACTION和NUMBER_OF_ARGUMENTS定义执行的命令和参数个数。
START_DATE定义开始执行时间。
REPEAT_INTERVAL定义了重复执行周期,直到结束时间END_DATE。
JOB_CLASS定义任务优先级并与资源管理关联。
ENABLED定义任务是否可执行,默认为FALSE。
AUTO_DROP定义是否在END_DATE后删除任务定义。默认是定义后自动执行,执行后自动删除。

另一种形式的任务创建为基于事件,需指定EVENT_CONDITION参数。

Program

Program通过DBMS_SCHEDULER.CREATE_PROGRAM创建,在Job和执行的操作间建立抽象。因此可以复用。Program默认为未启用。

Schedules

通过DBMS_SCHEDULER.CREATE_SCHEDULE创建,定义何时,何周期运行任务。
开始时间默认为当前时间,结束时间默认为永远。
REPEAT_INTERVAL定义周期,包括3个元素,即频率(每秒到每年),间隔(默认为1),specifier(按秒,按年日,按月日,按周日等)。
例如:
repeat_interval=>'freq=hourly; interval=12'表示每12小时执行一次。
repeat_interval=>'freq=yearly; bymonth=jan,mar,may;bymonthday=2'表示每年的指定3个月的第二天运行。
repeat_interval=>'freq=weekly; interval=2; byday=mon; byhour=6;byminute=10'表示每两周的周一6点10分运行。

简单来说,freq可以理解为单位,interval可以翻译为‘每’或every。by…可认为是指定时间。

自包含Job

使用CREATE_JOB 创建。
示例:

-- 连接到数据库
sqlplus system@orclpdb1
-- 创建一个表存放时间并设置时间格式
create table times(c1 date);
alter session set nls_date_format='dd-mm-yy hh24:mi:ss';
-- 创建任务,每一分钟插入当前时间
execute dbms_scheduler.create_job( -
job_name=>'savedate', -
job_type=>'plsql_block', -
job_action=>'insert into times values(sysdate);',  -
start_date=>sysdate, -
repeat_interval=>'freq=minutely;interval=1',  -
enabled=>true, -
auto_drop=>false);

-- 查询任务运行情况
SQL> select job_name, enabled, to_char(next_run_date, 'dd-mm-yy hh24:mi:ss'), run_count from user_scheduler_jobs;
JOB_NAME   ENABL TO_CHAR(NEXT_RUN_  RUN_COUNT
---------- ----- ----------------- ----------
SAVEDATE   TRUE  17-11-19 10:58:48          3

-- 查询任务运行情况
JOB_NAME   ENABL TO_CHAR(NEXT_RUN_  RUN_COUNT
---------- ----- ----------------- ----------
SAVEDATE   TRUE  17-11-19 10:59:48          4

-- 查询时间表
SQL> select * from times;

C1
-----------------
17-11-19 10:55:48
17-11-19 10:56:48
17-11-19 10:57:48
17-11-19 10:58:48

-- 禁止任务
exec dbms_scheduler.disable('savedate');

-- 查询任务状态 (ENABLED=FALSE)
SQL> select job_name, enabled, to_char(next_run_date, 'dd-mm-yy hh24:mi:ss'), run_count from user_scheduler_jobs;

JOB_NAME   ENABL TO_CHAR(NEXT_RUN_  RUN_COUNT
---------- ----- ----------------- ----------
SAVEDATE   FALSE 17-11-19 11:01:48          6

-- 删除任务
exec dbms_scheduler.drop_job('savedate');

-- 查询任务状态,无结果

补充,执行任务的人就是Job的创建者,如果你想让用户hr执行任务,可以赋予其创建任务的权限,然后让hr创建任务,例如:

grant create job to hr;
connect hr;
execute dbms_scheduler.create_job ...

使用 JOB CHAINS 执行系列相关任务

Job Chain是一系列有依赖关系的程序,连接的逻辑基于执行成功或失败。
以下示例创建了一个Job Chain,如果step1执行成功则执行step2,如果失败则执行step3:

exec dbms_scheduler.create_chain(chain_name=>'mychain');
exec dbms_scheduler.define_chain_step(chain_name=>'mychain', step_name=>'step1', property_name=>'prg1');
exec dbms_scheduler.define_chain_step(chain_name=>'mychain', step_name=>'step2', property_name=>'prg2');
exec dbms_scheduler.define_chain_step(chain_name=>'mychain', step_name=>'step3', property_name=>'prg3');
exec dbms_scheduler.define_chain_rule(chain_name=>'mychain', rule_name=>'rule1', condition=>'step1 succeeded', action=>'start step2');
exec dbms_scheduler.define_chain_rule(chain_name=>'mychain', rule_name=>'rule2', condition=>'step1 failed', action=>'start step3');
exec dbms_scheduler.enable('mychain');

运行job chain需要创建job:

exec dbms_scheduler.create_job(job_name=>'run_mychain', -
job_type=>'chain', -
job_action=>'mychain', -
start_date=>next_day(last_day(sysdate)-7, 'tuesday'), -
repeat_interval=>'freq=monthly;interval=2', -
enabled=>true);

注意,condition=>'step1 succeeded', action=>'start step2'中的succeeded(或者可以是completed)和start都是关键字,step1step2与实际定义的chain step对应。

在远程系统使用Scheduler Job

可以创建远程任务,任务的定义在本地数据库,执行的脚本在远程数据库。远程主机必需安装Scheduler 代理,包含在Oracle客户端软件中,代理默认监听端口为1500.
代理和数据库之间使用HTTP协议。在创建任务时指定远端主机的网络名即可。

使用高级Scheduler特性控制Job优先级

相关组件为:

  • Job Class:Job可定义Class,Class又可与资源管理中的消费组关联。
  • 消费组:限制资源,如CPU等
  • 资源计划:定义如何分配资源,任意时刻只能有一个生效的资源计划
  • Window:时间窗内,任务可运行,或资源计划可生效
  • Window Group:时间窗的组合
    相同class的Job是平等的,但如果不同class的Job在同一Window内运行,资源管理会根据class对应的消费组分配资源。

使用Job Class

然后通过dbms_scheduler.set_attribute在创建Job时或后续指定。
优先级取值1-5,默认为3,高优先级的在队列中优先执行。
日志记录也与Job Class有关,可以为不记录,仅记录执行时间和状态,完整记录等。
查询任务执行简要日志:

SQL> select job_name, log_date, status from dba_scheduler_job_log;

JOB_NAME                       LOG_DATE                                 STATUS
------------------------------ ---------------------------------------- ----------------
ORA$AT_OS_OPT_SY_1             15-NOV-19 02.02.43.179531 PM +08:00      SUCCEEDED
ORA$AT_OS_OPT_SY_1             15-NOV-19 02.02.43.279176 PM +08:00
ORA$AT_OS_OPT_SY_1             15-NOV-19 02.02.43.280915 PM +08:00
ORA$AT_OS_OPT_SY_21            16-NOV-19 10.00.05.073467 PM +08:00
ORA$AT_OS_OPT_SY_21            16-NOV-19 10.00.05.089088 PM +08:00
...

详细日志可查询DBA_SCHEDULER_JOB_RUN_DETAILS
日志有系统任务PURGE_LOG自动清理。每日清理30天之前的日志,由日程DAILY_PURGE_SCHEDULE定义。

使用Windows

dbms_scheduler.create_window定义。
示例:

exec dbms_scheduler.create_window(-
window_name=>'daily_reporting_window', -
resource_plan=>'night_plan', -
schedule_name=>'weekday_nights', -
duration=>'0 04:00:00', -
window_priority=>'low', -
comments=>'for running regular reports');

在夜间激活资源计划night_plan,持续4小时。window_priority定义了窗口重叠时的行为。例如如果还有一个月度资源计划恰好也在夜间。当然,重叠应尽量避免。
示例:

-- SYSTEM登录系统
sqlplus system@orclpdb1
-- 查询当前window
SQL> select window_name, active from dba_scheduler_windows;

WINDOW_NAME          ACTIV
-------------------- -----
MONDAY_WINDOW        FALSE
TUESDAY_WINDOW       FALSE
WEDNESDAY_WINDOW     FALSE
THURSDAY_WINDOW      FALSE
FRIDAY_WINDOW        FALSE
SATURDAY_WINDOW      TRUE
SUNDAY_WINDOW        FALSE
WEEKNIGHT_WINDOW     FALSE
WEEKEND_WINDOW       FALSE

9 rows selected.
-- 查询当前生效的plan
SQL> select * from v$rsrc_plan;

在这里插入图片描述

-- 清除所有plan
SQL> alter system set resource_manager_plan='' scope=memory;
-- 查询plan,只剩下INTERNAL_PLAN

        ID NAME                             IS_TO CPU INS
---------- -------------------------------- ----- --- ---
PARALLEL_SERVERS_ACTIVE PARALLEL_SERVERS_TOTAL PARALLEL_EXECUTION_MANAGED
----------------------- ---------------------- --------------------------------
    CON_ID DIRECTIVE_TYPE                       SHARES UTILIZATION_LIMIT
---------- -------------------------------- ---------- -----------------
PARALLEL_SERVER_LIMIT MEMORY_MIN MEMORY_LIMIT PROFILE
--------------------- ---------- ------------ --------------------------------
     19630 INTERNAL_PLAN                    TRUE  ON  OFF
                      0                     16 FULL
         3 DEFAULT_DIRECTIVE                       200

-- 创建时间窗
execute dbms_scheduler.create_window(-
window_name=>'daytime', resource_plan=>'my_plan',-
start_date=>trunc(systimestamp) + 6/24, -
repeat_interval=>'freq=daily', -
duration=>'0 12:00:00', -
comments=>'daily at 6AM');

-- 手工开启时间窗
exec dbms_scheduler.open_window(window_name=>'daytime', duration=>'0 00:05:00', force=>true)

-- 确认
SQL> select window_name, active from dba_scheduler_windows where active='TRUE';

WINDOW_NAM ACTIV
---------- -----
DAYTIME    TRUE
SQL> select * from v$rsrc_plan;

        ID NAME                             IS_TO CPU INS
---------- -------------------------------- ----- --- ---
PARALLEL_SERVERS_ACTIVE PARALLEL_SERVERS_TOTAL PARALLEL_EXECUTION_MANAGED
----------------------- ---------------------- --------------------------------
    CON_ID DIRECTIVE_TYPE                       SHARES UTILIZATION_LIMIT
---------- -------------------------------- ---------- -----------------
PARALLEL_SERVER_LIMIT MEMORY_MIN MEMORY_LIMIT PROFILE
--------------------- ---------- ------------ --------------------------------
     73638 MY_PLAN                          TRUE  ON  OFF
                      0                     16 FULL
         3 DEFAULT_DIRECTIVE                       200

-- 5分钟后,再次查询,会发现窗口已关闭并恢复为默认窗口。plan也恢复为默认。

-- 清理
exec dbms_scheduler.drop_window('daytime');

参考

  1. https://oracle-base.com/articles/10g/scheduler-10g
  2. https://oracle-base.com/articles/10g/scheduler-enhancements-10gr2#job_chains
  3. https://www.dummies.com/programming/databases/how-to-create-a-scheduler-job-in-oracle-12c/
发布了342 篇原创文章 · 获赞 42 · 访问量 54万+

猜你喜欢

转载自blog.csdn.net/stevensxiao/article/details/103103379