编辑:查看这个问题的结尾,了解导致错误的原因以及我是如何发现的。
当我运行一个将数据批量插入到 Oracle 数据库中的应用程序时,我从 Hibernate 中抛出了一个非常奇怪的异常。错误来自 Oracle 数据库ORA-00001,它
" 表示已尝试插入具有重复(唯一)键的记录。如果更新现有记录以生成重复(唯一)键,也会生成此错误。
该错误很奇怪,因为我在另一台机器上创建了相同的表(完全相同的定义),如果我通过我的应用程序使用它,我不会得到相同的错误。并且所有数据都被插入到数据库中,所以没有什么被真正拒绝。
两种设置之间必须有一些不同,但我能看到的唯一不同的是我在发布时得到的横幅输出
select * from v$version where banner like 'Oracle%';
给我带来麻烦的数据库:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
有效的数据库:
Oracle Database 10g Release 10.2.0.3.0 - 64bit Production
表定义、输入和我编写的应用程序对两者都是相同的。所涉及的表基本上是一个具有复合 id(serviceid、date、value1、value2)的四列表 - 没什么特别的。
关于什么可能是错的任何想法?我已经开始清理几次,删除两个表以平等地开始,但我仍然从数据库中得到错误。
更多的输出:
Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (STATISTICS.PRIMARY_KEY_CONSTRAINT) violated
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:367)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:8728)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
我如何找出导致问题的原因
感谢 APC 和 ik_zelf,我能够查明这个错误的根本原因。事实证明,Quartz 调度程序被错误地配置为生产数据库(出现错误的地方)。对于针对非故障 oracle 服务器<cronTriggerExpression>0/5 * * * * ?</cronTriggerExpression>
运行的作业,我每五秒运行一次批处理作业。我认为对于另一个 oracle 服务器来说,每分钟一次就足够了,并使用 * */1 * * * ? 设置了石英调度程序。事实证明这是错误的,而不是每分钟运行一次,而是每秒运行一次!
每个作业大约需要 1.5-2 秒,因此两个或多个作业同时运行,从而导致服务器上同时插入。因此,我没有插入 529 个元素,而是插入了 1000 到 2000 个元素。将 crontrigger 表达式更改为与另一个相同的表达式,每五秒运行一次,解决了该问题。
为了找出问题所在,我必须在 hibernate.cfg.xml 中设置 true 并禁用表上的主键约束。
-- To catch exceptions
-- to find the offending rows run the following query
-- SELECT * FROM uptime_statistics, EXCEPTIONS WHERE MY_TABLE.rowid = EXCEPTIONS.row_id;
create table exceptions(row_id rowid,
owner varchar2(30),
table_name varchar2(30),
constraint varchar2(30));
-- This table was set up
CREATE TABLE MY_TABLE
(
LOGDATE DATE NOT NULL,
SERVICEID VARCHAR2(255 CHAR) NOT NULL,
PROP_A NUMBER(10,0),
PROP_B NUMBER(10,0),
CONSTRAINT PK_CONSTRAINT PRIMARY KEY (LOGDATE, SERVICEID)
);
-- Removed the constraint to see what was inserted twice or more
alter table my_table
disable constraint PK_CONSTRAINT;
-- Enable this later on to find rows that offend the constraints
alter table my_table
enable constraint PK_CONSTRAINT
exceptions into exceptions;