[MongoDB] TTL index의 expire time

by 스뎅(thDeng) on

TTL Index

MongoDB에는 document를 collection에 넣고 특정 시간이 지나면 삭제하는 TTL index가 있다.

삭제 방식이 독특하기 때문에 이 점을 염두에 두고 적용해야 한다.

백그라운드 삭제 스레드

mongod의 백그라운드 스레드가 삭제할 docuemnt를 찾아서 삭제한다. 백그라운드 스레드가 실행되면 db.currentOp()명령이나 database profiler를 통해서 삭제 명령이 실행되는 것을 확인할 수 있다.

단점은 백그라운드 스레드가 delete 커맨드를 마구 날려서 삭제하기 때문에 부하가 발생할 수 있다는 점이 있다.

Atlas MongoDB를 AWS에서 사용하는 경우 IOPS 제한에 걸릴 수 있다.

삭제 주기

백그라운드 스레드는 60초 마다 실행되기 때문에, expire 시간이 되었다고 해도 즉시 삭제되는 것이 아니라 백그라운드 스레드가 실행되기를 기다려야 한다. 삭제할 데이터가 많다면 삭제를 기다리는 시간도 있어 60초 보다 더 긴 시간이 걸릴 수 있다.

Replica Sets

Document 수정은 Primary만 실행하기 때문에, Secondary node의 백그라운드 삭제 스레드는 실행되지 않고 idle 상태로 있는다. Secondary는 Primary에서 삭제된 정보를 복제 받아 반영한다.

primary

In a replica set, the primary is the member that receives all write operations.

primary - MongoDB Glossary

테스트 1

TTL index를 추가하고 document를 하나 넣는다.

use test;

// 5초 TTL index 설정
db.test.createIndex({
    createdAt: 1
}, {
    name: "IDX_EXPIRE_TEST",
    expireAfterSeconds: 5
});

db.test.insertOne({
    createdAt: new Date(),
    logEvent: 2,
    logMessage: "Success!"
});

현재 시각과 document가 생성된 시각을 함께 찍어본다. 시간이 흐르면 데이터가 삭제되는 것을 확인할 수 있고, 5초가 한참 지나도 데이터가 살아 있는 것을 알 수 있다.

> new Date() + ' ' + db.test.findOne()?.createdAt
'Mon Jan 16 2023 15:02:10 GMT+0900 (Korean Standard Time) Mon Jan 16 2023 15:02:01 GMT+0900 (Korean Standard Time)'
> new Date() + ' ' + db.test.findOne()?.createdAt
'Mon Jan 16 2023 15:02:32 GMT+0900 (Korean Standard Time) undefined'

테스트 2

그렇다면 document를 먼저 넣고 TTL index의 expire time을 변경하면 어떻게 될까?

위에서 5초로 설정되어 있는 것을 180초로 변경해 본다.

db.test.insertOne({
    createdAt: new Date(),
    logEvent: 2,
    logMessage: "Success!"
});

// 5초에서 180초로 변경
db.runCommand({
    collMod: "test",
    index: {
        name: "IDX_EXPIRE_TEST",
        expireAfterSeconds: 180
    }
});

같은 방법으로 언제까지 살아 있는지 확인하면 180초가 넘어야 삭제가 된다.

> new Date() + ' ' + db.test.findOne()?.createdAt
'Mon Jan 16 2023 15:25:10 GMT+0900 (Korean Standard Time) Mon Jan 16 2023 15:22:01 GMT+0900 (Korean Standard Time)'
> new Date() + ' ' + db.test.findOne()?.createdAt
'Mon Jan 16 2023 15:25:11 GMT+0900 (Korean Standard Time) Mon Jan 16 2023 15:22:01 GMT+0900 (Korean Standard Time)'
> new Date() + ' ' + db.test.findOne()?.createdAt
'Mon Jan 16 2023 15:25:12 GMT+0900 (Korean Standard Time) undefined'

결론

참고

별도로 명시하지 않을 경우, 이 블로그의 포스트는 다음 라이선스에 따라 사용할 수 있습니다: Creative Commons License CC Attribution-NonCommercial-ShareAlike 4.0 International License