Database/MongoDB 2020. 8. 16. 22:26

 

이번에 다루어볼 내용은 몽고디비에서 데이터를 백업하고 복구하는 방법이다.

 

백업하기(덤프, dump)

몽고디비가 설치되어 있다면, mongodump라는 명령어로 몽고디비 데이터를 백업할 수 있다.

 

> mongodump --host 127.0.0.1 --port 27017

 

위 명령으로 데이터를 백업한다면, 현재 디렉토리에 /dump 디렉토리가 생기고 이 디렉토리 밑에 데이터가 복구되어 있다.(DB 별로 폴더가 생겨있고, 그 폴더안에 BSON으로 데이터가 백업되어 있다.)

 

> mongodump --out ~/mongo_backup --host 127.0.0.1 --port 27017

 

--out 옵션으로 데이터 백업의 디렉토리 위치를 정해줄 수 있다.

 

> mongodump --out <dump data path> --host 127.0.0.1 --port 27017 -u <username> -p <password> 

 

username/password로 인증이 필요하다면, 위 명령어로 백업이 가능하다.

 

> mongodump --out <dump data path> --host 127.0.0.1 --port 27017 -u <username> -p <password> --db <덤프할 db명>

 

만약 몽고디비에서 특정 데이터베이스만 백업하고 싶다면, 위처럼 --db 옵션을 이용하면 된다.

 

> mongodump --out <dump data path> --host <dbhost> --port 27017 -u <username> -p <password> --db <dbname> --collection <collectionName>

 

특정 컬렉션 단위까지 세분화하여 백업하려면 --collection 옵션을 이용한다. 만약 mongodump&mongorestore에서 "error connecting to db server: server returned error on SASL authentication step:Authentication failed" 에러가 났다면, 아래와 같이 옵션하나를 넣어준다.

 

--authenticationDatabase admin

 

복구하기(restore)

다음은 위에서 덤프한 데이터를 복구하는 방법이다. 복구는 mongorestore라는 명령어를 이용한다.

 

> mongorestore --host 127.0.0.1 --port 27017 \
-u <username> -p <password> --drop <drop db name> \
--db <복구할 db name> <복구할 덤프데이터가 있는 디렉토리>

 

--drop 옵션은 복구전에 드랍시킬 데이터베이스 명을 입력하면 된다.(복구 전 원래 데이터베이스를 드랍시키고 백업 데이터로 새로 복구하는 것이다.) 위 명령을 간단하게 작성해보면 아래와 같다.

 

> mongorestore --host 127.0.0.1 --port 27017 --db local /mongo_backup/local

 

특정 데이터베이스를 복구하고 싶다면, 덤프 데이터가 있는 디렉토리에서 특정 데이터베이스의 디렉토리를 명시해야한다. 만약 모든 데이터를 전부다 백업하고 싶다면 아래 명령어를 입력한다.

 

> mongorestore --host 127.0.0.1 --port 27017 <dump data가 있는 디렉토리>

 

컬렉션 단위로 리스토어하기 위해서는 --collection 옵션을 사용하며, collectionName.bson까지 백업데이터 경로를 명시해주어야한다.

 

> mongorestore --host <dbhost> --port 27017 --db <dbname> --collection <collectionName> <data-dump-path/dbname/collection.bson> --drop
ex)
> mongorestore --port 27017 --db test2 --collection rest2 /mydata/restoredata/test/restaurants.bson --drop

 

여기까지 간단하게 몽고디비 데이터 백업 및 복구에 대해 다루어보았다.

posted by 여성게
:
Web/Spring 2020. 2. 3. 21:54

 

기본적으로 MongoDB는 ObjectId라는 유니크한 primary id를 갖는다. 하지만 @Id 어노테이션을 특정 Class로 매핑시키기 위한 방법은 없을까? 예를 들어 아래와 같은 상황이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Document
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DocumentData {
 
    @Id
    private CustomId id;
    private String value;
 
    @Data
    @AllArgsConstructor(staticName = "of")
    @NoArgsConstructor
    public static class CustomId implements Serializable {
        private String idPrefix;
        private String idDelemeter;
    }
}
cs

 

DocumentData라는 Collection이 있고, 해당 Collection에는 ObjectId 타입이 아닌 CustomId 오브젝트 타입의 Id를 넣고 싶은 것이고, 실제로 Id는 내부적으로 String 타입이며 idPrefix + idDelemeter 라는 스트링으로 매핑하고 싶다. 즉, CustomId("prefix", "!"); 로 생성된 오브젝트가 있고 이것이 실제로 Mongodb에 들어가면 _id : "prefix!" 인 형태로 저장이 하고 싶은 것이다. 이럴때는 어떻게 해야할까?

 

1
2
3
4
5
6
7
8
9
10
11
    @Bean
    public MongoCustomConversions customConversions() {
        return new MongoCustomConversions(Collections.singletonList(new CustomIdConverter()));
    }
 
    public static class CustomIdConverter implements Converter<DocumentData.CustomId, String> {
        @Override
        public String convert(DocumentData.CustomId source) {
            return source.getIdPrefix() + source.getIdDelemeter();
        }
    }
cs

 

위와 같이 MongoCustomConversions를 Bean으로 등록하면 특정 오브젝트 타입이 @Id로 Mapping 되어 있을 때, 구현한 Converter 내용에 따라 적절히 _id 값이 들어가게 된다. 위의 구현은 CustomId 오브젝트 타입이 @Id로 매핑되어 있을 때, idPrefix와 IdDelemeter를 조합하여 String Type의 _id 값을 만들어 낸다. 그리고 기존의 ObjectId로 매핑한 @Id도 그대로 사용가능하다.

 

1
2
3
4
5
6
7
8
public interface MongoRepositoryImpl extends ReactiveMongoRepository<DocumentData, DocumentData.CustomId> {}
 
@PostMapping("/mongo")
public Mono<DocumentData> save(){
    DocumentData data = new DocumentData(DocumentData.CustomId.of("prefix","!"), "value");
    mongoRepository.save(data);
    return mongoRepository.save(data);
}
cs

 

실제로 간단히 API를 만들어 요청을 보내보면 아래와 같이 데이터가 삽입되어 있다.

 

1
2
3
_id : "prefix!"
value : "value"
_class : "com.webflux.mongoexam.DocumentData"
cs

 

실제 필자도 내부적으로 자체적인 복잡한 ID 체계를 가져가기 위해 MongoCustomConversions를 빈으로 등록하여 사용하고 있다.

 

추가적으로 하나더 이슈가 있다. 만약에 특정 커스텀 클래스를 @Id class로 사용하려면 해당 클래스가 반드시 Serializable을 구현하는 클래스이어야한다! 이 이슈를 발견하게 된 것은 ReactiveMongoRepository의 findById를 사용할때 였다. 아이디클래스가 Serializable을 구현하지 않으면 예외를 내뱉는다.

 

 

{
    logEvent: "java.lang.ClassCastException",
    errorMsg: "class xxx cannot be cast to class java.io.Serializable (xxx is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @2c4eab42; java.io.Serializable is in module java.base of loader 'bootstrap')"
}

 

posted by 여성게
: