工作中需要一个定时任务来抽取数据,之前采用的是dbms_job包下的过程来创建job,遇到了一些问题。找了下资料,得知oracle10g以后就推荐采用dbms_scheduler包来取代dbms_job来创建定时任务。下面简单介绍下两者的使用方法及使用过程中的一些体会。
1.先创建日志表,用于记录存储过程执行时间及结果
create table bak_job_test(date_time date,mark varchar2(200));
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;
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分钟执行一次,调用存储过程创建表,结果报错:权限不足。之前了解过,定义存储过程时加上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;
定时器执行,调用存储过程创建表成功了,不需要显示的授权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。