2011-05-16 2 views
3

편집 :이 오류의 원인과 오류의 원인을 찾으십시오.동일 오라클 db 설정 : 그 중 하나만 예외

데이터를 오라클 데이터베이스에 일괄 적으로 삽입하는 앱을 실행할 때 매우 이상한 예외가 발생했습니다. 이 오류는

"시도가 중복 (독특한) 키를 가진 레코드를 삽입 에 적용된 것을 의미 오라클 데이터베이스, 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)가있는 네 개의 열 테이블입니다.

무엇이 잘못 될 수 있는지에 대한 아이디어가 있습니까? 나는 깨끗한 여러 번 시작, 두 테이블을 동등한 근거로 시작 떨어지고,하지만 난 여전히 데이터베이스에서 오류가 발생합니다.

출력의 좀 더

: 나는이 문제를 APC에

감사를 야기하고 ik_zelf 나는이 오류의 근본 원인을 찾아 낼 수 있었다 무엇을 발견하는 방법

. 쿼츠 스케줄러가 프로덕션 데이터베이스 (오류가 발생한 부분)에 대해 잘못 구성되어있는 것으로 나타났습니다. 실패하지 않는 Oracle 서버에 대해 실행중인 작업의 경우 매 5 초마다 배치 작업을 실행 한 <cronTriggerExpression>0/5 * * * * ?</cronTriggerExpression>이있었습니다. 나는 1 분에 한 번 다른 오라클 서버에 충분하다고 생각하고 쿼츠 스케줄러를 * */1 * * *로 설정했습니다. 이것은 잘못된 것으로 밝혀졌으며 매분마다 실행되는 대신 매초마다 실행되었습니다.

각 작업에는 약 1.5-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; 

답변

4

고유 한 복합 제약 조건이 있습니다. ORA-00001은 ServiceID, Date, Value1 및/또는 Value2에 중복 값이있는 두 개 이상의 행이 있음을 의미합니다. 입력 내용이 두 데이터베이스에서 동일하다고 가정합니다. 그래서 하나 : 당신이 당신의 프로그램이 던지는 것을 상상하는

  • ORA-00001
  • 당신은 입력이 모두 실행에 동일한 것으로 착각.

더 많은 설명은 두 번째 것입니다. 키 열 중 하나 이상이 외부 소스 또는 기본값 (예 : 날짜 열의 ServiceId 또는 SYSDATE의 코드 표)에 의해 채워집니다. 실패한 데이터베이스에서이 자동 채우기는 고유 한 값을 제공하지 못합니다. 사용중인 메커니즘에 따라 이것이 가능한 이유는 여러 가지가있을 수 있습니다. 고유 한 복합 키에서 NULL 항목 개수를 기억하십시오. 즉, (NULL, NULL.NULL, NULL) 레코드는 얼마든지 가질 수 있지만 (42, NULL, NULL, NULL) 레코드는 하나만 가질 수 있습니다.

실제 문제가 무엇인지 추측하기가 어렵습니다. (코드 작성자라는 이점이 있지만, 통찰력을 부여해야 함). 필요한 것은 추적 진술입니다. 내 선호하는 솔루션은 Bulk DML Exception Handling을 사용하는 것이지만 그때 나는 PL/SQL 팬입니다. Hibernate는 프로그램에 로깅을 할 수있게 해준다. 코드는 괜찮은 도구가있을 때 디버깅하기가 훨씬 쉽습니다.

마지막 수단으로 배치 삽입을 실행하기 전에 제약 조건을 해제하십시오. 그 후 다음과 같이 다시 활성화 : 중복 행을 가지고 있지만 결정적으로 MY_EXCEPTIONS 테이블이 충돌 모든 행을 나열합니다 경우 실패합니다

alter table t42 
    enable constraint t42_uk 
     exceptions into my_exceptions 
/

. 적어도 복제물의 근원에 대한 단서를 제공 할 것입니다. 예외 테이블이 없다면 $ORACLE_HOME/rdbms/admin/utlexcptn.sql 스크립트를 실행해야합니다 (이 디렉토리에 액세스하려면 DBA가 필요할 수 있습니다).


TL; DR

통찰력 정보가 ​​필요합니다 악기 코드를.

+0

예외에 대한 팁. 그것을 시도하고 나의 발견에 대해보고 할 것입니다. – oligofren

+0

기본 키 제약 조건을 비활성화하고 삽입 작업을 수행 한 다음 다시 활성화하면 두 번 많은 삽입 작업을 수행하고 있음을 알 수있었습니다. 그것은 다른 데이터베이스에서 삽입 작업을 수행 할 때 여전히 오류가 발생했기 때문에 내가 뭘 잘못했는지 알아 내려고 할 때 코드에서 약간의 변경이 있었기 때문에 발생했을 수 있습니다. 그러나 잘못된 것이 무엇인지 알아내는 데 훨씬 더 가깝습니다. . ik_zelf의보고 제약 조건 예외 (Exception Constraint Exceptions)라는 기사는 예외가 던져지는 장소와 어디에서 왔는지 식별하는데도 도움이되었습니다. – oligofren

+0

이중 오류의 원인을 찾아 냈습니다. 그래도 당신에게 대답을 수여. 내 질문을 업데이트하여 오류의 원인을 통합합니다. – oligofren

1

문제가있는 것은 EE이고 다른 하나는 SE 데이터베이스입니다. 첫 번째 하드웨어가 더 빠르다고 기대합니다. 이 경우 SYSDATE를 사용하여 날짜 열을 채우면 시간 해상도가 충분하지 않을 수 있습니다. 중복되는 날짜 값을 가져옵니다. 데이터의 다른 열도 고유하지 않은 경우 ORA-00001이 표시됩니다.

길게 보였지만 첫눈에이 방향을 들여다 보았습니다.

예외 테이블을 사용하여 데이터를 식별 할 수 있습니까? Reporting Constraint Exceptions

+0

예외에 대한 유용한 팁. Sysdate는 데드 엔드입니다. 데드 타임은 클라이언트 측의 날짜이며, 날짜는 datetime이 아닙니다. – oligofren

1

내 생각에는 서비스 ID가 될 것입니다. hibernate가 '신선한'삽입을 위해 사용하는 service_id가 이미 사용되었습니다.

은 아마도 테이블 내가 비록 걸거야 다른

에서 하나의 데이터베이스에서 비어 있지만 인구 인 SERVICE_ID 시퀀스를 생성하고 일련 번호 데이터의 콘텐츠와 동기화이다. 테이블에서 1000 행을 동일하게 사용하면 하나의 데이터베이스에있는 숫자가 다른 테이블보다 작습니다.

SELECT service_id_seq.nextval FROM DUAL 

시퀀스가 생성 된 곳 (예 : 소스 제어가없는 곳)에서 데이터를 다른 데이터베이스의 테이블로 가져온 위치를 많이 봅니다.

+0

모든 값은 어플리케이션에 의해 삽입됩니다. 아무 것도 자동 생성되지 않습니다. 서비스 ID는 단지 문자열이며 날짜에는 시간 부분이 없습니다. – oligofren