이번 포스팅은 네이버 클라우드(NKS)에서 구글 클라우드(GCP)로 마이그레이션을 하며 MySQL dump를 수행했을 때 일어났던 문제를 다룹니다.
문제 상황
MySQL 덤프한 파일로 import 수행 시 아래와 같이 `ERROR 1062 (23000)` 에러가 발생했는데요,
ERROR 1062 (23000) at line 347: Duplicate entry '\xEF\xBF\xBB\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF' for key 'letter.PRIMARY'
command terminated with exit code 1
PK에 중복된 값이 있어서 실패했음을 알 수 있습니다.
원인
PK 필드를 UUID로 사용했는데, 타입을 BINARY(16)로 사용했습니다.
그래서 덤프 수행 시 `\xEF\xBF\xBB`같은 이진 데이터(유니코드)가 `replacement character (�)`로 대체된 문제입니다.
해결 방법은 덤프 명령어의 인수로 `--hex-blob`을 추가하는 것입니다.
- `--hex-blob`: 이진 데이터(`BINARY(16)`) 필드를 16진수(`HEX()`) 문자열로 변환합니다.
해결
MySQL dump
MySQL에서 dump 명령어는 아래와 같습니다.
kubectl exec -it [MySQL Pod] -- mysqldump -u root -p[패스워드] --hex-blob [데이터베이스] > [파일_이름].sql
예시 코드
kubectl exec -it mysql-deployment-55bc667810-n42t8 -- \
mysqldump -u root -psecretpassword --default-character-set=utf8mb4 --hex-blob --single-transaction --skip-lock-tables mydb > 20250228_161714.sql
여기서 추가로 사용된 인수는 다음과 같습니다.
- --default-character-set=utf8mb4: 덤프할 때 문자열 인코딩을 `utf8mb4`로 지정합니다.
- --single-transaction: 덤프할 때 트랜잭션을 사용합니다. InnoDB 스토리지 엔진을 사용한다면 글로벌 락 없이 덤프할 수 있습니다.
- 그래서 덤프 중에 테이블이 변경되도 덤프 시작 시점의 데이터를 MVCC로 읽어 스냅샷 형태로 백업합니다.
- 주의할 점으로는 DDL(ALTER TABLE) 같은 테이블 구조를 변경하는 명령어가 백업 중간에 실행되면 백업할 때 반영되지 않습니다.
- --skip-lock-tables: MyISAM 같은 엔진을 사용할 때 잠금없이 덤프할 수 있도록 합니다. InnoDB만 사용하면 사용하지 않아도 됩니다.
- MyISAM을 사용하면 `FLUSH TABLES WITH READ LOCK;`이 실행되서 불필요한 락이 걸릴 수 있습니다.
- 해당 인수를 사용하면 잠금을 건너뛰고 수행할 수 있습니다.
주의할 점
`mysqldump` 명령어로 덤프하면, 기본적으로 모든 데이터를 읽어 메모리에 올린 후, 한 번에 파일로 저장합니다.
큰 테이블을 덤프할 때 메모리를 많이 사용할 수 있기 때문에, 운영 환경에서 사용할 때 주의해서 사용해야 하는데요,
이때 사용할 수 있는 옵션은 `--quick`이 있습니다.
- `--quick`: 한 번에 한 행씩 읽어 바로 파일로 출력합니다. 메모리에 올리지 않기 때문에 대용량 테이블을 빠르게 덤프할 수 있습니다.
MySQL import
덤프한 파일을 적용하려면 아래 명령어를 입력합니다.
kubectl exec -it [MySQL Pod] -- mysql -u [계정] -p[비밀번호] --default-character-set=utf8mb4 [데이터베이스] < [파일_이름].sql
여기서도 마찬가지로 인코딩 인수를 추가했습니다. (--default-character-set=utf8mb4)
예시 코드
kubectl exec -it mysql-deployment-55bc667810-wttz8 -- mysql -u root -psecretpassword --default-character-set=utf8mb4 mydb < 20250228_161714.sql
정리하며
MySQL을 백업할 때 자주 사용하는 명령어인데, 수동으로 백업을 자주하지 않다보니 덤프할 때마다 구글링해서 사용했습니다.
매번 구글링하며 아무 게시글에서 명령어를 참조해 쓰다보니 UUID 필드를 덤프할 때 발생했던 문제를 다시 맞딱뜨리는 실수를 했었는데요,
이번 기회에 다시 정리하면서 같은 실수를 반복하지 않으려합니다.
저와 같은 문제로 어려움을 겪으신 분들이 이 글로 도움을 받았으면 좋겠습니다.
읽어주셔서 감사합니다.
참고
- 덤프 명령어에 사용되는 인수 정리글: https://hahagogo.tistory.com/277
'Kubernetes' 카테고리의 다른 글
쿠버네티스에서 트래픽 유실 없는 무중단 배포 적용하기 (0) | 2025.01.06 |
---|---|
ncloud NKS에서 Nginx Ingress Controller 설치부터 HTTPS 적용하기 (0) | 2025.01.03 |
ncloud NKS로 쿠버네티스 클러스터 구성하기 (0) | 2025.01.01 |
[k8s] 쿠버네티스 핵심 개념 (0) | 2024.09.11 |
[k8s] 쿠버네티스 시작하기 (0) | 2024.09.11 |