[ORACLE] ORA-04013 错误的解决方案

错误信息:

ORA-04013: CACHE 值必须小于 CYCLE 值

ORA-04013: number to CACHE must be less than one cycle

 

关键词:Sequence

 

问题描述:开发人员反映部署于凌晨执行的自动作业在5月7日凌晨执行失败,而之前的几天内都是执行成功的,之间并未有对该自动作业进行过修改的操作,且测试环境未曾失败过。

使用select * from user_jobs查询发现上一次执行成功的时间点是5月6日凌晨0点,下一次计划执行时间为5月7日17点,累计连续执行失败次数9次。(9次计数的原因可参考文档2)

 

解决方案:查询数据库alert日志,查看当日凌晨自动作业失败原因。

Thu May 07 00:00:04 2020

Errors in file /oracle/app/oracle/diag/rdbms/xxxxxx/xxxxxx1/trace/xxxxxx1_j001_46361.trc::

ORA-12012: 自动执行作业 1 出错

ORA-04013: CACHE 值必须小于 CYCLE 值

ORA-06512: 在 "SCHEMA.RESET_SEQUENCE", line 9

ORA-06512: 在 line 1

 

咨询开发人员,关于此自动作业的内容,得知为

 

create sequence xxx_sequence increment by 1 start with 1 maxvalue 9999999 minvalue 1 cycle cache 500;

create or replace procedure reset_sequence
as
n number(10);
xsql varchar2(100);
begin
	execute immediate 'select xxx_sequence.nextval from dual' into n;
	n:=-(n-1);
	xsql:= 'alter sequence xxx_sequence increment by '|| n;
	execute immediate xsql;
	execute immediate 'select xxx_sequence.nextval from dual' into n;
	xsql:= 'alter sequence xxx_sequence increment by 1';
	execute immediate xsql;
	xsql:= 'update TABLE_XXX set XXNO='||n||'';
	execute immediate xsql;
end;

 

根据Oracle数据库关于保证数据一致性的特点,在创建/修改sequence时必须满足以下条件:

CACHE < CEIL (MAXVALUE-MINVALUE) / ABS (INCREMENT)

 

将上图中的数据代入公式中,不等号右边MAXVALUE为9999999,MINVALUE为1,所以CEIL (MAXVALUE-MINVALUE)为CEIL (9999999-1)=9999998;不等号左边CACHE值为500,那么我们可以计算出,INCREMENT允许的最大值为19999.996。当INCREMENT大于19999.996时,会造成不等号右边的值小于500,而当不等号左边的CACHE值设置为500。则不满足该条件,数据库系统会报错。

 

而在此作业中,报错的第9行内容,xsql=’alter sequence xxx_sequence increment by n’中的n一值,为第8行中n:=-(n-1),于是根据上文的计算我们可以得出,当此时n的绝对值大于等于20000、即第7行将select xxx_sequence_nextval from dual赋值给n,当时的n大于等于20001时,就会触发整个CYCLE值小于CACHE值的问题。

 

咨询开发人员得知,报错的5月7日0点时,前一天的业务量大约在7万多笔,即当时的n大约为7万多,超出了之前计算的阈值20001,所以引起了数据库报错。

 

回想之前5月1日凌晨成功执行的4月30日当天可能未有大量交易,5月2日至5月6日凌晨成功执行的对应5月1日至5日为非工作日,交易量可能也不大;而失败的5月7日凌晨对应的5月6日为5月份的第一个工作日,交易量要比之前的几天有明显的上升,突破了阈值,造成了数据库报错,自动作业执行失败。

 

对此,一般处理方式,在CACHE < CEIL (MAXVALUE-MINVALUE) / ABS (INCREMENT)

此公式中,要么减小CACHE值,要么扩大CYCLE值,使此不等式永恒成立。经开发人员调整,在下图的第9行中,将alter sequence xxx_sequence increment by n 设置为nocache,此时cache值为0,不等式将永恒成立(存在极小概率当nextval恰好为9999999时n等于0的情况)。

 

create or replace procedure reset_sequence
as
n number(10);
xsql varchar2(100);
begin
	execute immediate 'select xxx_sequence.nextval from dual' into n;
	n:=9999999-n;
	xsql:= 'alter sequence xxx_sequence increment by '||n||' nocache';
	execute immediate xsql;
	execute immediate 'select xxx_sequence.nextval from dual' into n;
	xsql:= 'alter sequence xxx_sequence increment by 1 cache 500';
	execute immediate xsql;
	xsql:= 'update TABLE_XXX set XXNO='||n||'';
	execute immediate xsql;
end;

 

观察5月8日起至5月12日的自动作业结果,报错未再现,自动作业成功。

 

 


参考文档1:关于Oracle数据库中Sequence的相关参数。

 

创建序列需要CREATE SEQUENCE系统权限。序列的创建语法如下:

 

  CREATE SEQUENCE 序列名

  [INCREMENT BY n]

  [START WITH n]

  [{MAXVALUE/ MINVALUE n| NOMAXVALUE}]

  [{CYCLE|NOCYCLE}]

  [{CACHE n| NOCACHE}];

 

    其中:

1)  INCREMENT BY用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表Oracle序列的值是按照此步长递减的。

2)  START WITH 定义序列的初始值(即产生的第一个值),默认为1。

3)  MAXVALUE 定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项,代表没有最大值定义,这时对于递增Oracle序列,系统能够产生的最大值是10的27次方;对于递减序列,最大值是-1。

4)  MINVALUE定义序列生成器能产生的最小值。选项NOMINVALUE是默认选项,代表没有最小值定义,这时对于递减序列,系统能够产生的最小值是负10的26次方;对于递增序列,最小值是1。

5)  CYCLE和NOCYCLE 表示当序列生成器的值达到限制值后是否循环。CYCLE代表循环,NOCYCLE代表不循环。如果循环,则当递增序列达到最大值时,循环到最小值;对于递减序列达到最小值时,循环到最大值。如果不循环,达到限制值后,继续产生新值就会发生错误。

6)  CACHE(缓冲)定义存放序列的内存块的大小,默认为20。NOCACHE表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能。

大量语句发生请求,申请序列时,为了避免序列在运用层实现序列而引起的性能瓶颈。Oracle序列允许将序列提前生成 cache x个先存入内存,在发生大量申请序列语句时,可直接到运行最快的内存中去得到序列。但cache个数也不能设置太大,因为在数据库重启时,会清空内存信息,预存在内存中的序列会丢失,当数据库再次启动后,序列从上次内存中最大的序列号+1 开始存入cache x个。这种情况也能会在数据库关闭时也会导致序号不连续。

7)  NEXTVAL 返回序列中下一个有效的值,任何用户都可以引用。

 CURRVAL 中存放序列的当前值,NEXTVAL 应在 CURRVAL 之前指定 ,二者应同时有效。

 使用ALTER SEQUENCE时,不可以修改START值。如果需要改变START值,需要删除后再重建此SEQUENCE。

 

 

参考文档2:关于Oracle数据库中自动作业失败后的重试机制。

 

当Oracle数据库中自动作业失败后,会在一定时间内进行自动重试,重试的间隔为2分钟、4分钟、8分钟、16分钟,……,以此类推。

第10次重试间隔为1024分钟。从第11次开始,重试时间为固定的1440分钟(24小时)。在第16次重试失败后,该自动作业将会被标记为broken,不再进行重试。

当Oracle数据库重试的时间到达设定的下次执行时间后,以设定的作业执行时间为准。

 

 

参考资料:

Oracle 更改序列属性遇到ORA-04007 错误。http://www.dbdream.com.cn/2018/03/oracle-%e6%9b%b4%e6%94%b9%e5%ba%8f%e5%88%97%e5%b1%9e%e6%80%a7%e9%81%87%e5%88%b0ora-04007-%e9%94%99%e8%af%af/

Oracle SEQUENCE 详细说明。https://blog.csdn.net/sd_tz_wzg/article/details/33728731

Oracle 数据库 JOB 失败后的重试规律解密。https://blog.csdn.net/renfengjun/article/details/25595923

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值