知识大全 Oracle作业(JOB)更新next
Posted 时间
篇首语:你最愿意做的那件事,才是你真正的天赋所在。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Oracle作业(JOB)更新next相关的知识,希望对你有一定的参考价值。
Oracle作业(JOB)更新next 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
摘要:本文通过实验和事件跟踪来分析Oracle Job执行过程中修改下次执行时间的机制 有些人问 Oracle的JOB在设定完next_date和interval之后 到底是什么时候决定下一次运行时间的 可以归纳成以下几个问题 . 假设我们的JOB设定第一次运行的时间是 : 运行的间隔是 小时 JOB运行需要耗时 分钟 那么第二次运行是在 : 还是 : ? . 如果是在 : 那是不是说明只要JOB一开始运行 next_date就被重新计算了? . JOB的下一次运行会受到上一次运行时间的影响吗?如果受到影响 如何可以避免这个影响而让JOB在每天的指定时刻运行? 本文通过一些实验和跟踪来解释上面的所有问题 首先我们选择一个测试用户 假设该用户名为kamus 由于我们在实验用的存储过程中会用到dbms_lock包 所以需要由sys用户先授予kamus用户使用dbms_lock包的权限 d:\\Temp>sqlplus / as sysdba SQL*Plus: Release Production on 星期三 月 : : Copyright (c) Oracle Corporation All rights reserved 连接到: Oracle i Enterprise Edition Release Production With the Partitioning OLAP and Oracle Data Mining options JServer Release Production SQL> grant execute on dbms_lock to kamus; 授权成功 然后用kamus用户登录数据库 创建我们测试使用的存储过程sp_test_next_date create or replace procedure sp_test_next_date as p_jobno number; P_nextdate date; begin 将调用此存储过程的job的next_date设置为 分钟以后 select job into p_jobno from user_jobs where what = sp_test_next_date; ; execute immediate begin dbms_job next_date( || to_char(p_jobno) || sysdate+ / );mit;end; ; 修改完毕以后检查user_jobs视图 输出job目前的next_date select next_date into P_nextdate from user_jobs where what = sp_test_next_date; ; dbms_output put_line( JOB执行中的next_date: || to_char(p_nextdate YYYY MM DD HH :MI:SS )); 等待 秒再退出执行 dbms_lock sleep(seconds => ); end sp_test_next_date; 创建调用该存储过程的JOB 定义interval为每天一次 也就是这次执行以后 下次执行时间应该在 天以后 SQL> variable jobno number; SQL> BEGIN DBMS_JOB SUBMIT(job => :jobno what => sp_test_next_date; next_date => SYSDATE interval => SYSDATE+ ); MIT; END; / PL/SQL 过程已成功完成 jobno 然后我们手工执行存储过程 执行完毕以后再手工从user_jobs视图中获得JOB的下次执行时间 可以看到在存储过程中修改的JOB的下次执行时间已经生效 变成了当前时间的 分钟以后 而不是默认的 天以后 SQL> conn kamus 请输入口令: 已连接 SQL> set serverout on SQL> exec sp_test_next_date(); JOB执行中的next_date: : : PL/SQL 过程已成功完成 SQL> col next_date for a SQL> select to_char(next_date YYYY MM DD HH :MI:SS ) next_date from user_jobs where what = sp_test_next_date; ; NEXT_DATE 我们再手工运行JOB 看看这次的结果 可以发现JOB没有运行完毕以前被修改了的下次运行时间跟JOB运行完毕以后再次手工检索user_jobs视图获得的下次运行时间已经不相同了 由此我们可以得出一个结论 next_date是在JOB运行完毕以后被Oracle自动修改的 而不是在JOB刚开始运行的时候 因为我们在存储过程中修改的next_date在JOB运行结束之后又被修改为默认的 天以后了 SQL> exec dbms_job run( ); JOB执行中的next_date: : : PL/SQL 过程已成功完成 SQL> select to_char(next_date YYYY MM DD HH :MI:SS ) next_date from user_jobs where what = sp_test_next_date; ; NEXT_DATE 现在我们再次修改存储过程 输出存储过程开始执行的时间 便于跟执行完毕以后的JOB下次执行时间进行比较 create or replace procedure sp_test_next_date as p_jobno number; P_nextdate date; begin 输出JOB刚开始执行的时间 dbms_output put_line( JOB开始执行的时间: || to_char(sysdate YYYY MM DD HH :MI:SS )); 将调用此存储过程的job的next_date设置为 分钟以后 select job into p_jobno from user_jobs where what = sp_test_next_date; ; execute immediate begin dbms_job next_date( || to_char(p_jobno) || sysdate+ / );mit;end; ; 修改完毕以后检查user_jobs视图 输出job目前的next_date select next_date into P_nextdate from user_jobs where what = sp_test_next_date; ; dbms_output put_line( JOB执行中的next_date: || to_char(p_nextdate YYYY MM DD HH :MI:SS )); 等待 秒再退出执行 dbms_lock sleep(seconds => ); end sp_test_next_date; 重新进行测试 我们可以发现JOB的next_date是JOB开始执行时间的 天以后 而不是JOB结束时间的 天以后(因为JOB结束需要经过 秒钟) SQL> exec dbms_job run( ); JOB开始执行的时间: : : JOB执行中的next_date: : : PL/SQL 过程已成功完成 SQL> select to_char(next_date YYYY MM DD HH :MI:SS ) next_date from user_jobs where what = sp_test_next_date; ; NEXT_DATE 至此 我们已经说明了两个问题 就是 JOB在运行结束之后才会更新next_date 但是计算的方法是JOB刚开始的时间加上interval设定的间隔 下面我们通过trace来再次求证这个结论 SQL> ALTER SESSION SET EVENTS trace name context forever level ; 会话已更改 SQL> exec dbms_job run( ); PL/SQL 过程已成功完成 SQL> ALTER SESSION SET EVENTS trace name context off ; 会话已更改 执行完毕以后在udump目录中查看生成的trace文件 如果我们用tkprof来格式化这个trace文件然后再查看格式化后的结果 我们会感到很诧异 因为在格式化完毕的SQL执行顺序中 更新job$表的语句出现在dbms_job next_date语句之前 也就是看上去是Oracle先按照interval自动更新了JOB的next_date 然后才继续往下执行存储过程中定义的next_date更新语句 而这样显然无法解释我们在上面的实验中看到的结果 但是当我们跳过tkprof而直接去查看生成的trace文件 就会恍然大悟 同时也印证了steve adams在ixora上提到的观点 tkprof格式化完的结果会省略一些信息 甚至在有时候会给我们错误的信息 直接查看trace文件 我们可以看到如下的执行顺序 . parse cursor # (oracle根据interval和先前保存的this_date字段值更新job$表的语句 包括更新failures last_date next_date total等) . parse cursor # (存储过程中的begin dbms_job next_date语句) . binds cursor # (将加上了 分钟的时间绑定到cursor # 上) . exec cursor # (执行cursor # ) . wait cursor # (经历一个PL/SQL lock timer事件 也就是存储过程中执行的dbms_lock sleep方法) . binds cursor # (将JOB刚开始执行时候的时间绑定到cursor # 上) . exec cursor # (执行cursor # ) 也就是说虽然更新job$的语句被很早地解析过了 但是直到JOB运行结束时这个被解析过的游标才开始作变量绑定进而开始执行 正是因为解析update sys job$语句的时间早于解析begin dbms_job next_date语句的时间 所以tkprof的结果将前者放在了前面 由于trace文件过长 所以不在本文中贴出了 如果有兴趣可以发邮件给我 我的邮件地址是 本文的最后一部分 解答本文开头提出的第三个问题 也就是 JOB的下一次运行会受到上一次运行时间的影响吗?如果受到影响 如何可以避免这个影响而让JOB在每天的指定时刻运行? JOB的下一次运行时间是会受上一次影响的 如果我们的interval仅仅是sysdate+ / 这样的形式的话 无疑 上次执行的时间再加上 小时就 cha138/Article/program/Oracle/201311/18096相关参考
现象 在oracle的工作队列里面执行存储过程执行出错导致队列死掉了我使用remove把作业从工作队列里面去除掉重新修改过程可是编译的时候死掉了根据以往的经验是因为过程正在执行的时候不能编译的原
一设置初始化参数job_queue_processes sql>altersystemsetjob_queue_processes=n;(n>) job_queue_process
OracleJOB用法小结 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一设置初始化参数job
Oracle数据库定时器Job 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 写法 decla
Oracle中如何根据时间来执行JOB 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!问题假设有一个
解析Oracle查询和删除JOB的SQL 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!本篇文章是对
Oracle数据库中如何根据时间来执行JOB 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 问题
Oracle更新操作优化 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 首先描述一下更新的要求根
Oracle提供免费OracleLinux更新源 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
Oracle多表级联更新详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!我们在平时的工作中可能遇