Oracle定时任务-DBMS_SCHEDULER

转载 2013年12月02日 14:59:39
 

Oracle定时任务(1)-DBMS_SCHEDULER


Oracle 10g之前,可以使用dbms_job来管理定时任务。
10g之后,Oracle引入dbms_scheduler来替代先前的dbms_job,
在功能方面,它比dbms_job提供了更强大的功能和更灵活的机制/管理。

使用dbms_scheduler创建一个定时任务有两种形式
1)创建1个SCHEDULER来定义计划,1个PROGRAM来定义任务内容,
再创建1个JOB,为这个JOB指定上面的SCHEDULER和PROGRAM。
2)直接创建JOB,在参数里面直接指定计划和任务内容。

要执行DBMS_SCHEDULER需要有CREATE JOB权限。
如果要创建外部操作系统命令的job, 还必须有CREATE EXTERNAL JOB权限。
如果要对于某个对象进行操作,必须是它的owner,或者对它具有alter权限,或者有create any job权限。
如果要创建/操作job_class,还需要有MANAGE SCHEDULER权限。job_class都是创建在sys schema中的。

名称 类型 描述
CREATE_SCHEDULE 过程

 DBMS_SCHEDULER.CREATE_SCHEDULE (
   schedule_name          IN VARCHAR2,
   start_date             IN TIMESTAMP WITH TIMEZONE DEFAULT NULL,
   repeat_interval        IN VARCHAR2,
   end_date               IN TIMESTAMP WITH TIMEZONE DEFAULT NULL,
   comments               IN VARCHAR2 DEFAULT NULL);

CREATE_PROGRAM 过程 DBMS_SCHEDULER.CREATE_PROGRAM (
   program_name             IN VARCHAR2,
   program_type             IN VARCHAR2,
   program_action           IN VARCHAR2,
   number_of_arguments      IN PLS_INTEGER DEFAULT 0,
   enabled                  IN BOOLEAN DEFAULT FALSE,
   comments                 IN VARCHAR2 DEFAULT NULL);
CREATE_JOB 过程 通过事先创建的schedule object 和 program object来创建job:
(另外还有2个过程只指定shcedule和program中的1个)
DBMS_SCHEDULER.CREATE_JOB (
   job_name                IN VARCHAR2,
   program_name            IN VARCHAR2,
   schedule_name           IN VARCHAR2,
   job_class               IN VARCHAR2              DEFAULT 'DEFAULT_JOB_CLASS',
   enabled                 IN BOOLEAN               DEFAULT FALSE,
   auto_drop               IN BOOLEAN               DEFAULT TRUE,
   comments                IN VARCHAR2              DEFAULT NULL,
   job_style               IN VARCHAR2              DEFAULT 'REGULAR',
   credential_name         IN VARCHAR2              DEFAULT NULL,
   destination_name        IN VARCHAR2              DEFAULT NULL);

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 FALSE,
   auto_drop            IN BOOLEAN                  DEFAULT TRUE,
   comments             IN VARCHAR2                 DEFAULT NULL,
   credential_name      IN VARCHAR2                 DEFAULT NULL,
   destination_name     IN VARCHAR2                 DEFAULT NULL);
SET_JOB_ARGUMENT_VALUE 过程

DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
   job_name                IN VARCHAR2,
   argument_position       IN PLS_INTEGER,
   argument_value          IN VARCHAR2);

DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
   job_name                IN VARCHAR2,
   argument_name           IN VARCHAR2,
   argument_value          IN VARCHAR2);

ENABLE
DISABLE
过程

DBMS_SCHEDULER.ENABLE (
   name              IN VARCHAR2,
   commit_semantics  IN VARCHAR2 DEFAULT 'STOP_ON_FIRST_ERROR');

DBMS_SCHEDULER.DISABLE (
   name              IN VARCHAR2,
   force             IN BOOLEAN DEFAULT FALSE,
   commit_semantics  IN VARCHAR2 DEFAULT 'STOP_ON_FIRST_ERROR');

*name可以用逗号分隔来指定多个对象,commit_semantics用于这种情况:STOP_ON_FIRST_ERROR,TRANSACTIONAL,ABSORB_ERRORS
*force参数用于dependencies,如果TRUE,即使其他对象依赖于它,操作也能成功。
另外,如果job正在运行,当force为TRUE, job被置为diabled并且允许运行中的job结束;
当force为false,返回错误。

RUN_JOB
STOP_JOB
过程

DBMS_SCHEDULER.RUN_JOB (
   job_name                IN VARCHAR2,
   use_current_session     IN BOOLEAN DEFAULT TRUE);

*use_current_session如果为TRUE:
1) The job runs as the user who called RUN_JOB
2) You can test a job and see any possible errors on the command line.
3) run_count,last_start_date, ast_run_duration,failure_count are not updated.
4) RUN_JOB can be run in parallel with a regularly scheduled job run.
*use_current_session如果为FALSE:
1) The job runs as the user who is the job owner.
2) You need to check the job log to find error information.
3) run_count,last_start_date,last_run_duration,failure_count are updated.
4) RUN_JOB fails if a regularly scheduled job is running.

DBMS_SCHEDULER.STOP_JOB (
   job_name         IN VARCHAR2
   force            IN BOOLEAN DEFAULT FALSE
   commit_semantics IN VARCHAR2 DEFAULT 'STOP_ON_FIRST_ERROR');

*force如果为FALSE, oracle尝试gracefully停止job, 
使用中断机制(interrupt mechanism),将控制权交还给slave process, 
来更新job queue中的job状态。如果失败了,返回错误。
force如果为TRUE, oracle立即中止job slave process.
Oracle建议只有force=FALSE停止job失败的情况下才尝试force=true.
并且如果使用force选项,比如有MANAGE SCHEDULER权限。

DROP_JOB
DROP_PROGRAM
DROP_SCHEDULE
过程 DBMS_SCHEDULER.DROP_JOB (
   job_name                IN VARCHAR2,
   force                   IN BOOLEAN DEFAULT FALSE,
   defer                   IN BOOLEAN DEFAULT FALSE,
   commit_semantics        IN VARCHAR2 DEFAULT 'STOP_ON_FIRST_ERROR');

*如果force为TRUE,试图停止正在运行的job(调用STOP_JOB(force=>false)),之后再drop。
*如果defer为TRUE,等待正在运行的job结束再drop。
*同时指定force和defer为TRUE,返回错误。
*如果同时指定force和defer为FALSE,对于一个正在运行的job,调用失败。

DBMS_SCHEDULER.DROP_PROGRAM (
   program_name            IN VARCHAR2,
   force                   IN BOOLEAN DEFAULT FALSE);

DBMS_SCHEDULER.DROP_SCHEDULE (
   schedule_name    IN VARCHAR2,
   force            IN BOOLEAN DEFAULT FALSE);

*force如果为false,这个program/schedule必须不被任何job引用,否则报错。
*force如果为true,引用此program/schedule的job都会被disable,正在运行的job会继续进行。

GET_ATTRIBUTE
SET_ATTRIBUTE
SET_ATTRIBUTE_NULL
过程

DBMS_SCHEDULER.GET_ATTRIBUTE (
   name           IN VARCHAR2,
   attribute      IN VARCHAR2,
   value          OUT {VARCHAR2|PLS_INTEGER|BOOLEAN|DATE|TIMESTAMP|
                        TIMESTAMP WITH TIME ZONE|TIMESTAMP WITH LOCAL TIME ZONE|
                        INTERVAL DAY TO SECOND});

DBMS_SCHEDULER.SET_ATTRIBUTE (
   name           IN VARCHAR2,
   attribute      IN VARCHAR2,
   value          IN {BOOLEAN|DATE|TIMESTAMP|
                        TIMESTAMP WITH TIME ZONE|TIMESTAMP WITH LOCAL TIME ZONE|
                        INTERVAL DAY TO SECOND});

DBMS_SCHEDULER.SET_ATTRIBUTE_NULL (
   name              IN VARCHAR2,
   attribute         IN VARCHAR2);


*一些可以设置的参数:
logging_level
定义如何记录log到dba_scheduler_job_log/dba_scheduler_job_run_details视图。
可用选项如下,是些预定义的常量。
需要注意,实际上的logging level还取决job所属的job_class, 取两者中的最高值。
例如创建job的时候如果不指定job class,默认是DEFAULT_JOB_CLASS,
而DEFAULT_JOB_CLASS的默认logging level是DBMS_SCHEDULER.LOGGING_RUNS,
所以创建的job的logging level至少是LOGGING_RUNS。
1) DBMS_SCHEDULER.LOGGING_OFF 不记录
2) DBMS_SCHEDULER.LOGGING_FAILED_RUNS 只记录失败的job运行
3) DBMS_SCHEDULER.LOGGING_RUNS 记录每次job运行
4) DBMS_SCHEDULER.LOGGING_FULL 不仅记录每次job运行,还包括针对job的任何操作。

max_failures
默认为null,即没有限制。

max_runs
默认为null,即没有限制。

restartable
job执行失败后是否retry,默认为false。 
当设置为true,执行失败1秒后进行第一次retry, 然后是10秒,100秒,每次时间间隔乘10。
最多执行6次retry(大概30小时后)。如果时间超过了下次正常的计划执行的时间,停止retry过程。
对于retry,*_scheduler_jobs视图中的RUN_COUNT, FAILURE_COUNT 不会增加。

此外,repeat_intervalstart_dateend_date等都可以设置。


参数说明
1)schedule_name,program_name,job_name
这些名字在整个sql名字空间内必须唯一。比如,job_name不能和某个表名相同。

2)repeat_interval
定义job的计划,可以指定的形式相当丰富,也相当灵活,很强大。
regular_schedule = frequency_clause
[";" interval_clause] [";" bymonth_clause] [";" byweekno_clause]
[";" byyearday_clause] [";" bydate_clause] [";" bymonthday_clause]
[";" byday_clause] [";" byhour_clause] [";" byminute_clause]
[";" bysecond_clause] [";" bysetpos_clause] [";" include_clause]
[";" exclude_clause] [";" intersect_clause][";" periods_clause]
[";" byperiod_clause]

frequency_clause = "FREQ" "=" "YEARLY" | "MONTHLY" | "WEEKLY" | "DAILY" | 
   "HOURLY" | "MINUTELY" | "SECONDLY"

interval_clause = "INTERVAL" "=" 1 through 99

bymonth_clause = "BYMONTH" "=" {month ( "," month)*}
   month = numeric_month | char_month
   numeric_month = 1 | 2 | 3 ...  12
   char_month = "JAN" | "FEB" | "MAR" | "APR" | "MAY" | "JUN" |
   "JUL" | "AUG" | "SEP" | "OCT" | "NOV" | "DEC"

byweekno_clause = "BYWEEKNO" "=" {weeknumber ( "," weeknumber)*}
   weeknumber = [minus] 1 through 53

byyearday_clause = "BYYEARDAY" "=" {yearday ( "," yearday)*}
   yearday = [minus] 1 through 366
   
bydate_clause = "BYDATE" "=" {date ( "," date)*}
   date = [YYYY]MMDD [ offset | span ]

bymonthday_clause = "BYMONTHDAY" "=" {monthday ( "," monthday)*}
   monthday = [minus] 1 through 31

byday_clause = "BYDAY" "=" {byday ( "," byday)*}
   byday = [weekdaynum] day
   weekdaynum = [minus] daynum
   daynum = 1 through 53 /* if frequency is yearly */
   daynum = 1 through 5  /* if frequency is monthly */
   day = "MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN"
   
byhour_clause = "BYHOUR" "=" {hour ( "," hour)*}
   hour = 0 through 23
   
byminute_clause = "BYMINUTE" "=" {minute ( "," minute)*}
   minute = 0 through 59
 
bysecond_clause = "BYSECOND" "=" {second ( "," second)*}
   second = 0 through 59
   
bysetpos_clause = "BYSETPOS" "=" {setpos ("," setpos)*}
   setpos = [minus] 1 through 9999

include_clause = "INCLUDE" "=" schedule_list
exclude_clause = "EXCLUDE" "=" schedule_list
intersect_clause = "INTERSECT" "=" schedule_list
periods_clause = "PERIODS" "=" periodnum
byperiod_clause = "BYPERIOD" "=" {periodnum ("," periodnum)*}
periodnum = 1 through 100

offset = ("+" | "-") ["OFFSET:"] duration_val
span = ("+" | "-" | "^") "SPAN:" duration_val
duration_val = dur-weeks | dur_days
dur_weeks = numofweeks "W"
dur_days = numofdays "D"
numofweeks = 1 through 53
numofdays = 1 through 376
minus = "-"

举几个例子
a) 05/02 和 09/22 的 8:00 a.m., 1:00 p.m., 6:00 p.m.
'freq=daily;byhour=8,13,18;byminute=0;bysecond=0;bydate=0502,0922'

b) 每个月的最后一个工作日(注意,INTERVAL如果不指定,默认为1)
'FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1'

c) 1/10开始的5天,即1/10~1/14
BYDATE=0110+SPAN:5D
+表示从指定日期开始;-表示到指定日期结束;
^表示围绕指定日期的n天,如果n为偶数,调整为n+1。

d) 以下三种表示方法等同
BYDATE=0205-OFFSET:2W
BYDATE=0205-14D (the OFFSET: keyword is optional)
BYDATE=0122

3)start_date
实际上是schedule生效的日期,
对于一个定时执行的schedule,实际上的开始日期取决于repeat_interval参数。
如果start_date为null,等同于job被enable的时刻。

Oracle取start_date来作为repeat_interval的default值。
例如,如果指定start_date为1/31/2010 9:45:58,指定repeat_interval为'FREQ=YEARLY',
等同于'freq=yearly;bymonth=1;bymonthday=31;byhour=9;byminute=45;bysecond=58'

不能给repeat_interval指定时区信息,Oracle取start_date的时区信息作为指定的时区。

4)end_date
这个时间之后,job将不再被执行。

5)program_type/program_action/number_of_arguments/job_type/job_action
program_type有三种形式
-'PLSQL_BLOCK'
program_action是一个PL/SQL block. 不支持参数,number_of_arguments必须为0.
必须以分号结尾。例如以下三种形式
'my_proc();'
'BEGIN my_proc(); END;'
'DECLARE arg pls_integer:= 10; BEGIN my_proc2(arg); END;'

-'STORED_PROCEDURE'
program_action是一个存储过程,注意不支持INOUT or OUT参数,也不支持function.
参数最多255个,可以通过SET_JOB_ARGUMENT_VALUE过程来设定。
例如'"Schema"."Procedure"'.

-'EXECUTABLE'
program_action是一个外部操作系统的命令行程序,包含完整路径,不能带任何命令行参数。
开始的'?'会被替换为oracle home目录;'@'会被替换为当前oracle实例的SID。

job_type类似于program_type,只是多了'CHAIN'这种类型来创建任务链。
 
6) enabled
如果为TRUE, 创建时候检查program/job有效性,如果通过检查把program/job置为ENABLED.
在program/job使用前必须通过ENABLE过程把它置为ENABLED。
如果program为disabled,仅仅enable一个job,那么job会按计划执行,但是会失败。

7)auto_drop
如果为TRUE, 在job完成之后或者被自动disabled之后job将被自动删除。
如果满足以下条件,job被视为完成。
a) 过了end_date。
b) 达到了最大运行次数(max_runs,可以通过SET_ATTRIBUTE来指定)
c) 非重复任务,即只运行一次的任务,并且已经运行了1次。
如果满足以下条件,job被视为自动disabled.
a) 达到了最大运行失败次数(max_failures,可以通过SET_ATTRIBUTE来指定)


相关数据字典
1) dba_scheduler_jobs/user_scheduler_jobs
Enabling 一个 disabled 状态的job会重设本视图中的RUN_COUNT, FAILURE_COUNT and RETRY_COUNT.

2) dba_scheduler_programs/user_scheduler_programs

3) dba_scheduler_schedules/user_scheduler_schedules
 
4) dba_scheduler_job_log/dba_scheduler_job_run_details

5) dba_scheduler_job_classes

6) 默认情况下,数据库自身定义了一个PURGE_JOB的任务。
该任务每天凌晨3点钟启动,清除30天前所产生的任务日志。

检验运行时间

dbms_scheduler提供了一个过程可以很方便的检验指定的计划(repeat_interval)。
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING (
   calendar_string    IN  VARCHAR2,
   start_date         IN  TIMESTAMP WITH TIME ZONE,
   return_date_after  IN  TIMESTAMP WITH TIME ZONE,
   next_run_date      OUT TIMESTAMP WITH TIME ZONE);

下面创建一个过程evaluate_repeat_interval,
传入repeat_interval字符串和计算的次数,会把每次的执行时间打印出来。

  1. create or replace procedure evaluate_repeat_interval(  
  2.   p_repeat_interval in varchar2,  
  3.   p_number_of_evaluation in int,  
  4.   p_start_date in timestamp with time zone default sysdate  
  5. )   
  6. as  
  7.   l_return_date_after timestamp with time zone;  
  8.   l_next_run_date  timestamp with time zone;  
  9. begin  
  10.   l_return_date_after := p_start_date;  
  11.   for i in 1..p_number_of_evaluation loop  
  12.     dbms_scheduler.evaluate_calendar_string(  
  13.       calendar_string=>p_repeat_interval,  
  14.       start_date=>p_start_date,  
  15.       return_date_after=>l_return_date_after,  
  16.       next_run_date=>l_next_run_date);  
  17.     dbms_output.put_line(l_next_run_date);  
  18.     l_return_date_after := l_next_run_date;  
  19.   end loop;  
  20. end;  
  21.   
  22. --调用的例子1:每个月的最后一天  
  23. begin  
  24. evaluate_repeat_interval(  
  25.   p_repeat_interval=>'FREQ=MONTHLY;BYMONTHDAY=-1',  
  26.   p_number_of_evaluation=>3,  
  27.   p_start_date=>to_timestamp_tz('2012-01-01 00:00:00.000 +08:00',  
  28.     'yyyy-mm-dd hh24:mi:ss.ff tzh:tzm')  
  29.   );  
  30. end;  
  31. --执行结果  
  32. <p>31-JAN-12 12.00.00.000000 AM +08:00  
  33. 29-FEB-12 12.00.00.000000 AM +08:00  
  34. 31-MAR-12 12.00.00.000000 AM +08:00</p><p>PL/SQL procedure successfully completed.</p>  
  35. --调用的例子2:每个月的最后一个工作日  
  36. begin  
  37. evaluate_repeat_interval(  
  38.   p_repeat_interval=>'FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1',  
  39.   p_number_of_evaluation=>3,  
  40.   p_start_date=>to_timestamp_tz('2012-01-01 00:00:00.000 +08:00',  
  41.     'yyyy-mm-dd hh24:mi:ss.ff tzh:tzm')  
  42.   );  
  43. end;  
  44. --执行结果  
  45. <p>31-JAN-12 12.00.00.000000 AM +08:00  
  46. 29-FEB-12 12.00.00.000000 AM +08:00  
  47. 30-MAR-12 12.00.00.000000 AM +08:00</p><p>PL/SQL procedure successfully completed.</p>  
更多0

Oracle 10g之前,可以使用dbms_job来管理定时任务。
10g之后,Oracle引入dbms_scheduler来替代先前的dbms_job,
在功能方面,它比dbms_job提供了更强大的功能和更灵活的机制/管理。

DBMS_JOB包
DBMS_JOB包中包含有许多过程和方法

名称 类型 描述
DBMS_JOB.ISUBMIT 过程

提交一个新任务,用户指定一个任务号
dbms_job.isubmit (
job       IN BINARY_INTEGER,
what      IN VARCHAR2,
next_date IN DATE,
interval  IN VARCHAR2 DEFAULT 'NULL',
no_parse  IN BOOLEAN DEFAULT FALSE);

*no_parse indicates whether to parse job PL/SQL at time of submission (FALSE) or execution (TRUE)
exec dbms_job.isubmit(100, 'begin MYPROC;end;', SYSDATE);

DBMS_JOB.SUBMIT 过程 提交一个新任务,系统指定一个任务号
dbms_job.submit(
JOB       OUT BINARY_INTEGER,
WHAT      IN  VARCHAR2, 
NEXT_DATE IN  DATE           DEFAULT SYSDATE, 
INTERVAL  IN  VARCHAR2       DEFAULT 'NULL',
NO_PARSE  IN  BOOLEAN        DEFAULT FALSE,
INSTANCE  IN  BINARY_INTEGER DEFAULT 0,
FORCE     IN  BOOLEAN        DEFAULT FALSE);
DBMS_JOB.REMOVE 过程 从队列中删除一个已经存在的任务
dbms_job.removejob IN BINARY_INTEGER);
DBMS_JOB.CHANGE 过程 更改用户设定的任务参数
dbms_job.change(
job       IN BINARY_INTEGER,
what      IN VARCHAR2,
next_date IN DATE,
interval  IN VARCHAR2,
instance  IN BINARY_INTEGER DEFAULT NULL,
force     IN BOOLEAN        DEFAULT FALSE);
exec dbms_job.change(100,NULL,NULL,'SYSDATE+3');
DBMS_JOB.WHAT 过程 更改PL/SQL任务定义
dbms_job.what ( 
job  IN BINARY_INTEGER,
what IN VARCHAR2);
DBMS_JOB.NEXT_DATE 过程 更改任务下一次运行时间
dbms_job.next_date( 
job       IN BINARY_INTEGER,
next_date IN DATE);
DBMS_JOB.INTERVAL 过程 更改任务运行的时间间隔
dbms_job.interval ( 
job      IN BINARY_INTEGER,
interval IN VARCHAR2);
exec dbms_job.interval(100,'TRUNC(SYSDATE)+1');
DBMS_JOB.BROKEN 过程 将任务挂起,不让其重复运行,也可以重新启动任务。
dbms_job.broken ( 
job       IN BINARY_INTEGER,
broken    IN BOOLEAN,
next_date IN DATE DEFAULT SYSDATE);
exec dbms_job.broken(100,FALSE,NEXT_DAY(SYSDATE, 'MONDAY'));
DBMS_JOB.RUN 过程 在当前会话中立即执行任务。如果任务是broken状态,改为not broken.
dbms_job.run( 
job   IN BINARY_INTEGER,
force IN BOOLEAN DEFAULT FALSE);
DBMS_JOB.INSTANCE 过程 用于RAC环境,为JOB的执行分配一个实例。
dbms_job.instance(
job      IN BINARY_INTEGER,
instance IN BINARY_INTEGER, 
force    IN BOOLEAN DEFAULT FALSE);
select instance_number from gv$instance;
exec dbms_job.instance(100, 1);
DBMS_JOB.USER_EXPORT 过程 创建文字字符串,用于重新创建一个任务
dbms_job.user_export ( 
job    IN     BINARY_INTEGER,
mycall IN OUT VARCHAR2);
declare
  l_sqltxt varchar2(1000);
begin
  dbms_job.user_export(100,l_sqltxt);
  dbms_output.put_line(l_sqltxt);
end;

注意:执行上面的任何创建/删除/更改任务的过程后一定要马上commit。
          You must issue a COMMIT statement immediately after the statement.
          否则不仅会造成更改无效,甚至很有可能造成一些奇怪的现象,比如job停止之类,切记!

参数说明
DBMS_JOB包中所有的过程都有一组相同的公共参数。
1)job
参数job是一个整数,用来唯一地标示一个任务。
该参数既可由用户指定也可由系统自动赋予。
DBMS_JOB.SUBMIT过程通过获得序列SYS.JOBSEQ的下一个值来自动赋予一个任务号,
该任务号是作为一个OUT参数返回的,所以调用者随后可以识别出提交的任务。
DBMS_JOB.ISUBMIT过程则由调用者给任务指定一个识别号,
如果指定了重复任务号,ISUBMIT过程会抛出一个错误。
当数据库被导出或者被导入的时候,任务号也将被保留下来。
以在执行含有任务的数据的导入/导出操作时很可能会发生任务号冲突的现象。

2)what
what参数是一个可以转化为合法PL/SQL调用的字符串,该调用将被任务队列自动执行。
what参数的长度是4000个字节。
该参数的值一般情况下都是对一个PL/SQL存储过程的调用。PL/SQL调用必须用分号隔开。
还有一个实际经验就是最好将存储过程调用封装在一个匿名块中,这样可以避免一些比较莫名错误的产生。
例如,一般情况下,what参数可以这样引用:what =>’my_proc;’ 
但是比较安全的引用,应该这样写:what =>’begin my_proc; end;’ 
任何时候,我们只要通过更改what参数就可以达到更改任务定义的目的。
但是需要注意,通过改变what参数来改变任务定义时,用户当前的会话设置也被记录下来并成为任务运行环境的一部分。
如果当前会话设置和最初提交任务时的会话设置不同,就有可能改变任务的运行行为。

3)next_date
Next_date参数是用来调度任务队列中该任务下一次运行的时间。
这个参数对于DBMS_JOB.SUBMIT和DBMS_JOB.BROKEN这两个过程确省为系统当前时间,也就是说任务将立即运行。
当将一个任务的next_date参数赋值为null时,则该任务下一次运行的时间将被指定为4000年1月1日,
也就是说该任务将永远不再运行。
如果想在任务队列中保留该任务而又不想让其运行,将next_date设置为null是一个非常简单的办法。
next_date也可以设置为过去的一个时间。系统任务的执行顺序是根据它们下一次的执行时间来确定的,
于是将next_date参数设置为过去就可以达到将该任务排在任务队列前面的目的。

4)Interval
Internal参数是一个表示Oracle合法日期表达式的字符串。
这个日期字符串的值在每次任务被执行时算出,
强调一点,next_date是在一个任务开始时算出的,而不是在任务成功完成时算出的。
算出的日期表达式有两种可能,要么是未来的一个时间要么就是null。
当任务成功完成时,系统更新任务队列表,将下一次任务要运行的时间置为前面算出的next_date值。
当由interval表达式算出next_date是null时,任务自动从任务队列中移出,不会再继续执行。
因此,如果传递一个null值给interval参数,则该任务仅仅执行一次。


JOB_QUEUE_PROCESSES
Oracle有专门的后台进程来执行任务队列。
后台进程的数量通过JOB_QUEUE_PROCESSES来设置,可以设为0到1000。
*JOB_QUEUE_INTERVAL从9i之后就被废弃了。

需要注意,如果配置了最多1 000 个Jnnn进程,并不会看到真的有1 000 个进程随数据库启动。
相反,开始时只会启动一个进程,即作业队列协调器(CJQ0),
它在作业队列表中看到需要运行的作业时,会启动Jnnn 进程。
如果Jnnn 进程完成其工作,并发现没有要处理的新作业,此时Jnnn 进程就会退出。
unix下面可以用ps -ef | grep ora_j 查看这些进程(J000, ... J999),
另外还有一个ora_cjq0_xxx的队列管理进程。

作业队列协调器(CJQ0)进程被唤醒时,
它首先查看任务队列目录中所有的任务是否当前的时间超过了下一次运行的日期时间。
检测到需要该时间立即执行的任务后,这些任务按照下一次执行日期的顺序依次执行。
当开始执行一个任务时,其过程如下:

  1. 以任务所有者的用户名开始一个新的数据库会话。
  2. 当任务第一次提交或是最后一次被修改时,更改会话NLS设置和目前就绪的任务相匹配。
  3. 通过interval日期表达式和系统时间,计算下一次执行时间。
  4. 执行任务定义的PL/SQL
  5. 如果运行成功,任务的下一次执行日期(next_date)被更新,否则,失败计数加1。

任务运行失败后的重试
提交的任务如果运行失败会在2分钟后将再次试图运行该任务。
如果这次运行又失败了,下一次尝试将在4分钟后进行,再下一次在8分钟以后。
任务队列每次加倍重试间隔直到它超过了正常的运行间隔。
所以如果任务的运行间隔设置的比较短,比如1分钟,就观察不到这个重试时间间隔加倍现象。
在连续16次失败后,任务就被标记为中断的(broken),任务将不再重复执行。
这个时候,如果通过broken或者run等过程重新启动任务,成功之行一次后,这个失败间隔会清空。
如果重新启动后还是失败,那么失败次数变成17,job状态变回broken。


相关数据字典
任务队列中的任务信息可以通过以下几个字典视图来查看。

视图名 描述
DBA_JOBS 本数据库中定义到任务队列中的任务
DBA_JOBS_RUNNING 目前正在运行的任务
USER_JOBS 当前用户拥有的任务

DBA_JOBS 和USER_JOBS中的字段。

字段(列) 类型 描述
JOB NUMBER 任务的唯一标示号
LOG_USER VARCHAR2(30) 提交任务的用户
PRIV_USER VARCHAR2(30) 赋予任务权限的用户
SCHEMA_USER VARCHAR2(30) 对任务作语法分析的用户模式
LAST_DATE DATE 最后一次成功运行任务的时间
LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小时,分钟和秒
THIS_DATE DATE 正在运行任务的开始时间,如果没有运行任务则为null
THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小时,分钟和秒
NEXT_DATE DATE 下一次定时运行任务的时间
NEXT_SEC VARCHAR2(8) 如HH24:MM:SS格式的next_date日期的小时,分钟和秒
TOTAL_TIME NUMBER 该任务运行所需要的总时间,单位为秒
BROKEN VARCHAR2(1) 标志参数,Y标示任务中断,以后不会运行
INTERVAL VARCHAR2(200) 用于计算下一运行时间的表达式
FAILURES NUMBER 任务运行连续没有成功的次数
WHAT VARCHAR2(2000) 执行任务的PL/SQL块
CURRENT_SESSION_LABEL RAW MLSLABEL 该任务的信任Oracle会话符
CLEARANCE_HI RAW MLSLABEL 该任务可信任的Oracle最大间隙
CLEARANCE_LO RAW MLSLABEL 该任务可信任的Oracle最小间隙
NLS_ENV VARCHAR2(2000) 任务运行的NLS会话设置
MISC_ENV RAW(32) 任务运行的其他一些会话参数

DBA_JOBS_RUNNING的字段含义

数据类型 描述
SID NUMBER 目前正在运行任务的会话ID
JOB NUMBER 任务的唯一标示符
FAILURES NUMBER 连续不成功执行的累计次数
LAST_DATE DATE 最后一次成功执行的日期
LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小时,分钟和秒
THIS_DATE DATE 目前正在运行任务的开始日期
THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小时,分钟和秒


任务运行间隔指定
任务重复运行的时间间隔取决于interval参数中设置的日期表达式。

最简单的需求是特定的时间间隔后,重复运行该任务。例如天运行一次'sysdate+1'。
这样可能带来的问题是不能保证任务的下一次运行的准确时间。
比如第一次运行在午夜12点,这样以后每次运行理论上都在午夜12点。
但是如果某用户在上午8点使用run过程执行了该任务,以后该任务重新定时到上午8点运行。
另外如果数据库关闭或者说任务队列非常的忙以至于任务不能在计划的那个时间点准时执行,
都可能运行时间的不断“漂移”。

另一种需求是需要要任务在特定时间执行,下面是一些例子。
#每天午夜12点 'TRUNC(SYSDATE + 1)' 
#每天早上8点30分 'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)' 
#每星期二中午12点 'NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24' 
#每个月第一天的午夜12点 'TRUNC(LAST_DAY(SYSDATE ) + 1)' 
#每季度的第一天凌晨1点 'TRUNC(ADD_MONTHS(SYSDATE,3),'Q') + 1/24'
#每个季度最后一天的晚上11点 'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24'
#每年1月1日凌晨1点执行 'add_months(trunc(sysdate,''yyyy''),12)+1/24'
#每星期六和日上午11点 'trunc(least(next_day(sysdate,7),next_day(sysdate,1)))+(11*60)/(24*60)'
  注:1-星期天 2-星期1 3-星期2 ... 7-星期6


Oracle定时任务(1)-DBMS_SCHEDULER

Oracle 10g之前,可以使用dbms_job来管理定时任务。 10g之后,Oracle引入dbms_scheduler来替代先前的dbms_job, 在功能方面,它比dbms_job提供了更...
  • fw0124
  • fw0124
  • 2011年09月06日 15:51
  • 13980

oracle调度程序作业dbms_scheduler

转自:http://www.cnblogs.com/doc/archive/2009/02/04/1384018.html 整理scheduler 这一部分,源于最近发现系统上自动采集...
  • Rain_Gao
  • Rain_Gao
  • 2016年06月29日 14:42
  • 633

Oracle 使用DBMS_SCHEDULER创建定时任务

在Oracle10g里面,已经不赞成使用DBMS_JOB,推荐使用DBMS_SCHEDULER,它的健壮为调度提供更好的规划和结构。下面我只简单写一个例子。 begin     DBMS_SCHE...
  • Seabiscuit_92
  • Seabiscuit_92
  • 2016年04月01日 17:08
  • 2856

oracle实现每天定时执行一个计划任务

http://www.shangxueba.com/jingyan/1614101.html oracle实现每天定时执行一个计划任务     创建测试表     SQL> cr...
  • xwawa2012
  • xwawa2012
  • 2017年01月13日 10:18
  • 3135

oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。

oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。   一、查询系统中的job,可以查询视图   --相关视图 select * f...
  • fu_pengfei_love822
  • fu_pengfei_love822
  • 2017年05月04日 17:30
  • 2607

ORACLE数据库定时任务

用于安排和管理作业队列,通过使用作业,可以使ORACLE数据库定期执行特定的任务。 一、dbms_job涉及到的知识点 1、创建job: variable jobno number; dbms_jo...
  • u013531928
  • u013531928
  • 2015年08月17日 12:31
  • 2918

Oracle中的job的定时任务

oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。  一、查询系统中的job,可以查询视图 --相关视图 select * from dba_jobs; sele...
  • YSC1123
  • YSC1123
  • 2016年01月28日 12:51
  • 3579

dbms_scheduler包中job(作业)学习

1、dbms_scheduler         Oracle 10g引入dbms_scheduler来替代先前的dbms_job,在功能方面,它比dbms_job提供了更强大的功能和更灵活的机制/管...
  • u013062902
  • u013062902
  • 2013年12月18日 20:28
  • 1662

oracle起定时任务,每隔1秒执行一次

创建一个测试表和一个存储过程: [sql] view plain copy  print? create table a(a date);   ...
  • konglongaa
  • konglongaa
  • 2017年02月09日 11:27
  • 1370

oracle定时任务的编写及查看删除

declare jobno number; begin dbms_job.submit(   jobno,--定时器ID,系统自动获得   'PRC_INSERT;', --w...
  • heidou_2016
  • heidou_2016
  • 2016年08月15日 17:39
  • 5208
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Oracle定时任务-DBMS_SCHEDULER
举报原因:
原因补充:

(最多只允许输入30个字)