使用调度程序来简化管理任务
• 创建作业、程序和调度
• 监视作业执行
• 使用基于时间或基于事件的调度来执行调度程序作业
• 描述窗口、窗口组、作业类和使用者组的用途
• 使用电子邮件通知
• 使用作业链来执行一系列相关任务
• 描述远程系统上的调度程序作业
• 使用高级调度程序概念来区分作业的优先级
简化管理任务

Oracle 环境中的许多任务都需要作业调度功能。例行的数据库维护和应用程序逻辑要求定期调度并运行作业。企业到企业(B2B) 应用程序要求对其业务事件进行调度。DBA 需要在指定时间窗口中调度定期维护作业。
Oracle DB 通过数据库调度程序提供高级调度功能,此调度程序是DBMS_SCHEDULER程序包中函数和过程的集合。可以在任何SQL 环境中,或者通过Oracle EnterpriseManager (EM) 来调用此调度程序。
使用此调度程序,数据库管理员和应用程序开发者可以控制在数据库环境中执行各种任务的时间和位置。这些任务可能既耗时又复杂;可以使用调度程序来管理和计划这些任务。可以根据时间或者在发生指定事件时启动调度程序作业,而且调度程序还可以在作业状态更改时(例如,从RUNNING变为COMPLETE)引发事件。还可以使用为达到组合目标而链接在一起的一系列已命名的程序。
核心组件


核心组件和主要步骤
一个作业包含两个必需组件:需要执行的操作,操作的发生时间或调度。“操作”是由命令区域和作业属性中的job_type和job_action参数表示的。“时间”是在调度中表示的,调度可以基于时间或事件,或者从属于其它作业的结果。
调度程序使用以下基本组件:
• “作业”指定要执行的操作。它可以是PL/SQL 过程、纯二进制可执行文件、Java 应用程序或Shell 脚本。可以将程序(内容)和调度(时间)指定为作业定义的一部分,
也可以改用现有的程序或调度。可以使用作业的参数来定制其运行时行为。
• “调度”指定作业的执行时间和次数。调度可以基于时间或事件。可以为作业定义调度,方法是使用一系列日期、一个事件,或两者相结合,以及表示重复间隔的附加说
明。可以单独存储作业的调度,然后对多个作业使用同一个调度。
• “程序”是有关特定可执行文件、脚本或过程的元数据集合。自动作业将执行某个任务。使用程序,无需修改作业本身即可修改作业任务或者“内容”。可以定义程序的参数,使用户可以修改任务的运行时行为。
基本工作流
使用调度程序来简化管理任务:
1. 创建程序(启用或禁用)-可选
– 在多个作业中重用此操作
– 在无需重新创建PL/SQL 块的情况下更改作业的调度
2. 创建并使用调度
3. 创建并提交作业
可以在Oracle EnterpriseManager 的图形环境中执行所有步骤,或者通过命令行使用DBMS_SCHEDULERPL/SQL 程序包执行所有步骤。
1. 创建程序
使用CREATE_PROGRAM过程来创建程序。使用调度程序时,创建程序是一个可选部分。还可以对操作进行编码,使其在CREATE_JOB过程的匿名PL/SQL 块中执行。通过单独创建程序,可以定义一次操作,然后在多个作业中重用此操作。使用这种方法,无须重新创建PL/SQL 块即可更改作业的调度。
默认情况下,程序是以禁用状态创建的(除非enabled参数设为TRUE)。在将禁用的程序启用之前,作业无法执行此程序。可以通过将enabled的值指定为TRUE来指定应以启用状态创建程序。
2. 创建并使用调度
作业的调度可以是预定义的调度(用CREATE_SCHEDULE过程创建的),也可以是在创建作业时定义的。
调度指定有关作业运行时间的属性,例如:
• 起始时间,定义作业从哪一时间开始执行;结束时间,指定作业在哪一时间之后失效且不再进行调度
• 指定作业重复间隔的表达式
• 通过组合现有调度创建的复杂调度
• 启动作业之前必须满足的条件或状态变化(称为事件)
通过使用调度(而不是在作业定义中指定作业的执行次数),可以管理多个作业的预定执行,而无须更新多个作业定义。如果修改了某个调度,则使用该调度的每个作业都将自动使用新调度。
3. 创建并运行作业
作业是一个组合,其中包括调度、要执行的操作的说明以及作业需要的所有附加参数。可以为作业设置许多属性。属性将控制作业的执行方式。
作业操作在程序中(而不是直接在作业中)时,无需重新创建PL/SQL 块即可更改作业调度。
每个作业必须有一个调度。调度可以是预定义的,也可以在创建作业的过程中定义。
持久轻量作业
持久轻量作业:
• 减少启动作业所需的开销和时间
• 作业元数据和运行时数据在磁盘上占用很小的空间
• 是使用作业模板(在命令行中)创建的
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'my_lightweight_job2',
program_name => 'MY_PROG',
schedule_name => 'MY_SCHED',
job_style => 'LIGHTWEIGHT');
END;
/
选择合适的作业类型:
–使用常规作业可提供最大灵活性。
–需要在很短的时间内创建大量作业时,请使用持久轻量作业。
轻量作业:
• 适合需要在一秒内创建数百个作业的客户。对于常规作业,每个作业都要创建一个数据库对象,用于描述作业、修改多个表以及在进程中创建重做。此种类型作业需求的相关开销是很大的。在Oracle DB 调度程序中,有一种“持久轻量作业”。轻量作业的目的是减少启动作业所需的开销和时间。将为作业创建极少的元数据。这可以减少启动作业时所需的时间和创建的重做。
• 作业元数据和运行时数据在磁盘上占用很小的空间。在磁盘上占用的空间小还可实现在RAC 环境中进行负载平衡。
• 始终是使用作业模板创建的。作业模板必须是一个存储过程或一个程序。存储过程可以保存作业所需的所有信息,包括权限。只可以指定少量作业属性:作业参数和调度。
• 必须在命令行中创建。JOB_STYLE参数在EM 中不可用。
在示例中,MY_PROG是作业模板,调度是通过已命名的调度应用的。
使用基于时间的或基于事件的调度
要为作业指定基于时间的调度,可以指定日历表达式或日期时间表达式。使用日历表达式时,将使用作业的重复间隔和起始日期来计算作业的下一启动时间。使用日期时间表达式时,指定的表达式确定作业下次应运行的时间。如果没有指定重复间隔,作业将只在指定的起始日期运行一次。
如果作业使用基于事件的调度,作业将在事件发生时运行。在较高层次上,可以将事件视为状态的更改。布尔条件的状态从FALSE更改为TRUE,或者从TRUE更改为FALSE时,将发生事件。
调度程序使用Oracle StreamsAdvanced Queuing (AQ) 来引发和使用事件。
注:调度程序不保证作业恰好在计划的时间执行,因为可能会由于系统过载而造成资源不可用。
创建基于时间的作业
示例:创建一个作业,从今晚起在每晚11:00 调用备份脚本。
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name=>'HR.DO_BACKUP',
job_type=> 'EXECUTABLE',
job_action=>
'/home/usr/dba/rman/nightly_incr.sh',
start_date=> SYSDATE,
repeat_interval=>'FREQ=DAILY;BYHOUR=23',
/* next night at 11:00 PM */
comments => 'Nightly incrementalbackups');
END;
/
创建基于时间的作业
可以使用DBMS_SCHEDULER程序包的CREATE_JOB过程来创建作业。默认情况下将以禁用状态创建作业,仅当显式启用时,这些作业才生效并可以调度。所有作业名称都采用以下形式:[schema.]name。
应该使用SYSTIMESTAMP并指定时区,这样当时间因夏时制更改时,作业能够自动调整其执行时间。
默认情况下,将在当前方案中创建作业。可以通过指定方案的名称在另一个方案中创建作业,如示例所示。作业所有者是在其方案中创建作业的用户,而作业创建者是创建作业的用户。作业将按作业所有者的权限来执行。作业运行时的国家语言支持(NLS) 环境与创建作业时的环境相同。job_type参数指示作业将要执行的任务的类型。可能的值包括:
• PLSQL_BLOCK:匿名PL/SQL 块
• STORED_PROCEDURE:命名的PL/SQL、Java 或外部过程
• EXECUTABLE:可以从操作系统(OS) 命令行执行的命令
job_action参数可以是要运行的过程的名称、脚本的名称或操作系统命令的名称,也可以是匿名的PL/SQL 代码块,具体取决于job_type参数的值。
在示例中,job_type被指定为EXECUTABLE,job_action是所需的外部可执行文件加上任何命令行参数(可选)的操作系统相关完整路径。
外部作业是指在数据库外部运行的作业。所有外部作业均作为低权限的来宾用户运行,这一点已在数据库管理员配置外部作业支持时确定。因为可执行文件作为低权限的来宾帐户运行,所以应确保其有权访问必要的文件和资源。大多数(但不是所有)平台都支持外部作业。对于不支持外部作业的平台,如果将作业或程序的属性创建或设置为EXECUTABLE类型,将返回错误。
创建基于事件的调度
要创建基于事件的作业,必须设置:
• 队列说明(应用程序将消息入队以启动作业)
• 一个事件条件(与Oracle Streams AQ 规则条件的语法相同),如果为TRUE则启动作业

可以基于事件触发作业。应用程序可以通知调度程序启动作业,方法是将消息入队到Oracle Streams 队列中。以这种方法启动的作业称为基于事件的作业。要创建基于事件的作业,必须用CREATE_JOB过程设置以下两个附加属性:
• queue_spec:对队列的指定,包括应用程序将消息放入其中以引发作业启动事件的队列的名称;对于安全队列,则为<queue_name>、<agent_name> 对。
• event_condition:基于消息属性的条件表达式,此表达式的求值结果必须为TRUE,消息才能启动作业。只要消息有效负载是用户定义的对象类型,并且将表达式中的对象属性加了tab.user_data前缀,就可以在表达式中包含用户数据属性。
可以将queue_spec和event_condition指定为内嵌作业属性,或者用这两个属性创建基于事件的调度,然后创建一个引用此调度的作业。
使用Oracle Enterprise Manager 创建基于事件的调度

使用Oracle EnterpriseManager 创建基于事件的调度
使用“Create Schedule(创建调度)”页,可以从标准的、基于时间的调度和基于事件的调度之中选择一种来创建。如果选择基于事件的调度,则界面将更改,然后可以指定队列名、代理名和事件条件以及其它调度属性。
注:对于与event_condition匹配的事件的每个实例,调度程序都会运行基于事件的作业。但是,将忽略作业已经运行后发生的事件;事件将被使用,但不会触发作业再次运行。
创建基于事件的作业
示例:创建一个作业,如果成批装入的数据文件在上午9:00 前到达文件系统,则运行此作业。
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name=>'ADMIN.PERFORM_DATA_LOAD',
job_type => 'EXECUTABLE',
job_action =>'/loaddir/start_my_load.sh',
start_date => SYSTIMESTAMP,
event_condition => 'tab.user_data.object_owner =
''HR'' and tab.user_data.object_name = ''DATA.TXT''
and tab.user_data.event_type = ''FILE_ARRIVAL''
and tab.user_data.event_timestamp < 9 ',
queue_spec => 'HR.LOAD_JOB_EVENT_Q');
END;
创建基于事件的作业
要将事件信息指定为作业属性,请使用CREATE_JOB的替代语法,其中包括queue_spec和event_condition属性。作业可以包含作为作业属性的内嵌事件信息,或可以通过指向事件调度来指定事件信息。显示的示例使用了内嵌的基于事件的调度。
示例显示了一个作业,只要有文件在上午9:00 前到达操作系统,就会启动此作业。假定消息有效负载是一个对象,该对象包括四个名称分别为object_owner、object_name、event_type和event_timestamp的属性。
本例使用的是用户定义的事件。因此,文件在到达了文件系统后,必须有一个程序或过程将包含正确信息的事件对象类型入队到指定的事件队列中,才能启动此作业。
HR.LOAD_JOB_EVENT_Q队列必须与用于将事件的发生通知调度程序的事件对象类型相同。即,HR.LOAD_JOB_EVENT_Q队列必须是类型化队列,其中的类型包括四个名称为object_owner、object_name、event_type和event_timestamp的属性。
基于事件的调度
事件类型:
• 用户或应用程序生成的事件
• 调度程序生成的事件
由调度程序作业引发的事件:
• JOB_STARTED
• JOB_SUCCEEDED
• JOB_FAILED
• JOB_BROKEN
• JOB_COMPLETED
• JOB_STOPPED
• JOB_SCH_LIM_REACHED
• JOB_DISABLED
• JOB_CHAIN_STALLED
• JOB_ALL_EVENTS
• JOB_RUN_COMPLETED
• JOB_OVER_MAX_DUR
引发事件的示例:
DBMS_SCHEDULER.SET_ATTRIBUTE('hr.do_backup',
'raise_events',DBMS_SCHEDULER.JOB_FAILED);
基于事件的调度
你可以创建一个作业,但不向作业分配调度,而是通过直接引用事件来启动作业。有两种类型的事件:
• 用户或应用程序生成的事件:应用程序可以引发由调度程序使用的事件。调度程序通过启动作业来回应事件。此类事件的示例:正在运行的作业完成;文件到达文件系统;数据库内的帐户被锁定;以及库存到达下限阈值。
• 调度程序生成的事件:调度程序可以引发事件来指示在调度程序自身内发生的状态更改。例如,在作业启动时、作业完成时、作业超出其分配的运行时间时等条件下,调度程序均可以引发事件。事件的使用者是一个应用程序,该应用程序将执行某个操作以便对事件做出响应。
你可以对作业进行配置,使调度程序在作业的状态更改时引发事件。可以通过设置raise_events作业属性来完成此操作。默认情况下,在变更作业的raise_events属性之前,作业不会引发任何状态更改事件。要变更此属性,必须先使用CREATE_JOB过程创建作业,然后使用SET_ATTRIBUTE过程修改此属性的默认值。本例显示hr.do_backup作业已变更,使得该作业在失败时引发事件。为作业启用作业状态更改事件后,调度程序将引发这些事件,方法是将消息入队到默认的事件队列SYS.SCHEDULER$_EVENT_QUEUE中。
默认的调度程序事件队列是一个安全队列。可能需要配置队列,才能允许特定用户在此队列上执行操作,具体取决于应用程序。
默认的调度程序事件队列主要用于调度程序生成的事件。Oracle 建议你不要将此队列用于用户应用程序或用户定义的事件。

创建复杂调度

创建复杂调度
调度是数据库中的对象。创建调度时,将自动保存这些调度。可以使用调度的组合来创建更复杂的调度。通过组合调度,可以向日历表达式中添加特定日期,或者从日历表达式中排除特定日期。
定义调度的重复间隔时可以使用下列选项:
• INCLUDE:向日历表达式结果中添加日期列表
• EXCLUDE:从日历表达式结果中删除日期列表
• INTERSECT:只使用两个或多个调度共有的日期
创建要组合使用的调度时,可以对日期列表进行编码,方法是包含形式为[YYYY]MMDD的硬编码日期,或者包含用CREATE_SCHEDULE过程创建的已命名调度。例如,可以对调度的重复间隔使用下列值来指定日期列表:
0115,0315,0325,0615,quarter_end_dates,1215
此字符串表示日期1 月15 日、3 月15 日、3 月25 日、6 月15 日、12 月15 日以及QUARTER_END_DATES调度所指定的日期列表。
如果未在调度中指定硬编码日期的可选年份,则包括每一年的这些日期。
持久轻量作业的作业元数据和运行时数据在磁盘上占用很小的空间。持久轻量作业是使用作业模板创建的。

扫描二维码关注我的微学堂
搜索刘老师微信号:Rman-2014,备注“Oracle学习与咨询”,即可添加好友;或者扫描下面二维码,关注我的“微学堂”公众号,了解最新OCP认证动态、题库及答案解析、培训机构及讲师介绍、课堂授课内容等。每天还有一篇技术文章发布哦!





