几天前, 公司的 job 调度出现了问题, 由于权限管的严, 没有查看 Oracle 一些重要的数据字典, 后面联系 DBA, 是由于数据库切换到备机时, 参数设置不对, 导致 db job 没有正常调度.
今天刚好有时间, 想总结下 Oracle 的定时任务, 写的不好的地方, 请多多指教!
--1. 先检查 oracle job 两个重要参数 job_queue_processes 和 aq_tm_processes
- SQL> show parameter job_queue_processes;
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- job_queue_processes integer 0
- SQL> show parameter aq_tm_processes;
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- aq_tm_processes integer 0
--2. 新建一个序列, 作为数据来源
- -- Create sequence
- create sequence s_seq
- minvalue 0
- maxvalue 10000
- start with 1
- increment by 1
- order;
--3. 新建一张测试表
- --create table
- create table t_job(
- id number,
- record_time date
- );
--4. 创建一个存储过程;
- create or replace procedure proc_test_job as
- begin
- insert into t_job
- (id,record_time)
- select s_seq.nextval,sysdate from dual;
- commit;
- end proc_test_job;
- /
--5. 创建一个定时任务
- declare
- job_number number;
- cursor job_cursor is select * from user_jobs where what like '%proc_test_job%';
- begin
- for x in job_cursor loop
- job_number:=x.job;
- sys.dbms_job.remove(job_number);
- end loop;
- commit;
- -- Call the procedure
sys.dbms_job.submit(job => job_number, --out 参数, job 编号
what => 'proc_test_job;', -- 注意有分号
next_date => sysdate + 5/(24*60), -- 下一个 5 分钟执行
interval => 'trunc(sysdate,''mi'')+1/(24*60)' -- 每隔一分钟执行
- );
- commit;
- end;
- /
--6. 查看 job 的信息
- select t.JOB, t.NEXT_DATE, t.WHAT, t.INTERVAL, t.*
- from user_jobs t
- where t.WHAT like '%proc_test_job%';
--7. 设置 第 1 步中的两个参数
- SQL> alter system set job_queue_processes = 10 scope = both;
- System altered
- SQL> alter system set aq_tm_processes = 1 scope = both;
- System altered
--8. 查看 job 的信息以及目标表的数据, 从以下查看, 确实是每隔 1 分中执行一次
这样就完成了一个 Oracle Job 定时任务的配置了.
在实际工作, 由于业务的需要, 比如公司经常做活动, 那可能会经常调整 db job 调度时间. 下面讲解一些在工作当中操作 job 的 sp
1. 要修改 job 的下次启动时间;
- begin
- -- Call the procedure
sys.dbms_job.next_date(job => :job, --job 是入参, 对应的是 user_jobs 中的 job 字段信息
next_date => :next_date); --job 下次启动时间
end;
2. 要停止调度 job;
- begin
- -- Call the procedure
- sys.dbms_job.broken(job => :job,
- broken => broken,
- next_date => :next_date); -- next_date(指定某一时刻停止) sysdate(立刻停止)
- end;
3. 删除 job
- begin
- -- Call the procedure
- sys.dbms_job.remove(job => :job);
- end;
4. 启动 job
- begin
- -- Call the procedure
- sys.dbms_job.run(job => :job, force => force);
- end;
5. 修改要执行的 job
- begin
- -- Call the procedure
- sys.dbms_job.what(job => :job,
- what => :what);
- end;
--6. 修改 job 的执行间隔
- begin
- -- Call the procedure
- sys.dbms_job.interval(job => :job,
- interval => :interval);
- end;
一些常用的时间设置
1: 每分钟执行
Interval => TRUNC(sysdate,'mi') + 1/ (24*60) -- 每分钟执行
interval => 'sysdate+1/(24*60)' -- 每分钟执行
interval => 'sysdate+1' -- 每天
interval => 'sysdate+1/24' -- 每小时
interval => 'sysdate+2/24*60' -- 每 2 分钟
interval => 'sysdate+30/24*60*60' -- 每 30 秒
2: 每天定时执行
Interval => TRUNC(sysdate+1) -- 每天凌晨 0 点执行
Interval => TRUNC(sysdate+1)+1/24 -- 每天凌晨 1 点执行
Interval => TRUNC(SYSDATE+1)+(8*60+30)/(24*60) -- 每天早上 8 点 30 分执行
3: 每周定时执行
Interval => TRUNC(next_day(sysdate,'星期一'))+1/24 -- 每周一凌晨 1 点执行
Interval => TRUNC(next_day(sysdate,1))+2/24 -- 每周一凌晨 2 点执行
4: 每月定时执行
Interval =>TTRUNC(LAST_DAY(SYSDATE)+1) -- 每月 1 日凌晨 0 点执行
Interval =>TRUNC(LAST_DAY(SYSDATE))+1+1/24 -- 每月 1 日凌晨 1 点执行
5: 每季度定时执行
Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') -- 每季度的第一天凌晨 0 点执行
Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') + 1/24 -- 每季度的第一天凌晨 1 点执行
Interval => TRUNC(ADD_MONTHS(SYSDATE+ 2/24,3),'q')-1/24 -- 每季度的最后一天的晚上 11 点执行
6: 每半年定时执行
Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+1/24 -- 每年 7 月 1 日和 1 月 1 日凌晨 1 点
7: 每年定时执行
Interval =>ADD_MONTHS(trunc(sysdate,'yyyy'),12)+1/24 -- 每年 1 月 1 日凌晨 1 点执行
来源: http://www.linuxidc.com/Linux/2019-04/158196.htm