본문 바로가기
IT/DB

MySQL Duplicate entry 1062 오류 해결: 어떤 인덱스가 막는지 찾는 순서 (MySQL 8.4, 2026년 9월 14일 확인)

by 바른정보블로그 2026. 9. 14.

MySQL 1062 Duplicate entry 오류 원인과 해결 순서 안내 대표 이미지

잘 돌던 INSERT가 갑자기 ERROR 1062 (23000): Duplicate entry '...' for key '...'를 뱉으면 당황스럽습니다. 급한 마음에 INSERT IGNORE를 붙였다가 데이터가 조용히 사라지기도 하죠. 이 글은 MySQL 8.4 LTS 공식 매뉴얼에서 확인한 내용만으로 어떤 인덱스가 막고 있는지 찾는 순서와 각 해결책의 부작용을 정리했습니다. 2026년 9월 14일 기준입니다.

3줄 빠른 결론

  • 1062는 PRIMARY KEY 또는 UNIQUE 인덱스 위반이며, 메시지 뒤의 키 이름이 범인입니다.
  • SHOW CREATE TABLESHOW INDEX FROM 테이블그 인덱스의 컬럼 구성부터 확인하세요.
  • INSERT IGNORE는 행을 버리고, REPLACE는 기존 행을 삭제 후 삽입합니다. 의도한 동작인지 꼭 구분하세요.

오류 메시지 정확히 읽기

번호 심볼 SQLSTATE 의미
1062 ER_DUP_ENTRY 23000 데이터 값이 중복
1586 ER_DUP_ENTRY_WITH_KEY_NAME 23000 같은 상황, 키 이름 표시형
1061 ER_DUP_KEYNAME 42000 인덱스 이름이 중복(데이터 아님)

공식 레퍼런스는 "1062의 메시지는 ER_DUP_ENTRY_WITH_KEY_NAME의 형식 문자열을 사용한다"고 적고 있어 실제로는 키 이름이 문자열로 보입니다. 8.4 매뉴얼 예시입니다.

mysql> CREATE TABLE t (i INT NOT NULL PRIMARY KEY);
mysql> INSERT INTO t (i) VALUES(1),(1);
ERROR 1062 (23000): Duplicate entry '1' for key 't.PRIMARY'

테이블명.인덱스명 형태이며 PRIMARY는 기본키입니다. 이 표기의 도입 시점은 릴리스 노트에서 확인하지 못해 8.4 매뉴얼 예시 기준으로만 봐 주세요.

원인 찾는 순서

  1. 키 이름 확보 - 오류 메시지의 for key 뒤 이름을 그대로 복사합니다.
  2. 테이블 정의 확인 - SHOW CREATE TABLE 테이블명;으로 PRIMARY KEY·UNIQUE 정의와 끝줄의 COLLATE 값을 봅니다.
  3. 인덱스 컬럼 확인 - SHOW INDEX FROM 테이블명;에서 해당 Key_name 행의 Non_unique가 0인지, Seq_in_index복합 인덱스 컬럼 순서를 확인합니다. 공식 ALTER TABLE 문서도 인덱스 이름은 이 명령으로 알아내라고 안내합니다.
  4. 실제 중복 행 찾기
    SELECT 컬럼, COUNT(*) FROM 테이블
    GROUP BY 컬럼 HAVING COUNT(*) > 1;
    매뉴얼이 레시피로 안내하진 않고 문서화된 기능을 조합한 표준 기법입니다.
  5. 콜레이션 확인 - 기본값 utf8mb4_0900_ai_ci악센트·대소문자 무시Appleapple이 중복으로 잡힙니다. 구분하려면 utf8mb4_0900_as_csutf8mb4_bin으로 선언해야 합니다.

해결책 3가지와 문서화된 부작용

방법 동작 알아야 할 점
INSERT IGNORE 중복 행을 버리고 경고로 강등 1062뿐 아니라 NULL 위반·외래키 참조 오류도 함께 무시됨. 잘못된 값이 "가장 가까운 값"으로 보정될 수 있음
INSERT ... ON DUPLICATE KEY UPDATE 충돌 시 기존 행을 UPDATE 영향 행 수가 삽입 1 / 갱신 2 / 값 동일 0. 유니크 인덱스가 여러 개면 "사용을 피하라"고 매뉴얼이 권고
REPLACE 기존 행 DELETE 후 INSERT 명시하지 않은 컬럼은 기본값으로 초기화. INSERT와 DELETE 권한 모두 필요. 반환 카운트가 1보다 크면 삭제가 일어난 것

INSERT IGNORE로 넘어간 행은 직후 SHOW WARNINGS;로 확인하세요. REPLACE는 PRIMARY KEY나 UNIQUE 인덱스가 있을 때만 의미가 있습니다.

자주 놓치는 원인 3가지

  1. NULL은 중복으로 안 잡힙니다. 공식 문서는 "UNIQUE 인덱스는 NULL 허용 컬럼에 여러 개의 NULL을 허용한다"고 명시합니다.
  2. AUTO_INCREMENT에 값을 직접 섞어 넣을 때입니다. 매뉴얼은 최근 시퀀스가 100일 때 (1,'a'), (NULL,'b'), (101,'c')를 넣으면 NULL 행에 101이 배정돼 (101,'c')가 실패한다고 예시를 듭니다.
  3. "재시작하면 카운터가 초기화된다"는 옛말입니다. InnoDB는 최대값을 저장해 재시작 후에도 유지하며, 비정상 종료 시에만 이전 값이 재사용될 수 있습니다.

주의사항

  • InnoDB 같은 트랜잭션 엔진은 제약 위반 시 해당 문장을 자동 롤백합니다. 비트랜잭션 엔진은 오류 행에서 멈추고 나머지를 처리하지 않습니다.
  • ON DUPLICATE KEY UPDATEIGNORE를 함께 쓰면 유니크 키가 여러 개인 테이블에서 예상과 다르게 동작할 수 있다고 매뉴얼이 경고합니다.
  • REPLACE와 외래키 CASCADE·트리거의 상호작용은 8.4 공식 페이지에서 확인하지 못해 미확인입니다.
  • 기본키가 없으면 InnoDB가 첫 UNIQUE NOT NULL 인덱스를 기본키로 승격합니다.

중복이 이미 있는 테이블에 UNIQUE를 걸어야 한다면

  1. 위 5번 쿼리로 중복 건수를 먼저 셉니다.
  2. MySQL은 UNIQUE 인덱스 생성 시 중복 값이 없는지 검사하고 PRIMARY KEY면 NULL 여부도 검사합니다. 중복이 남아 있으면 실패하며, 이때의 정확한 에러 번호는 매뉴얼에 없어 미확인입니다.
  3. 과거의 ALTER IGNORE TABLE ... ADD UNIQUE는 8.4 문법에 존재하지 않습니다. 중복을 먼저 정리해야 합니다.
  4. 매뉴얼은 기본키를 테이블 생성 시 정의하는 것이 최선이라고 권고합니다.

자주 묻는 질문

Q1. 1062와 1061은 뭐가 다른가요?
1062는 데이터 값 중복, 1061(SQLSTATE 42000)은 인덱스 이름 중복입니다. 마이그레이션 스크립트를 두 번 돌렸을 때 자주 뜹니다.

Q2. 영향 행 수가 2로 나오는데 정상인가요?
정상입니다. ON DUPLICATE KEY UPDATE는 삽입 1, 갱신 2, 값이 같으면 0을 반환합니다.

Q3. 대소문자만 다른 값인데 왜 중복인가요?
MySQL 8.x 기본 콜레이션 utf8mb4_0900_ai_ci가 대소문자를 구분하지 않기 때문입니다. 참고로 utf8mb4_0900_bin은 NO PAD라 'a''a '를 다른 값으로 봅니다.

함께 보면 좋은 글

공식 출처

댓글