异常处理 org.springframework.dao.DataIntegrityViolationException

异常处理 org.springframework.dao.DataIntegrityViolationException_第1张图片

问题描述:

数据仓库: Oracle 11g

后台报错:DataIntegrityViolationException

详细日志:

Caused by: java.lang.ClassNotFoundException: org.springframework.dao.DataIntegrityViolationException
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at org.springframework.util.ClassUtils.forName(ClassUtils.java:257)


原因分析:

1.为什么报错DataIntegrityViolationException

DataIntegrityViolationException 这个异常是数据库插入时违反数据库约束引起 ,例如主键重复、向非空字段插入空值,或者插入字段违反表结构等

例如:

ORA-01438: value larger than specified precision allowed for this column
; nested exception is java.sql.SQLException: ORA-01438: value larger than specified precision allowed for this column

经过核实 OPERATORLOG  表的主键列设置为999999 ,实际数量只有70W+,并没有达到999999 , 主键列ID 是通过Sequence创建,查询Sequence最的最大值 已经到1000002,因此新插入行对象ID会越界造成DataIntegrityViolationException错误,

2. 为什么表行数和Sequence查询很大

OPERATORLOG 这张表是日志表, 其中会记录一些批量操作的日志, 为了节省效率, 将Sequence 设置了 cache =500, 但是一些异常情况下Spring事务回滚, 但是Sequence 不会回滚 造成 SEQ 值的浪费 因此出现了表行数小于 Sequence数值的情况

3. 为什么巡检没有发现问题

项目使用Oracle数据库,没有做分库分表,而是使用Oracle分区分表技术来解决表过大引起的性能问题

表的数量会持续增加,因此就需要售后人员定期巡检系统,当序列达到一定字段的时候,运行脚本扩容,因此团队要求序列的长度严格和主键长度一致,巡检时查询长度达到N%后对字段做扩容处理

--例如达到70%需要扩容
SELECT * FROM USER_SEQUENCES UC where UC.last_number > UC.max_value * 0.7

从脚本分析看由于序列的最大值没有设置成和主键长度一致造成了巡检时候没有发现问题

 --记录SQL:通过Sequence找到表名和主键名等信息
 --Oracle信息 USER_SEQUENCES 序列信息,USER_TAB_COLUMNS 表字段信息,USER_CONSTRAINTS 约束信息
 --A:需列信息 序列命名要求SEQ_表名,所以使用了SUBSTR函数
 --B:主键列:约束类型是P主键约束并且,POWER实现N次方计算
 SELECT *
   FROM (SELECT Q.SEQUENCE_NAME, Q.MAX_VALUE, Q.LAST_NUMBER, T.TABLE_NAME
           FROM USER_SEQUENCES Q, USER_TABLES T
          WHERE T.TABLE_NAME = SUBSTR(Q.SEQUENCE_NAME, 5)) A, 
        (SELECT C.TABLE_NAME,
                CC.COLUMN_NAME,
                TC.DATA_PRECISION,
                POWER(10, TC.DATA_PRECISION) - 1 MAX
           FROM USER_CONSTRAINTS  C,
                USER_CONS_COLUMNS CC,
                USER_TAB_COLUMNS  TC
          WHERE CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME
            AND C.CONSTRAINT_TYPE = 'P'
            AND TC.COLUMN_NAME = CC.COLUMN_NAME
            AND TC.TABLE_NAME = C.TABLE_NAME) B
  WHERE A.TABLE_NAME = B.TABLE_NAME
    AND A.LAST_NUMBER > A.MAX_VALUE * 0.7


解决方案:

修改增加操作日志表OPERATORLOG主键的值,实现扩容

alter table OPERATORLOG  modify OPERATORLOG_PK  NUMBER(10);


概念整理:

1. 表空间和表分区

  • 表空间:是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间。
  • 分区表:当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。

2. 表分区作用

       Oracle的表分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还可以极大简化常见的管理任务,分区是构建千兆字节数据系统或超高可用性系统的关键工具。

       分区功能能够将表、索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区。每个分区有自己的名称,还可以选择自己的存储特性。从数据库管理员的角度来看,一个分区后的对象具有多个段,这些段既可进行集体管理,也可单独管理,这就使数据库管理员在管理分区后的对象时有相当大的灵活性。但是,从应用程序的角度来看,分区后的表与非分区表完全相同,使用 SQL DML 命令访问分区后的表时,无需任何修改

3. 表分区的优缺点

优点:

  • 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
  • 增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
  • 维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
  • 均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。

缺点:

  • 已经存在的表没有方法可以直接转化为分区表。但是有几种方式可以间接完成这个操作

你可能感兴趣的:(数据存储,Java,java,开发语言,后端)