編集:エラーの原因と私がどのように見つけたかについては、この質問の最後を見てください。
Oracleデータベースにデータをバッチ挿入するアプリを実行すると、Hibernateから非常に奇妙な例外がスローされます。エラーは、OracleデータベースORA-00001から発生します。
「重複(一意)キーを持つレコードを挿入しようとしたことを意味します。このエラーは、既存のレコードが重複(一意)キーを生成するように更新された場合にも生成されます。」
別のマシンで同じテーブル(まったく同じ定義)を作成したため、アプリで同じテーブルを使用しても同じエラーが発生しないため、エラーは奇妙です。また、すべてのデータがデータベースに挿入されるため、実際に拒否されるものはありません。
2つの設定の間で何かが異なる必要がありますが、私が見ることができる唯一の違いは、発行時に取得するバナー出力です。
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)を持つ4列のテーブルです。
何が間違っている可能性があるかについてのアイデアはありますか?私は何度かクリーンを開始し、両方のテーブルを削除して同じ理由で開始しましたが、それでもデータベースからエラーが発生します。
出力のいくつか:
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>
5秒ごとにバッチジョブを実行していました。他のOracleサーバーでは1分に1回で十分であると考え、クォーツスケジューラを* * / 1 * * *?で設定しました。これは間違っていることが判明し、毎分実行する代わりに、毎秒実行しました!
各ジョブには約1.5〜2秒かかり、2つ以上のジョブが同時に実行されていたため、サーバーで同時に挿入が発生していました。したがって、529個の要素を挿入する代わりに、1000から2000個の挿入を取得していました。crontrigger式を他の式と同じに変更し、5秒ごとに実行すると、問題が修正されました。
何が悪かったのかを見つけるために、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;