注:因近日在设定 ORACLE job时,存在间隔时间非按照设定的间隔执行的情况,后参考下文解决
转自《永州异蛇》BLOG
現象:
在 oracle 920 中设置了一个 job ,间隔执行时间是 sysdate+10/1440,也就是
10 分钟执行一次,
结果观察执行的时间如下:
2004-10-19 8:58:42
2004-10-19 9:08:43
2004-10-19 9:18:48
2004-10-19 9:28:49
2004-10-19 9:38:54
2004-10-19 9:48:55
2004-10-19 9:59:00------多了一份鈡
2004-10-19 10:09:01
改正的辦法:
使用job中,oracle计算下次执行时间的sysdate是在当前job执行完成的时间,所以
job会有这个误差:
解决如下:
nextdate: trunc(sysdate+1/144,'MI'),
interval: trunc(sysdate+1/144,'MI')
dbms_job.submit(
you_jobno,
'you_procedure;',
trunc(sysdate+1/144,'MI'),
'trunc(sysdate+1/144,''MI'')');
結果:
在测试情况下,时间间隔改成了一分钟
trunc(sysdate+1/1440,'MI')
(job 运行的时间在 0.02 s 左右)
运行时间如下 :
2004-10-21 9:05:06
2004-10-21 9:06:02
2004-10-21 9:07:04
2004-10-21 9:08:05
2004-10-21 9:09:01
2004-10-21 9:10:03
2004-10-21 9:11:05
2004-10-21 9:12:01
虽然还是有点误差,但是这个误差不会积累,基本符合要求,
我想是因为在计算下次运行时间的时候 trunc 了一下,就得到了
一个准确的时间。
解釋:
关于job 的时间误差,我谈谈以下几点:
1.关于时间重叠的问题
比如我有两个JOB,都是在凌晨3点运行,那么如果其中一个在3点运行,那么另一个必须等待第一个JOB完成,然后才能执行。特别是有些象sysdate+1/24,这样每阁一小时运行的JOB就更容易冲突
2.即使没有时间重叠,ORACLE也是按job_queue_internal(通常是1分钟)的间隔进行检查JOB队列,这样3点钟的作业正好在3:00:45才检查到,那么就会在3:00:45才执行该job.我们知道ORACLE JOB如果第一次执行失败,那么按一定的时间间隔再次启动该JOB直到成功,如果直到运行16次还是失败,那么就中断该JOB,所以实际运行的时间会进行推迟
3.采用”精确定时“函数(从前面可能看到,其实是很难实现精确定时执行JOB的)
我们可以采用如trunc(sysdate)+(1+24)/25或trunc(sysdate)+25/24。表示每天1点执行job,这样就不会受上次JOB延时的影响
4. 在 8i 中有 job_queue_interval 来决定最大误差范围,默认好象是 60 s
在 Oracle9i中这个参数的名称变成了._job_queue_interval 默认值为5s (jametong)
但是可以通过设置job 的 interval: trunc(sysdate+1) 类似,排除误差的累积!
5. Oracle job是由数个job进程来执行job中的任务,在执行完一个job后计算该job的下一个执行时间,因此假设oracle job的时间间隔是1分钟,如果job中的存储过程没有执行完毕,在下一分钟也不会再执行该存储过程。