一、JOB时间间隔的问题

我们MIS系统中需要建立一些JOB,比如客户会要求在月底自动生成一些报表统计信息。

在指定JOB的执行时间时,一般我们会选择在每月月底的午夜来执行(或者有多个JOB,应该分散在不同的时间段来执行)。此时不能直接用sysdate来确定时间,因为每次执行后,oracle自动生成的下一次的执行时间,会有几秒的延迟。

比如,我指定第一次执行时间为:2008-03-27 10:58:01,时间间隔的方式为:last_day(add_months(sysdate, 1))。

那么,JOB执行后我会发现,第一次的执行时间是2008-03-27 10:58:05,而下一次的执行时间被更新为2008-04-30 10:58:05;而下次执行后,发现它的执行时间是2008-04-30 10:58:07,而它再次执行的时间变为2008-05-31 10:58:07;……

二、可能原因

(1)JOB的调用有时间延迟。我指定在10:58:01执行,可是由于延迟,真正执行的时间是10:58:05;

(2)根据实际的执行时间来自动计算下一次的执行时间。我指定下一次的时间计算方法是last_day(add_months(sysdate, 1))。但它是根据10:58:05来计算的,而不是10:58:01。

三、解决办法

这种延迟累计起来,就可能导致执行时间错误!为避免这种延迟,我们应该手工指定执行时间中的“时分秒”。比如,

每月月底的午夜:

last_day(add_months(to_date(to_char(sysdate, 'yyyy-mm-dd'), 'yyyy-mm-dd'), 1))

每月的任意指定时间:

last_day(add_months(to_date(to_char(sysdate, 'yyyy-mm-dd') || ' 11:24:31', 'yyyy-mm-dd hh24:mi:ss'), 1))

……

这样,每次执行的时间大概会比指定的时间延迟2-5秒,但oracle自动计算出来的下一次执行时间是没有问题的,所以不会累计这个延迟。

四、相关测试

下面是一个小测试:

SQL> conn tianyc/test

已连接。

SQL> select * from v$version;

BANNER

-----------------------------------------------------------

Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production

PL/SQL Release 9.2.0.1.0 - Production

CORE    9.2.0.1.0       Production

TNS for 32-bit Windows: Version 9.2.0.1.0 - Production

NLSRTL Version 9.2.0.1.0 - Production

-- 1. 创建初始环境

-- 1.1 创建表test_job,存放执行日期SQL> create table test_job ( a date );

表已创建。

-- 1.2 创建过程,向表test_job中插入执行时的日期

SQL> CREATE OR REPLACE PROCEDURE PRC_TEST_JOB(PRM_A        IN DATE,

2                                           PRM_APPCODE  OUT NUMBER,

3                                           PRM_ERRORMSG OUT VARCHAR2)

4  IS

5  BEGIN

6    PRM_APPCODE := 1;

7    PRM_ERRORMSG := 'succeed';

8    INSERT INTO test_job VALUES(prm_a);

9    COMMIT;

10  END PRC_TEST_JOB;

11

12  /

过程已创建。

-- 2. 创建任务

-- 2.1 查看当前时间,用来确定创建的任务的执行时间

SQL> select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY

-------------------

2008-03-27 10:52:20

-- 2.2 创建任务,调用步骤1.2中创建的过程。在10:58:01时执行。

SQL> variable x number;

SQL> begin

2    sys.dbms_job.submit(job => :x,

3                        what => 'DECLARE

4                                    n_appcode NUMBER(10);

5                                    v_errormsg VARCHAR2(4000);

6                                  BEGIN

7                                    prc_test_job(SYSDATE, n_appcode, v_errormsg);

8                                  END;',

9                        next_date => to_date('27-03-2008 10:58:01', 'dd-mm-yyyy hh24:mi:ss'),

10                        interval => 'last_day(add_months(sysdate, 1))');

11    commit;

12  end;

13  /

PL/SQL 过程已成功完成。

-- 3. 验证数据

-- 3.1 在该执行时间之前没有数据

SQL> select * from test_job;

未选定行

SQL> select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY

-------------------

2008-03-27 10:57:46

-- 3.2 过了该时间后,可以查询到数据

SQL> select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY

-------------------

2008-03-27 10:58:18

SQL> select to_char(a, 'yyyy-mm-dd hh24:mi:ss') from test_job;

TO_CHAR(A,'YYYY-MM-

-------------------

2008-03-27 10:58:05

-- 3.3 任务执行完毕后,自动根据条件(INTERVAL)更新下次的执行时间(NEXT_DATE)

SQL> select PRIV_USER, LAST_DATE, NEXT_DATE, INTERVAL from user_jobs;

PRIV_USER                      LAST_DATE  NEXT_DATE  INTERVAL

------------------------------ ---------- ---------- ----------------------------------

TIANYC                         27-3月 -08 30-4月 -08 last_day(add_months(sysdate, 1))

SQL> select what from user_jobs;

WHAT

-------------------------------------------------------------------------------

DECLARE

n_appcode NUMBER(10);

v_errormsg VARCHAR2(4000);

BEGIN

prc_test_job(SYSDATE, n_appcode, v_errormsg);

END;

SQL>

-- 4. 存在问题:

-- 4.1 test_job里的执行时间不是10:58:01, 而是10:58:05:

SQL> select to_char(a, 'yyyy-mm-dd hh24:mi:ss') from test_job;

TO_CHAR(A,'YYYY-MM-

-------------------

2008-03-27 10:58:05

-- 4.2 在视图user_jobs里也是如此。把这两个时间精确到秒,看看效果:

SQL> select PRIV_USER, to_char(LAST_DATE, 'yyyy-mm-dd hh24:mi:ss'),

2   to_char(NEXT_DATE, 'yyyy-mm-dd hh24:mi:ss'), INTERVAL from user_jobs;

PRIV_USER  TO_CHAR(LAST_DATE,' TO_CHAR(NEXT_DATE,' INTERVAL

---------- ------------------- ------------------- --------------------------------

TIANYC     2008-03-27 10:58:05 2008-04-30 10:58:05 last_day(add_months(sysdate, 1))

SQL>

-- 4.3 经过多次测试,每次执行时并不是按照上次指定的秒执行的,而是滞后几秒。这样累计起来,就可能导致执行日期的错误。

--      所以要想每次都精确地按照秒来执行job,应该手工来指定时间。比如:

-- 4.3.1 在每个月的月底的午夜执行

SQL> select to_char(last_day(add_months(to_date(to_char(sysdate, 'yyyy-mm-dd'), 'yyyy-mm-dd'), 1)), 'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(LAST_DAY(AD

-------------------

2008-04-30 00:00:00

-- 4.3.2 在每个月的月底的任意指定时间执行(这里我指定时间为11:24:31)

SQL> select to_char(last_day(add_months(to_date(to_char(sysdate, 'yyyy-mm-dd') || ' 11:24:31', 'yyyy-mm-dd hh24:mi:ss'), 1)), 'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(LAST_DAY(AD

-------------------

2008-04-30 11:24:31

SQL>

oracle中每月调用一次,JOB——手工指定Oracle中job执行的时间间隔相关推荐

  1. C语言:从键盘中输入字符串,追加填写到指定文件中

    /*从键盘中输入字符串,追加填写到指定文件中*/ #include <stdio.h> #include <string.h> #include <ctype.h> ...

  2. c++语言程序中,要调用的函数必须在main()函数中定义,惠州学院C++考试复习题

    惠州学院C++复习题 一.选择题 1.C++的源文件的扩展名是_____C____. A.h B.obj C.cpp D.exe 2.下列选项能够作为C++变量名的是___C____. A.false ...

  3. c语言中怎么调用自己定义的函数,c语言中怎么调用自己定义的函数?

    一,函数调用的一般形式为: 函数名(实参列表); 实参可以是常数.变量.表达式等,多个实参用逗号,分隔. 在C语言中,函数调用的方式有多种,例如: 在函数调用中还应该注意的一个问题是求值顺序的问题.所 ...

  4. ImpREC手工指定IAT中的表项值

    前言 在做Armadillo1.x的脱壳练习, 找OEP, 脱壳还是一样的. 但是在IAT修复时, 遇到了新知识点. 我找到了壳代码写IAT表项的代码, 由于很乱, 没有找到合适的点来修改(让壳代码写 ...

  5. python类中方法调用自己类的方法_python 类中方法总结 --- 实例方法、类方法、静态方法...

    在python的类语法中,可以出现三种方法,具体如下: (1)实例方法 1)第一个参数必须是实例本身,一般使用[self]表示. 2)在实例方法中,可以通过[self]来操作实例属性,[类名]来操作类 ...

  6. oracle中每月调用一次,Oracle Job的使用(定时执行)

    转载自:https://www.cnblogs.com/Chestnuts/articles/7066333.html oracle中的job能为你做的就是在你规定的时间格式里执行存储过程,定时执行一 ...

  7. java中如何调用自身结构_如何在Java中的自定义异常中设置我自己的消息,可以检索我的getMessage()但是没有使用构造函数,有什么办法吗?...

    我刚学习 Java中的异常处理.我想知道的不是尝试说: throw new Exception("My Message"); 和 String message=ex.getMess ...

  8. Android中实现调用摄像头拍照并显示在ImageView中

    场景 点击拍照按钮调用系统摄像机进行拍照,并将拍的照片显示在ImageView中. 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的 ...

  9. c语言中被调用函数只需在主调函数中声明,其他函数中不用声明,求助,函数在其他函数中使用时要先声明后调用,这个没声明就用了...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 如题,程序如下: #include #include //malloc,calloc,free,realloc头文件 #define LEN sizeof ...

  10. oracle数据库扩大表空间,[小技巧]手工扩大Oracle数据库表空间的方法

    1.首先查看表空间的名字和所属文件select tablespace_name, file_id, file_name,round(bytes/(1024*1024),0) total_spacefr ...

最新文章

  1. matlab外部接口简介
  2. 基于DDD的.NET开发框架 - ABP领域服务
  3. checkbox选中和不选中 jqu_jquery checkbox 选中不选中
  4. 站立会议(11月19日)
  5. power iso linux启动盘,Power ISO Maker/ISO燃烧到磁盘工具 V3.0版
  6. Java 创建线程的三种方式
  7. PSD分层电商促销模板|季末大促上演
  8. Spring MVC JSR-303验证框架之Hibernate-Validator
  9. sublime text3 Package Control 插件安装及推荐(MAC)
  10. 约数国王c语言,求最大公约数问题
  11. JSON解析方式 gson
  12. PaddlePaddle(8)—— 如何写好一篇高质量的精选项目
  13. android 样式预处理,基于Android平台的字符识别预处理算法设计与实现
  14. QML 环形进度条canvas 98行代码实现
  15. 在Centos操作系统下安装mysql8.0
  16. VXLAN技术——数据中心底层技术
  17. Nginx: 104: Connection reset by peer 错误
  18. LeetCode08 有效的数独
  19. 面试B站,结果面试官牵着一条狗出来面试我....这是什么操作??
  20. 2023银行校园招聘简历自我评价高分写法模板

热门文章

  1. C语言基础:C语言宏定义(2) - 带参数的宏定义
  2. Xamarin Android中引用Jar包的方法
  3. 通过和函数名相同的字符串调用函数 --浅谈loadstring函数
  4. mysql 51.数据库下载_Database Master官方下载_MySQL/SQLite数据库管理软件V5.2.51.18513下载(暂未上线)_预约_飞翔下载...
  5. 微信怎么at所有人_变速箱报废、发动机故障、车门下沉,全新马自达3到底怎么了?...
  6. Spring-BeanPostProcessor的执行顺序
  7. Spring中注册Bean的方式有哪些?
  8. SQL查找是否存在,别再count了
  9. 警惕!这5种“脸色”在暗示你这些健康问题!
  10. Windows服务器配置fileZilla Server