oracle定时任务dbms_job与dbms_scheduler使用方法
2018年08月20日 13:18:20 风灵使 阅读数:111
工作中需要一个定时任务来抽取数据,之前采用的是dbms_job
包下的过程来创建job
,遇到了一些问题。找了下资料,得知oracle10g
以后就推荐采用dbms_scheduler
包来取代dbms_job
来创建定时任务。下面简单介绍下两者的使用方法及使用过程中的一些体会。
1.先创建日志表,用于记录存储过程执行时间及结果
create table bak_job_test(date_time date,mark varchar2(200));
- 1
2.创建一个存储过程,用于创建表
create or replace procedure my_test authid current_user is
v_count number := 0;
v_mess varchar2(200) := '';
begin
select count(1) into v_count from user_tables t where t.TABLE_NAME = 'BAK_JOB_TABLES';
if v_count > 0 then
execute immediate 'drop table bak_job_tables purge';
end if;
execute immediate 'create table bak_job_tables as select * from user_tables where 1=2';
insert into bak_job_test(date_time,mark) values(sysdate,'success');
exception
when others then
v_mess := substr(SQLERRM,0,200);
insert into bak_job_test(date_time,mark) values(sysdate,v_mess);
end;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
3.使用dbms_job
包创建定时任务
declare
myjob number;
begin
dbms_job.submit(myjob,'begin my_test; end;',sysdate,'TRUNC(sysdate,''mi'') + 1 / (24*60)');
commit;
end;
- 1
- 2
- 3
- 4
- 5
- 6
定时器1分钟执行一次,调用存储过程创建表,结果报错:权限不足。之前了解过,定义存储过程时加上authid current_user
就可以在存储过程里面使用当前用户所角色的权限,出现这种问题 让人很费解,手动授权grant create table to user
之后,确实可以解决这个问题,但是这种方式不通用,特别是存储过程里面用到其他的权限的时候就不方便了。所以决定试试dbms_scheduler
包来创建定时任务。
先简单介绍下dbms_job
包下常见的过程:
1) dbms_job.remove(jobId)
删除job
定时任务,可以从user_jobs
视图中查看job
的详细情况
2) dbms_job.run(jobid)
运行定时任务
3) dbms_job.broken(jobid,true)
终止定时任务
4) dbms_job.interval(jobid,'interval')
修改定时任务的执行时间
4.使用dbms_scheduler
创建定时任务
使用dbms_scheduler
需要具有create job
权限,对定时任务一些操作需要具有MANAGE SCHEDULER
权限,如:dbms_scheduler.stop_job('my_job_test',true);
BEGIN
dbms_scheduler.create_job(job_name => 'my_job_test',
job_type => 'STORED_PROCEDURE',
job_action => 'my_test',
start_date => sysdate,
repeat_interval => 'sysdate + 1/1440',
enabled => TRUE,
comments => 'test');
end;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
定时器执行,调用存储过程创建表成功了,不需要显示的授权grant create table to user
,只需要存错过程定义为authid current_user
即可。个人觉得dbms_job
在调用authid current_user
的存储过程的时候,未能调用到用户具有的角色的权限,这或许是dbms_job
的一个bug
。
简单介绍下dbms_scheduler
关于定时任务的一些常用过程:
1) dbms_scheduler.run(jobName)
运行job
2) dbms_scheduler.stop_job(jobName,force)
停止job
,force
默认为false
,oracle
建议false
停止失败情况下,使用true
,且使用true
需要有manage scheduler
权限
3) dbms_scheduler.drop_job(jobName)
删除job
4) dbms_scheduler.enable(jobName)
打开job
5) dbms_scheduler.disable(jobName,force)
禁用job
,force
参数用于dependencies
,如果TRUE
,即使其他对象依赖于它,操作也能成功
相关视图
1) user_scheduler_jobs
查看job
信息
2) User_Scheduler_Job_Log job
job日志
3) user_scheduler_job_run_details
job运行日志
4) user_scheduler_running_jobs
正在运行的job
总结:
oracle
定时任务,dbms_job
调用存储过程创建表,需要显示授权,存储过程定义为authid current_user
也不行,而dbms_scheduler
是不需要显示授权的,这点来说后者更方便使用。另外,dbms_scheduler
提供了job
运行日志记录视图,可以查看具体的运行日志,比较实用。而且,oracle10g
以后也推荐使用dbms_scheduler
。
https://blog.csdn.net/lldustc_blog/article/details/52944927
Oracle Job 定时调用存储过程
2011年11月03日 13:22:32 webajax 阅读数:702
--创建测试表名
create table job_table(run_date date);
--创建存储过程
create or replace procedure job_proc as
begin
insert into job_table (run_date) values (sysdate);
end;
--创建job并指定一分钟执行一次
declare
job number;
begin
dbms_job.submit(job,'job_proc;',sysdate,'TRUNC(sysdate,''mi'')+1/(24*60)');
end;
commit;
--暂停任务
--select job from user_jobs
找出job的id值,然后使用下面的放语句停止任务。
begin
dbms_job.broken(584,true);
end;
--重启任务
begin
dbms_job.run(584);
end;
--删除任务
delete user_jobs where job=584;
drop procedure job_proc;
drop table job_table;
创建job后。系统即会在指定时间里自动调用该存储过程。
关于时间间隔的相关知识:
1.TRUNC(for dates)
TRUNC函数为指定元素而截去的日期值。
其具体的语法格式如下:
TRUNC(date[,fmt])
其中: date 一个日期值 fmt 日期格式,该日期将由指定的元素格式所截去。忽略它则由最近的日期截去
下面是该函数的使用情况:
TRUNC(TO_DATE('24-Nov-1999 08:00 pm'),'dd-mon-yyyy hh:mi am') ='24-Nov-1999 12:00:00 am'
TRUNC(TO_DATE('24-Nov-1999 08:37 pm','dd-mon-yyyy hh:mi am'),'hh') ='24-Nov-1999 08:00:00 am'
trunc(sysdate,'yyyy') --返回当年第一天.
trunc(sysdate,'mm') --返回当月第一天.
trunc(sysdate,'d') --返回当前星期的第一天.
trunc(sysdate,'dd')--返回当前年月日
trunc函数后面加的数字的单位是天。
每天凌晨0点0分:trunc(sysdate+1)
每天早上8点 trunc(sysdate+1)+1/3
每天早上8点30分 trunc(sysdate+1)+(8.5*60)/(24*60)
每天早上8点30分 trunc(sysdate+1)+8.5/24
每天早上8点30分 trunc(sysdate+1)+(8*60+30)/(24*60)
https://blog.csdn.net/webajax/article/details/6931770
oracle使用DBMS_SCHEDULER调度作业
置顶 2016年10月27日 13:24:14 lldustc 阅读数:9522 标签: oracle 更多
个人分类: oracle
dbms_scheduler包的功能比dbms_job包强大很多,但是很多初学者直接被它的复杂性吓跑了,跟着我,只需几分钟就会用了。
三个概念
大多数人看到这个包里的函数和函数里众多的参数,就开始晕菜了,不要被这些表象迷惑了,其实这些东西都是围绕着三个基本概念,schedule,program和job。oracle是为了复用的目的,提炼出了调度的这三个要素,弄懂这三个要素,立刻豁然开朗。
schedule
schedule表示调度计划表。调度从什么时间开始被调度,什么时候结束,以什么频度调度。使用DBMS_SCHEDULER.CREATE_SCHEDULE过程创建schedule。
begin
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => ¨daily_schedule¨,
start_date => SYSDATE,
repeat_interval => ¨FREQ=DAILY ; INTERVAL=1¨,
comments => ¨every one day¨);
END;
/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
其中repeat_interval参数,支持两种格式:
- dbms_job里的interval格式,建议让这种晦涩语法见鬼去吧
- 日历表达式(linux系统的crontab使用的格式)
日历表达式分为三部分: 第一部分是频率,也就是”FREQ”这个关键字,它是必须指定的; 第二部分是时间间隔,也就是”INTERVAL”这个关键字,取值范围是1-999. 它是可选的参数; 第三部分是附加的参数,可用于精确地指定日期和时间,它也是可选的参数,下面这些值都是合法的:
BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY
BYHOUR,BYMINUTE,BYSECOND
看几个例子就会用了
每隔2小时运行一次
repeat_interval => 'FREQ=HOURLY; INTERVAL=2'
每天运行一次
repeat_interval => 'FREQ=DAILY'
每周的1,3,5运行
repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,WED,FRI"
每年的3,6,9,12月的18号运行
repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=18'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
另外使用dbms_scheduler.evaluate_calendar_string可以方便的计算出什么时候执行该调度。
program
program表示调度应该做什么事情,是对程序的抽象。使用DBMS_SCHEDULER.CREATE_PROGRAM创建program
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => ¨time_synchronization¨,
program_action => ¨/sbin/ntpdate 128.59.67.100¨,
program_type => ¨EXECUTABLE¨,
enabled => TRUE);
END;
/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
调度现在可以支持调用外部程序了,这点很强大。
目前程序支持三种类型:
- PL/SQL块: PLSQL_BLOCK,
- 存储过程: STORED_PROCEDURE
- 外部程序: EXECUTABLE, 外部程序可以是一个shell脚本,也可以是操作系统级别的命令。
program_action: 根据program_type的不同,program_action有不同的含义。
- program_type是存储过程,就需要指定存储过程的名字;
- program_type是PL/SQL块,就需要输入完整的PL/SQL代码;
- program_type是外部程序,就需要输入script的名称或者操作系统的指令名
job
job表示按照指定的schedule,执行指定program,完成用户指定的工作。使用DBMS_SCHEDULER.CREATE_JOB创建job。
SQL> BEGIN
2 DBMS_SCHEDULER.CREATE_JOB (
3 job_name => ¨time_synchron¨,
4 program_name => ¨time_synchronization¨,
5 schedule_name => ¨daily_schedule¨,
6 enabled => true);
7 END;
8 /
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
调度的相关操作
作业相关操作
一般情况下是如果你设定了job的enable是true的话,oracle会按照你的计划,定时调用你的job,不需要手动执行。如果临时需要马上调度job也是可以的。
exec dbms_scheduler.run_job(¨time_synchron¨);
- 1
如果觉得没有必要继续执行这个job了,可以停止该job,让oracle以后不要再继续调度了。
exec dbms_scheduler.stop_job(¨time_synchron¨);
- 1
查看作业相关情况
Job 每执行一次,无论成功或失败,均会[DBA|ALL|USER]_SCHEDULER_JOB_LOG中生成一条对应的记录(前提是LOGGING_LEVEL属性值未设置为DBMS_SCHEDULER.LOGGING_OFF),job的详细信息可以通过
[DBA|ALL|USER]_SCHEDULER_JOB_RUN_DETAILS视图查看。