Oracle数据库SEQUENCE溢出异常预防测试

发表于:2019-12-26 09:56

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:孙小平    来源:51Testing软件测试网原创

  在系统实现中,经常需要用到序列号来记录操作执行的顺序或者打印时间戳等。因为序列号等我们只取正值,所以一般都使用无符号数以表示更大的范围。虽然一般的32位或者64位无符号数表示的范围很大,甚至可以确保在系统的生命周期内都不会用完,但是作为一个健壮的系统还是需要考虑无符号数达到最大后,重新归零的溢出问题。
  事件背景:
  数据库在sequence没有超过INTEGER类型上限时,系统程序代码中那些错误的和无意义的类型转换、实体类和BEAN用INTEGER类型作为主键的情况是不会引起错误的,一旦超过INTEGER类型上限时,这些场景下就会发生ID变成负数的情况,从而发生保存到数据库中的外键是负数或者根据ID查询不到数据继而产生空指针异常!
  测试方法:
  1.删除原有HIBERNATE_SEQUENCE
  2.重新创建HIBERNATE_SEQUENCE
   CREATE SEQUENCE HIBERNATE_SEQUENCE
  INCREMENT BY 1
  START WITH 999999999999999999
  NOMAXVALUE
  NOCYCLE
  CACHE 20;
  在创建的初始值为18位9的前提下,数据可插入上千条没有问题;
  3.再次重新创建HIBERNATE_SEQUENCE
   CREATE SEQUENCE HIBERNATE_SEQUENCE
  INCREMENT BY 1
  START WITH 9999999999999999999
  NOMAXVALUE
  NOCYCLE
  CACHE 20;
  在创建的初始值为19位,只要超过18位就无法插入数据,报:数字溢出错误,异常信息如下:
   at java.lang.Thread.run(Thread.java:662) Caused by:
  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could
  not get next sequence value; uncategorized SQLException for SQL [select
  hibernate_sequence.nextval from dual]; SQL state [99999]; error code [17026];
  数字溢出; nested exception is java.sql.SQLException: 数字溢出 at
  org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
  at
  org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
  at
  org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
  at
  org.springframework.orm.hibernate3.HibernateAccessor.convertJdbcAccessException(HibernateAccessor.java:424)
  at
  org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:407)
  创建的SEQUENCE最大值为ORACLE的默认值,ORACLE数据库保存的最大值为 28位数,均为9 。
  问题:
  1.ORACLE默认最大SEQUENCE值为28位9,但在19位9的情况下就无法插入数据,报数字溢出;
  2.我们数据库中数值过大时都保存的是科学计数法;
  3.所有涉及业务表中的ID都是科学计数法;
  4.创建脚本中的SEQUENCE创建语句是否合理?
  1.我们都限制了最大值;
  2.有的初始值都不是从1开始的(如:HIBERNATE_SEQUENCE );
  3.是否考虑循环;
  测试案例:
  1.创建SEQUENCE,设置最大值(nomaxvalue);
  2.创建SEQUENCE,设置最小值(nominvalue);
  3.创建SEQUENCE,不设置最大值(nomaxvalue);
  4.创建SEQUENCE,不设置最小值(nominvalue);
  5.创建SEQUENCE,设置最大值、设置最小值;
  6.创建SEQUENCE,不设置最大值、不设置最小值;
  7.创建SEQUENCE,设置序列不重复(nocycle);
  8.创建SEQUENCE,设置序列重复(cycle);
  9.创建SEQUENCE,设置序列每次增长1(increment by 1);
  10.创建SEQUENCE,设置序列每次增长任意值;
  11.创建SEQUENCE,设置序列初始值是1(start with 1);
  12.创建SEQUENCE,设置序列初始值为任意值;
  13.创建SEQUENCE,设置创建的初始值为INTEGER数据类型的上限(2147483648);
  14.创建SEQUENCE,设置创建的初始值大于INTEGER数据类型的上限(2147483648);
  15.创建SEQUENCE,设置创建的初始值为LONG数据类型的上限(28位9);
  16.创建SEQUENCE,设置创建的初始值大于LONG数据类型的上限(28位9);
  17.检查已创建SEQUENCE是否限制了最大值;
  18.检查已创建SEQUENCE是否初始值都是从1开始的;
  19.检查已创建SEQUENCE是否考虑循环;
  20.检查所有实体类和JAVA BEAN中的主键和外键是否为Long类型;
  21.检查是否存在Long转换成INTEGER或Int,大转小会造成数据错误;
  22.检查JSP页面单选或多选传回ACTION的ID或IDS为字符串类型,字符串转换成Long类型的正确方式之一为Long.valueof(ids),而不能把字符串先转换成Int再转成Long;
  23.检查局域变量中ID属性的类型不能为int,比如客户表的ID,在代码中经常出现CustInfo custInfo = xxxService.findCustIdByID(int custId) 或者int custId = xxx.getCustId()。这种类型只能通过关键字 Integer 和 int 来筛选;
  24.修改了实体类和JAVA BEAN的主键或外键类型,所有引用了该对象该字段的文件都需要重新编译后发布,否则会报对象属性类型不匹配。
  系统使用过程中,并且正在做交易的过程中,突然出现系统崩溃,而又不能在分分钟解决此问题,对于客户来说损失较大,对于用户来说不能容忍。现将实际项目中出现的问题分享出来,希对君有益!

     版权声明:本文出自51Testing会员投稿,51Testing软件测试网及相关内容提供者拥有内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号