Express.js와 MongoDB를 이용하여 작성했던 게시판 프로젝트가 있다. 헤로쿠가 무료 플랜을 중단하면서 서버가 내려갔었는데, 친구들의 요청이 있기도 했고 NestJS와 MySQL + kysely를 손에 익힐 겸 다시 재작성하고 있다.
프로젝트를 살리는 김에 이전 글들을 볼 수 있으면 좋을 것 같다는 생각이 들었다.
그러니 알아보자. MongoDB의 데이터를 MySQL로 이전하는 방법
MongoDB에서 데이터 추출
mongoexport
명령어를 이용하면 저장된 데이터를 csv
형식이나 json
형식의 파일로 가져올 수 있다. (참고: MongoDB Documentation)
나는 uri를 이용한 방법으로 진행했다. 인스턴스의 uri와 액세스 권한이 있는 유저의 이름과 비밀번호를 확인하여 아래 명령어를 입력한다.
mongoexport --uri mongodb+srv://<유저명>:<비밀번호>@<호스트> --type csv -c <컬렉션명> -f <콤마로구분한필드명> -o <파일명.csv>
이렇게 하면 해당 컬렉션의 데이터를 csv 파일 형태로 가져올 수 있다.
MySQL에 csv 파일 덤프
LOAD DATA INFILE
명령어를 이용하여 csv 파일을 import해보자. (참고: MySQL LOAD DATA Statement)
파일을 가져올 수 있는 위치는 기본적으로 제한되어 있다. secure_file_priv
옵션을 확인해보자.
show variables like "secure_file_priv";
import할 파일이 해당 위치에 있어야 한다는 뜻이다. 현재 저 DB는 도커에서 돌아가고 있기 때문에 로컬 위치를 의미하지 않는다. 로컬 파일을 이용하여 데이터를 가져올 수도 있지만 기본적으로 local_infile
옵션은 off로 설정되어 있기 때문에 해당 옵션을 변경하기 보다는 csv 파일을 도커로 전송하여 사용해보도록 하자. (local_infile
옵션을 true로 설정한 후 LOAD DATA LOCAL INFILE
명령어를 이용하면 로컬 파일 사용 가능)
로컬 파일을 도커로 전송하려면 docker cp
명령어를 이용하면 된다.
docker cp [파일위치] [컨테이너 이름]:/var/lib/mysql-files
이렇게 하면 csv 파일이 도커로 전송된 것을 확인할 수 있다.
이제 전송한 파일을 이용하여 데이터를 입력해 보자.
LOAD DATA INFILE '/var/lib/mysql-files/post.v1.csv'
INTO TABLE post
FIELDS
terminated by ',' -- csv 구분자
optionally ENCLOSED by '"'
ignore 1 lines -- csv 파일 헤더 무시
(@title, content, name, file_url, @views, @date_time) -- @로 지정하면 변수로 받음
SET
created_at = STR_TO_DATE(@date_time, '%Y-%m-%dT%H:%i:%s.%fZ'),
views = 0, -- 해당 csv 파일엔 조회수가 존재하지 않아서 기본값 설정
uid = null,
title = LEFT(@title,100); -- mongodb에 저장된 글 중 제목 길이가 100글자 이상인 글 처리
데이터가 post
테이블에 잘 입력된 것을 확인할 수 있다.