Post

MERGE INTO(UPSERT) 에서도 PK violation이 발생할 수 있다.

상황

  • 요구사항 1) tbl에 없는 경우 INSERT. 있다면 에러 없이 스킵 처리
  • 요구사항 2) 동시에 여러 스레드에서 쿼리 실행해야 함
1
2
3
4
5
6
MERGE INTO tbl
   USING dual
   ON (pk1 = '1')
   WHEN NOT MATCHED THEN
   INSERT (pk1) VALUES ('1')

1
2
3
4
; SQL []; ORA-00001: 무결성 제약 조건(TBL.IPK\_PK1)에 위배됩니다
   ; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: 무결성 제약 조건(TBL.IPK\_PK1)에 위배됩니다

  • tbl에 없는 경우 INSERT임에도, PK violation이 발생했음.
    • (만약 constraint가 없었다면 같은 pk1=1 이 중복해서 저장되었을 것임)
  • ThreadPool count 1로 주고 실행하면 dup key 에러 없이 실행됨.

원인 : race condition

이러한 속성 때문에 MERGE INTO를 tbl에 없는 경우 INSERT, 있다면 에러 없이 스킵 처리에 사용하는 것은 적절하지 않을 수 있다.

해결방안

  • 앱단에서 ORA-00001 catch 해서 dupkey 무시
  • BEGIN… EXCEPTION… END; 구문 사용해서 쿼리 단에서 dupkey 무시
  • ignore_row_on_dupkey_index 힌트 사용해서 dupkey 무시
    • 이 힌트는 특정한 경우 오라클 11g <> 19c 동작이 다르기 때문에 주의

비슷한 이슈

This post is licensed under CC BY 4.0 by the author.