有一个地市的oracle主机非常奇怪,客户端连接后经常莫名其妙的断网,而且在command 并不会提示错误,具体的表现是command窗口里面一直显示在执行,但很可能该过程在数据库当中都已经停止运行,实际上执行时间稍微长一些的存储过程往往都要对执行的结果进行检查,对于没有执行的部分 还需要重新执行,非常麻烦,但是一时又找不到发生这种情况的原因,于是想到用oracle的job来执行。
declare n number;
begin
dbms_job.submit(:n,'proc_name;',trunc(sysdate)+1/24,'trunc(sysdate)+1+1/24');
end;
执行之后 报错:ORA-01008:并非所有变量都关联
取掉变量:n前面的冒号,再次执行,
declare n number;
begin
dbms_job.submit(n,'proc_name;',trunc(sysdate)+1+1/24,'trunc(sysdate)+1+1/24');
end;
成功。
另外在cmd当中执行
variable n number;
begin
dbms_job.submit(:n,'proc_name;',trunc(sysdate)+1/24,'trunc(sysdate)+1+1/24');
end;
也是一样的 而且还能直接显示job number。 需要仔细看两段语句的不同 declare和variable 以及n 和:n
这里n是job number,
'proc_name;'是需要执行的存储过程名称,
trunc(sysdate)+1+1/24 首次执行时间
'trunc(sysdate)+1+1/24') 是下一次执行时间
由于执行之后不能马上看出效果,于是对日期进行修改,
declare n number;
begin
dbms_job.submit(n,'proc_name;',to_date('2009-3-11 14:00:00‘,'yyyy-mm-dd hh24:mi:ss'),'trunc(sysdate)+1+1/24');
end;
执行之后 查看执行记录 select * from user_jobs 发现并没有 执行。
google之后发现需要查看job的参数job_queue_processes 是否为0
SQL>show parameter job
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
job_queue_processes integer 0
SQL>
由于value=0 表示job不会自动执行,因此需要改为不为0的值,其他值的含义比如5 就表示并行度,可以同时执行5个job,其余job等待执行完成后再接着执行,但是这里有出现了一个问题,假如有4个job正在执行,这个时候又有两个job的执行时间到了,那么这个时候这两个job就只会执行其中一个,而另外一个则会等待。
因此告诉地市相关人员 他们的job_queue_processes需要设置 可能需要重启,由于是报表数据库,因此只能选择在晚上下班之后进行操作。
由于以前有过乱改参数造成数据库无法启动的错误,因此首先在自己的机器上进行测试,由于自己的主机是10g,而地市的主机是9i,因此不敢盲目的将10g的修改方法套用在9i上面,于是在itpub论坛发帖求助,可能是由于发错了版面,没有人回复帖子,最后还是google确认了9i的修改方法 那就是
在管理员权限下执行
SQL>alter system set job_queue_processes=10 scope=spfile;
在这里scope 有三个可选值 MEMORY ,SPFILE , BOTH 意思分别是:
MEMORY:只改变当前实例运行
SPFILE:只改变SPFILE的文件
BOTH:改变spfile和当前的实例
然后找空闲的时间重启就可以了,在重启了机器之后,我以为之前建的job就不会启用,由于job启用的存储过程都有日志记录,不料在查看日志的时候发现 有重复执行的情况,原来我又重新建立了job,而之前建立的job在数据库重启之后 没有在user_jobs里面发现,但是oracle还是执行了,正如我们刚才讨论的并行度的问题一样,job是等待执行,即便过了计划执行时间,还是会执行的。 在这里可能也有人有疑问 为什么job会不存在了呢? 因为我建的是执行一次的job,原因前面也说过了 是因为客户端执行断网的缘故才启用job。
在这里要说明的是 执行一次的job在执行完毕之后 在user_jobs里面就找不到相关的记录了。
那也有人要问执行一次应该怎么写语句?聪明的你一定想到了 那就是把下一次执行那地方空起来。
declare n number;
begin
dbms_job.submit(n,'proc_name;',to_date('2009-3-11 14:00:00‘,'yyyy-mm-dd hh24:mi:ss'),'');
end;
这样就只会执行一次了 启用了job之后 地市的问题暂时得到了解决,但是这并不是根治的方法 那个奇怪的断网错误还是需要解决才行啊。
另外如果想让一个job立刻执行的话,比如当前日期是2009-3-13 15:39:00
那么只需要将日期指定比它还早的任何一个时间 比如2009-3-13 15:38:00
job就会在创建后调用存储过程。