Oracle定时任务
一、DBMS_JOBS
DBMS_JOB包由$ORACLE_HOME/rdbms/admin/dbmsjob.sql和prvtjob.plb两个脚本文件创建,其中这两个文件被catproc.sql在创建数据库后被立即调用执行。脚本为DBMS_JOB包创建了一个公共同义词,并给DBMS_JOB包赋予了公共的可执行权限,所有Oracle用户都可使用DBMS_JOB包。
常用数据字典有DBA_JOBS、USER_JOBS、DBA_JOBS_RUNNING,这些数据字典由catjobq.sql脚本创建,catjobq.sql同样也在创建数据库后被catproc.sql调用执行。
若要Job可以被正常执行,需要将数据库中的参数job_queue_processes设置为大于0的一个数字,即job的队列过程数,随着Oracle启动而启动SNP(任务队列后台过程),最多可启动36个SNP。
1.DBMS_JOB包含的过程
名称 | 描述 | 类型 |
DBMS_JOB.ISUBMIT | 提交一个新任务,用户指定一个任务号 | 过程 |
DBMS_JOB.SUBMIT | 提交一个新任务,系统指定一个任务号 | 过程 |
DBMS_JOB.REMOVE | 从队列中删除一个已存在的任务 | 过程 |
DBMS_JOB.CHANGE | 更改用户设定的任务参数 | 过程 |
DBMS_JOB.WHAT | 更改PL/SQL任务定义 | 过程 |
DBMS_JOB.NETX_DATE | 更改任务下一次运行时间 | 过程 |
DBMS_JOB.INSTNACE |
| 过程 |
DBMS_JOB.INTERVAL | 更改任务运行的时间间隔 | 过程 |
DBMS_JOB.BROKEN | 将任务挂起,不让其重复运行 | 过程 |
DBMS_JOB.RUN | 当前会话中立即执行任务 | 过程 |
DBMS_JOB.USER_EXPORT | 创建文字字符串,用于重新创建一个任务 | 过程 |
DBMS_JOB.IS_JOBQ |
| 函数 |
DBMS_JOB.BACKGROUND_PROCESS |
| 函数 |
2.DBMS_JOB包参数
名称 | 类型 | 注释 |
Job | Binary_integer | 任务的唯一识别码 |
What | Varchar2 | 作为任务执行的PL/SQL代码 |
Next_date | Varchar2 | 任务下一次运行的时间 |
Interval | Varchar2 | 日期表达式,用来计算下一次任务运行的时间 |
Job说明:
job参数是一个整数,用来唯一标示一个任务。该参数可以由用户指定也可以系统自动生成,其取决于提交任务时选用的任务提交存储过程。如果使用dbms_job.submit过程通过获得序列sys.jobseq的下一个值自动赋值任务号,如果使用dbms_jobisubmit过程则调用者给任务指定一个识别号。任务号只有在删除或者重新提交任务时可以变更,其他情况不会变更。
What说明:
what参数是一个可以转化为合服PL/SQL调用的字符串,该调用将被任务队列自动执行。如果参数中使用了文字字符串,需要将字符串用单引号括起来,而PL/SQL必须用分号分隔,例如:
what =>’my_procedure(parameter1);’
what =>’my_procedure(parameter1);end;’ ##安全写法
需要注意的是通过当前会话设置的what参数会被记录下来当做任务运行环境的一部分,而且what参数限制在2000字节以内。
Next_date说明
Next_date参数用来调度任务队列中该任务下一次运行的时间,这个参数对于dbms_job.submit和dbms_job.broken两个存储过程缺省为系统当前时间,即任务立即执行。
当一个任务的next_date参数赋值为null时,则该任务下一次运行的时间将被指定为4000年1月1日,即任务将永远不再被执行,其用以保留任务而不让其运行。也可以将这个参数值设置为过去的某个时间点。
Interval参数说明
Interval参数是一个表示Oracle合法日期表达式的字符串。这个日期字符串的值在每次任务被执行时算出,其结果值要么是未来的某个时间要么为null。当interval的值为null时,则该任务仅被执行一次。
Job_queue_interval
任务队列规程定期唤醒并检查队列目录表是否有任务需要被执行,其决定SNP过程两次检查目录表休眠多少时间,单位是秒。默认设置为60S,超出这个时间范围的JOB不会被执行。
Job_queue_keep_connections
参数值为true和false,表示SNP两个任务运行期间(休眠间隔),当true时任然保持和Oracle的连接,当false时SNP断开和数据库连接,当唤醒时又重新连接并检查任务队列。主要考虑队列的有效性和数据库的关闭方法,一般执行频繁的任务可以设置为true,执行不频繁的设置为false即可。
Job_queue_processes
任务队列数。
4. DBMS_JOB执行过程
①以任务所有者用户开启一个新数据库会话;
②当任务第一次提交或最后一次修改完成时,更改会话的NLS和目前就绪的任务相匹配;
③通过interval日期表达式和系统时间,计算下一次任务执行时间;
④执行定义的PL/SQL存储过程;
⑤如果运行成功,则任务下一次执行日期(Next_date)被更新,否则失败计数加1,累积达16次则job终止执行,或者超出执行范围job同样终止执行;
⑥经过job_queue_interval秒后,又到另一个任务执行,重复上述工作。
注意:
当任务运行失败时,SNP过程在1分钟后将再次试图运行该任务。如果这次运行又失败了,下一次尝试将在2分钟后进行,再下一次在4分钟以后。任务队列每次加倍重试间隔直到它超过了正常的运行间隔。在连续16次失败后,任务就被标记为中断的(broken),如果没有用户干预,任务队列将不再重复执行。
5.DBMS_JOB任务队列视图
任务队列数据字典:
视图名 | 描述 |
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日期的小时,分钟和秒 |
6.DBMS_JOB时间间隔设置
任何重复运行的任务时间间隔取决于interval参数设置的日期表达式,一个定时任务一般设定要求有三种,分别是:
(1) 在一个特定时间间隔后,重复运行该任务;可用’sysdate + N' ,N以天为单位。
(2) 在特定时间和日期运行任务;
(3) 任务完成后,下一次执行任务在一个特定的时间间隔后。
时间间隔interval设置示例1:(无法指定特定日期和时间)
描述 | Interval参数值 |
每天运行一次 | 'SYSDATE + 1' |
每小时运行一次 | 'SYSDATE + 1/24' |
每10分钟运行一次 | 'SYSDATE + 10/(60*24)' |
每30秒运行一次 | 'SYSDATE + 30/(60*24*60)' |
每隔一星期运行一次 | 'SYSDATE + 7' |
不再运行该任务并删除它 | NULL |
注意:
上述时间间隔设置不能保障下一次运行的时间在一个特定的日期或者时间,仅指定一个任务两次运行的时间间隔。例如,如果一个任务第一次运行是在凌晨12点,interval指定为'SYSDATE + 1',则该任务将被计划在第二天的凌晨12点执行。但是,如果某用户在下午4点手工(DBMS_JOB.RUN)执行了该任务,那么该任务将被重新定时到第二天的下午4点。还有一个可能的原因是如果数据库关闭或者说任务队列非常的忙以至于任务不能在计划的那个时间点准时执行。在这种情况下,任务将试图尽快运行,也就是说只要数据库一打开或者是任务队列不忙就开始执行,但是这时,运行时间已经从原来的提交时间漂移到了后来真正的运行时间。这种下一次运行时间的不断“漂移”是采用简单时间间隔表达式的典型特征。
时间间隔interval设置示例2:(定时到特定时间和日期)
描述 | INTERVAL参数值 |
每天午夜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)' |
每个季度最后一天的晚上11点 | 'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24' |
每星期六和日早上6点10分 | 'TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) +(6×60+10)/(24×60)' |
7.DBMS_JOB创建示例
declare
jid number;
begin
dbms_job.submit(job => jid,
what => 'begin insert into old_job_test values(sysdate, ''abc''); commit; end;',
interval => 'trunc(sysdate,''mi'')+3/24/60');
commit;
dbms_output.put_line(jid);
end;
二、DBMS_Scheduler
1. DBMS_Scheduler创建示例
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'INSERT_TEST_TBL',
job_type => 'STORED_PROCEDURE',
job_action => ' P_ INSERT INTOTEST ',
start_date => sysdate,
repeat_interval => 'FREQ=DAILY;INTERVAL=1');
END;
/
Job_name指定任务名称,名称必须唯一,Job_name可以指定到特定用户下,例如scott.job_name。
Job_Type任务执行的操作类型,可以是以下类型
⑴plsql_block表示任务执行的是一个PL/SQL匿名块
⑵、stored_procedure表示指定的Oracle过程(含PL/SQL Procedure和Java Procedure) executable表示执行的是一个外部程序,比如说系统命令
⑶、chain表示任务执行的是一个chain
Job_Action任务执行操作,应与Job_type指定的参数相匹配
Start_Date指定任务初次执行的时间,可以为空,空值表示立即执行,空值等同于sysdate。
REPEAT_INTERVAL指定任务执行频率,隔多长时间再次执行,可以为空值,空值表示只执行一次,其中包含的重要参数有FREQ和INTERVAL,FREQ可以为YEARLY,MONTHLY,WEEKLY,DAILY,HOURLY,MINUTELY,SECONDLY,表示年、月、日、时、分、秒,INTERVAL表示时间间隔频率,取值范围为1-99。示例表示每天执行一次,如果INTERVAL是7,则表示每隔7天执行一次等同于weekly , 1。
ENABLED指定任务是否启动,默认是False表示该任务不会被执行,除非手动调用,或用户手动将该参数设置为TRUE。
RESTARTABLE指定jobs运行出错后,是否能够适时重启创建任务时如未明确指定,本参数默认情况下设置为FALSE,如果设置为TRUE,就表示当任务运行时出错,下次运行时间点到达时仍会启动,并且如果运行仍然出错,会继续重新运行,不过如果连接出错达到6次,该job就会停止。
MAX_FAILURES指定jobs最大连续出错次数该参数值可指定的范围从1-1000000,默认情况下该参数设置为NULL,表示无限制。达到指定出错次数后,该job会被自动disable。
2. DBMS_Scheduler相关视图
DBA_SCHEDULER_JOBS
ALL_SCHEDULER_JOBS
USER_SCHEDULER_JOBS
DBA_SCHEDULER_JOB_LOG
3. DBMS_Scheduler管理
(1)、启用Jobs
创建Jobs的时候没有显示指定ENABLED参数,即时指定了START_DATE参数,默认情况下JOB也不会被调用,因此可以通过修改JOB的启动状态,具体如下:
exec dbms_scheduler.enable(“JOB_NAME”) ;
(2)、禁用Jobs
exec dbms_scheduler.disable(“JOB_NAME”) ;
(3)、修改Jobs
exec dbms_scheduler.set_attribute("INSERT_TEST_TBL","JOB_ACTION","P_ INSERT INTOTEST");
(4)、执行Jobs
exec dbms_scheduler.run_job("Job_name ");
(5)、停止Jobs
exec dbms_scheduler.stop_job("Job_name");
(6)、删除Jobs
exec dbms_scheduler.drop_job("Job_name");
(7)创建Jobs
begin
sys.dbms_scheduler.create_job(job_name =>'SCOTT.TEST_JOB',
job_type =>'STORED_PROCEDURE',
job_action =>'t1_pro',
start_date =>to_date('27-11-2015 09:06:47','dd-mm-yyyy hh24:mi:ss'),
repeat_interval =>'Freq=daily;Interval=1;ByHour=10;ByMinute=30;BySecond=30',
end_date =>to_date(null),
job_class =>'DEFAULT_JOB_CLASS',
enabled =>true,
auto_drop =>true,
comments =>'');
end;
/
4. DBMS_Scheduler Repeat_interval设置详解
repeat_interval => =>'Freq=daily;Interval=1;ByMonth=Feb;ByWeekNo=17;ByYearDay=7;ByMonthDay=9;ByDay=Wed;ByHour=10;ByMinute=52;BySecond=00'
参数名 | 参数值 |
FREQ | YEARLY|MONTHLY|WEEKLY|DAILY|HOURLY|MINUTLY|SECONDLY |
INTERVAL | [1-99] |
BYMONTH | [1-12] OR JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|DEP|OCT|NOV|DEC |
BYWEEKNO | [1-53] OR [-53,-1] |
BYYEARDAY | [1-366] OR [-366,-1] |
BYMONTHDAY | [1-31] OR [-31,-1] |
BYDAY | MON|TUE|WED|THU|FRI|SAT|SUN |
BYHOUR | [0-23] |
BYMINUTE | [0-59] |
BYSECOND | [0-59] |
每隔10分钟运行一次:
REPEAT_INTERVAL => 'FREQ=HOURLY; BYMINUTE=0,10,20,30,40,50; BYSECOND=0'或
REPEAT_INTERVAL => 'FREQ=MINUTELY; BYMINUTE=0,10,20,30,40,50; BYSECOND=0'
每周五运行:
REPEAT_INTERVAL => ‘FREQ=DAILY; BYDAY=FRI’; 或
REPEAT_INTERVAL => ‘FREQ=WEEKLY; BYDAY=FRI’;或
REPEAT_INTERVAL => ‘FREQ=YEARLY; BYDAY=FRI’;
当月最后一天运行:
REPEAT_INTERVAL => ‘FREQ=MONTHLY; BYMONTHDAY=-1’;
每天下午4,5,6点定时运行:
REPEAT_INTERVAL => ‘FREQ=DAILY; BYHOUR=16,17,18’;
只运行一次:
repeat_interval => null
BEGIN
dbms_scheduler.create_schedule(repeat_interval => null,
start_date => systimestamp,
schedule_name => 'scheduler_0306_2');
dbms_scheduler.create_job(job_name => 'job_0306_2',
program_name => 'program_0306',
schedule_name => 'scheduler_0306_2',
auto_drop => FALSE,
enabled => TRUE);
END;
5. DBMS_Scheduler注意点
(1) 设置运行时间,注意系统时间和时区的设置
Linux
更改/etc/timezone里面的内容为:Asia/Shanghai
#mv /etc/localtime /etc/localtime-2015
# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
Oracle
select dbtimezone from dual;
select sessiontimezone from dual;
alter database set time_zone='+08:00';
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/27067062/viewspace-2127806/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/27067062/viewspace-2127806/