Last Updated on 3월 24, 2024 by Jade(정현호)
안녕하세요
이번 포스팅에서는 MongoDB 의 스토리지 엔진에 대해서 전반적으로 내용을 살펴보려고 합니다.
포스팅은 Real MongoDB 책 내용을 정리한 것이 주요 내용이며, 추가적으로 MongoDB Document 의 내용이 포함되어 있습니다.
Contents
플러그인 스토리지 엔진
스토리지 엔진 은 사용자의 데이터를 디스크와 메모리에 저장하고 읽어오는 역할을 담당합니다.
아래 이미지는 MongoDB의 아키텍처 와 플러그인 스토리지 엔진 사용에 관한 하여 간략하게 이미지화 한 것입니다.
[Mix and match storage engines]
위의 이미지에서 아래에 위치한 MMAPv1 와 WiredTiger 등을 스토리지 엔진이라고 하며, 이 스토리지 엔진들은 사용자의 데이터를 디스크에 영구적으로 기록하거나 다시 읽어와서 메모리에 에 적재하는 역할을 담당합니다.
이러한 MongoDB의 스토리지 엔진과 같은 구성 또는 아키텍처는 MySQL 서버에서도 동일(유사)하게 다양한 스토리지 엔진을 사용할 수 있도록 스토리지 엔진이 플러그인 형태로 구현되어 있습니다.
다만 MongoDB의 경우 MySQL 서버와 다르게 하나의 인스턴스에서 동시에 여러개의 스토리지 엔진을 사용할 수는 없습니다.
하나의 MongoDB 서버에서 MMAPv1 스토리지 엔진과 WiredTiger 스토리지 엔진을 동시에 사용할 수는 없습니다.
데이터를 저장하거나 조회하면 MongoDB 서버는 그 쿼리를 분석해서 어떻게 처리하면 효율적일지 판단하며, 이런 부분은 옵티마이저(Optimizer) 라고 부르는 컴포넌트가 처리를 담당하게 되며, 옵티마이저의 가장 중요한 역할은 최적화된 실행 계획을 수립하는 것입니다.
이때 디스크에서 데이터를 어떻게 가져오고 어떻게 최적으로 저장할 것인지 결정하는 부분이 스토리지 엔진 영역의 역할입니다.
MongoDB 서버 엔진은 사람의 머리, 두뇌 역할을 한다면, 각 스토리지 엔진은 손과 발의 역할을 맡은 형태입니다.
MongoDB 스토리지 엔진
현재 MongoDB 서버에서는 다음과 같이 다양한 스토리지 엔진을 사용할 수 있습니다.
각 스토리지 엔진이 가진 장단점이 있지만, 일반적으로 사용자들이 실행하는 쿼리나 데이터 변경을 위한 DML 문장들은 스토리지 엔진과는 투명(무관하게)하게 작동한다는 특징이 있습니다.
MMAPv1 스토리지 엔진을 사용하는 서비스를 WiredTiger 스토리지 엔진을 사용하는 MongoDB 서버로 바꾸어도 응용 프로그램은 거의 변경하지 않아도 됩니다.
MongoDB에서 사용 가능한 스토리지 엔진 리스트
• MMAPv1
• WiredTiger
• In-Memory
• RocksDB
• TokuDB
MMAPv1 스토리지는 MongoDB가 출시했을 때 부터 사용되던 스토리지 엔진이고, WiredTiger 스토리지 엔진은 MongoDB 3.0 부터 도입된 스토리지 엔진입니다. 그리고 WiredTiger 스토리지 엔진은 MongoDB 3.2 버전 부터 기본 스토리지 엔진 으로 사용되고 있습니다.
그리고 In-Memory 스토리지 엔진 WiredTiger 스토리지 엔진의 변형으로, 데이터를 디스크에 기록하지 않고 메모리 보관하는 엔진입니다.
RocksDB 스토리지 엔진은 페이스북에서 LevelDB 를 커스터마이징 하여 개선한 스토리지 엔진이며, TokuDB 는 Percona에서 개발중인 스토리지 엔진(인수하였음)입니다.
MMAPv1 스토리지 엔진을 제외한 모든 스토리지 엔진은 도큐먼트 수준의 잠금을 지원하기 때문에 대부분 스토리지 엔진의 동시성 처리가 좋다고 할 수 있습니다. 그리고 MMAPv1 스토리지 엔진을 제외한 대부분의 스토리지 엔진에서 데이터파일이나 인덱스의 압축도 지원하고 있습니다.
다만 암호화 기능 그리고 In-Memory 스토리지 엔진의 기능은 WiredTiger 에서만 지원이 됩니다.
그리고 유일하게 TokuDB 스토리지 엔진에서는 컬렉션의 파티션 기능도 제공하고 있으며, 파티션 기능은 컬렉션을 샤드 서버 별로 분산하는 것을 의미하는 것이 아니라 RDBMS 에서 보통적으로 사용하는 파티션 기능을 의미합니다.
이 파티션 기능에 대해서는 MongoDB에서도 오래된 데이터를 빠르게 삭제하거나 데이터의 접근에 대해서 특정 영역으로 제한할 때는 여전히 파티션 기능이 유용할 수 있습니다.
스토리지 엔진 혼합 사용
하나의 MongoDB 서버에서 동시에 여러 스토리지 엔진은 사용할 수가 없습니다.
WiredTiger 를 디폴트 스토리지 엔진으로 설정해서 MongoDB 서버를 기동했다면 같은 인스턴스에 RocksDB 스토리지 엔진이나 TokuDB 스토리지 엔진을 같이 사용할 수는 없습니다. 하지만 인스턴스가 다르다면 다른 스토리지 엔진을 사용할 수는 있습니다.
예를 들어 하나의 샤드 클러스터에서 1번 샤드는 WiredTiger 스토리지 엔진을 사용, 2번 샤드에서는 RocksDB 스토리지 엔진을 사용을 할수 있으며 무방 합니다.
또한 하나의 레플리카 셋에서 멤버 별로 다른 스토리지 엔진을 사용하는 것도 가능 합니다.
또는 레플리카셋 별로도 다른 스토리지를 사용할 수도 있습니다.
MongoDB의 각 샤드와 레플리카 셋의 멤버들은 OpLog에 의해서 동기화가 됨에 따라 사실상 각 멤버들의 스토리지 엔진에 의존 적이지 않기 때문입니다.
MMAPv1 스토리지 엔진
MMAPv1 스토리지 엔진은 MongoDB 처음에서 부터 사용된 스토리지 엔진으로 MongoDB 3.0 까지 주로 사용되던 스토리지 엔진 입니다.(3.0 버전 부터 WiredTiger 스토리지 엔진이 지원됨, 다만 3.0버전까지는 기본 스토리지는 MMAPv1 임)
MongoDB 2.6까지는 데이터베이스 레벨의 잠금이 사용되었고 MongoDB 3.0 버전부터 Collection 단위의 잠금을 지원하게 됩니다.
그래서 이전 버전에서는 DML 문장의 동시 처리 성능이 좋지 않았으나 MongoDB 3.0 으로 Collection 레벨의 잠금으로 개선됨에 따라서 이전보다는 동시성 수준이 더 좋아졌습니다. 하지만 컬렉션 수준도 여전히 동시성 처리에 많은 성능적인 개선이 필요한 부분입니다.
MMAPv1 스토리지 엔진은 자체적으로 내장된 캐시 기능이 없어서 운영 체제의 캐시를 활용해야 합니다.
(RDB의 Buffer Cache나 InnoDB Buffer Pool 과 같은 내장 캐시가 없음)
이러한 운영 체제의 캐시를 사용하기 때문에 커널에서 제공하는 시스템 콜을 거치게 되게 되며 이 과정에서의 오버헤드가 상대적으로 큰 편이라고 할 수 있습니다. 또한 운영체제의 캐시 기능은 자주 사용되는 페이지의 관리나 더티 페이지(Dirty Page)의 관리가 데이터베이스보다는 안정적이지 않은 편입니다.
MMAPv1 스토리지 엔진 설정
MongoDB 서버의 설정 파일에서 결정하는 옵션 대부분은 성능을 좌우할 만큼 큰 영향력을 가진 파라미터가 없으며 MMAPv1 스토리지 엔진은 내장 공유 캐시가 없기 때문에 리눅스의 페이지 캐시를 사용함으로 더더욱 MongoDB 서버차원에서의 성능과 관련된 옵션상 설정할 부분은 없습니다.
smallFiles 는 MMAPv1 스토리지 엔진에서 컬렉션 단위로 디스크의 사용 공간을 제약하는 옵션이며, 데이터 파일의 초기 크기를 작게 만들고 최대 크기도 512MB 로 제한합니다.
storage.smallFiles 옵션을 사용하지 않는다면 각 파일은 자동으로 증가하는 순번을 확장자로 가지는 생성되며, 최초 파일은 64MB 크기로 생성되고, 두번째 파일은 배수인 128MB 그 다음은 그 배수 생성되며 최대 2GB까지 증가해서 유지하게 됩니다.
storage.smallFiles 를 사용하다면 공간 낭비를 줄일 수는 있지만, 데이터베이스 용량이 커짐에 따라서 파일의 개수도 많아 짐으로 OS 디렉토리내 많은 파일수에 의해서 문제가 될 수 있거나 OS의 File descriptor 제한에 걸릴수도 있습니다.
storage.directoryPerDB 를 true 로 설정하여 기능을 사용하면 디스크의 데이터파일을 데이터베이스 단위로 별도의 디렉토리에 저장할 수 있습니다. 데이터베이스 단위로 서로 다른 디스크 나 다른 파티션에 사용을 할수 있도록 지원하기 위함이며 또는 파일의 관리 편의성을 위해서입니다. 해당 옵션은 MMAPv1 와 WiredTiger 모두에서 사용 가능한 storage 옵션입니다.
운영체제 캐시와 MMAPv1
MMAPv1 스토리지 엔진은 자체적 내장된 캐시 기능이 없으므로 위에서 설명한 내용과 같이 OS의 페이지 캐시에 의존적입니다. 또한 캐시 기능이 없기 때문에 더티 페이지(DML 문장에 의해서 변경된 블록) 를 효율적으로 관리하는 기능이 지원되지 않습니다.
리눅스 OS 의 페이지 캐시도 일반적인 RDBMS 에서 사용하는 캐시 와 유사한 기능을 가지고는 있으나 RDBMS 서버에서 사용되는 캐시에 비해 관리되는 방식이 조금 단순하고 불안정하게 처리되는 경우가 많습니다.
대표적인 케이스가 MongoDB 가 사용하는 페이지 캐시가 갑작스럽게 줄어드는 상황입니다. 그로 인해서 많은 데이터를 다시 디스크에서 읽어 들어야 하고 다시 페이지 캐시에 캐싱이 되는 과정에서 한 번에 많은 디스크 IO가 발생하게 되어 성능 저하가 되는 케이스입니다.
이런 현상은 리눅스 OS 에서 실행 중인 프로그램들이 더 많은 메모리를 필요로 하는 경우에 리눅스 OS가 추가로 여유 메모리를 더 준비하게 되면서 발생하는 케이스로 페이지 캐시가 응용 프로그램의 사용영역으로 전환되는 경우이며, 메모리 공간을 대량으로 여유 공간으로 만들기도 합니다.
그래서 OS의 페이지 캐시에 의존적이기 때문에 그만큼 메모리 관련된 커널 파라미터 설정이 필수적이라는 것을 의미하게 됩니다.
프레그멘테이션
MMAPv1 스토리지 엔진은 도큐먼트가 저장되는 순서대로 데이터 파일에 기록되며 만약 중간에 도큐먼트가 삭제되면 MMAPv1 스토리지 엔진은 도큐먼트 삭제로 인해서 빈공간이 생기게 되면 빈 공간에 정보를 저장해 두었다고 나중에 새로운 도큐먼트가 저장되면 이 빈 공간의 정보를 사용해서 도큐먼트가 저장할 위치를 찾게 됩니다.
문제는 도큐먼트의 크기가 계속 증가하면서 기존의 작은 빈공간에 대해서 다시 사용하지 못하고 계속 빈공간으로 남아있게 된다는 점입니다. 이러한 상황이 반복이 된다면 데이터 파일에서 사용하지 못한 빈공간이 늘어나게 되고 그렇게 된다면 데이터 파일의 크기는 실제 저장된 도큐먼트 크기에 비해 커지게 될 것입니다.
이런 현상을 프레그멘테이션(Fragmentation) 이라고 합니다. 이러한 프레그멘테이션 현상은 주로 가변 필드의 데이터 타입(문자열 이나 바이너리 데이터 타입) 에서 주로 발생되며, 디스크의 공간 낭비가 될 뿐만 아니라 캐시 메모리의 효율도 같이 떨어지게 됩니다.
플레그멘테이션에 대한 확인은 아래와 같이 컬렉션 상태 확인을 통해서 알 수 있습니다.
db.runCommand({collStats : "users"}) or db.users.stats()
명령어를 수행한 컬렉션의 도큐먼트 건수나 전체 저장 공간의 크기 정보를 확인할 수 있습니다.
- size : 컬렉션의 전체 도큐먼트의 크기로 이 값은 도큐먼트에 패딩된 바이트까지 합한 값이며, 인덱스의 크기는 포함하지 않습니다.
- storageSize : 컬렉션을 위해 할당된 데이터 파일의 크기입니다. 여기에는 인덱스의 저장공간은 포함되지 않습니다.
많은 정보 중에 위의 두개의 필드 값의 차이를 통해서 컬렉션과 데이터 파일간의 차이를 확인할 수 있습니다.
프레그멘테이션이 수백GB 정도 된다면 이 컬렉션은 다시 빌드하거나 컴팩션을 하여 공간을 줄이는 것을 고려할 수 있습니다.
컴팩션은 아래와 같이 진행할 수 있습니다.
db.runCommand( {compact : 'users' })
컴팩션을 한다고 해서 실제의 데이터파일의 사이즈가 줄어드는 것은 아닙니다. 파일의 프레그멘테이션을 줄이는 명령어입니다.
그래서 프레그멘테이션한 결과만큼 데이터파일의 실제 물리적인 사이즈가 줄어드는 것이 아닌 파일의 빈 공간이 사용이 가능한 공간이 되는 것입니다.
컴팩션 하는 동안에는 대상 컬렉션이 저장된 데이터베이스의 모든 오퍼레이션이 블록킹(Blocking) 됨에 따라서 그 동안 조회 쿼리와 DML 을 실행할 수가 없습니다.
MMAPv1 스토리지 엔진은 MongoDB 4.0 버전에서 Deprecated 되었으며, 4.2 버전에서는 remove 되었습니다.
그래서 최신 버전에서는 사용이 불가 합니다.
WiredTiger 스토리지 엔진
WiredTiger 스토리지 엔진은 Berkeley DB 개발자들에 의해서 개발된 임베디드 데이터베이스 엔진으로 2014년 12월 MongoDB로 인수되어 지금은(3.2버전 부터) MongoDB의 기본 스토리지 엔진으로 사용되고 있습니다.
MongoDB은 WiredTiger 스토리지 엔진을 도입하기 하기전에는 MMAPv1 스토리지 엔진을 사용하였고 MMAPv1 스토리지 엔진은 동시성의 문제 그리고 캐시 기능 부재 로 인하여 범용적으로 사용하기에는 여러가지 문제점이 있었습니다.
그래서 MongoDB 에서는 WiredTiger 스토리지 엔진을 인수하여 MongoDB의 스토리지 엔진으로 내장하게 되었습니다.
WiredTiger 스토리지 엔진은 내부적인 잠금 경합 최소화(Lock-free algorithm) 을 위해서 "하자드 포인터(Hazzard-Pointer)" 나 "스킵 리스트(Skip-List)" 와 같은 새로운 기술을 채택하고 있습니다. 또한 최신의 RDBMS 가 가지고 있는 MVCC 기능이나 데이터 파일 압축, 암호화 기능을 모두 가지고 있습니다.
그래서 WiredTiger 스토리지 엔진을 내장하면서 상용 RDBMS 가 가지고 있는 고급 기능들을 모두 지원하게 되었습니다.
WiredTiger 설정
MongoDB 에서 Storage 관련해서 설정할 수 있는 내용은 많지 않습니다 MMAPv1 도 그렇고 WiredTiger 도 설정할 수 있는 내역이 많지가 않습니다.
그리고 또한 설정 가능한 파라미터가 성능에 엄청한 차이를 만드는 파라미터 또한 아닙니다.
일반적인 경우에서는 표준 설정(기본값)을 그대로 사용하는 것이 더 충분히 좋을 경우가 있습니다.
파라미터에서 설정할 수 있는 부분으로 크게 두가지 인 storage 섹션과 wiredTiger 섹션이 있습니다.
storage 섹션 과 저널 설정 등은 모든 스토리지 공통된 설정이 되는 내용입니다.
- dbPath : 데이터 파일이 저장할 경로를 설정합니다.
- indexBuildRetry : 인덱스 생성시 비정상적으로 중단된 후 서버가 재시작 시 인덱스 생성을 자동으로 시작할지를 결정합니다.
- directoryPerDB : 서버가 데이터베이스 단위로 디렉토리를 생성할지 아니면 dbPath에 설정된 디렉터리에 모든 데이터파일을 저장할지를 결정합니다.
- journal : MongoDB 서버의 저널 로그의 활성화 여부를 결정하며, false 로 설정시 저널 로그(트랜잭션 로그)가 기록되지 않습니다.
WiredTiger 섹션에서는 아래와 같은 설정 등을 할 수 있으며, engineConfig는 WiredTiger 스토리지 엔진의 전역적 설정이고, collectionConfig 와 indexConfig 는 각각 컬렉션과 인덱스에만 설정되는 옵션들을 명시할 수 있습니다.
- engineConfig.cacheSizeGB : WiredTiger 스토리지 엔진의 공유 캐시가 어느 정도의 메모리를 사용하게 할 것인지 설정으로 기본적으로 메모리의 약 50~60% 정도를 설정하면 됩니다.
- collectionConfig.blockCompressor: WiredTiger 스토리지 엔진의 데이터 파일을 압축할 것인지, 사용하는 알고리즘은 어떤 것을 할 것인지를 결정하게 됩니다.
zlib 와 snappy 압축 알고리즘을 사용할 수 있으며 압축 알고리즘을 사용하지 않으려면 none 으로 설정하면 됩니다.
MongoDB 4.2 버전부터는 zstd(Zstandard) 를 사용할 수 있으며, zstd는 2016년쯤 페이스북에서 개발한 차세대 압축 알고리즘으로 무손실 데이터 압축 형태로 높은 압축률에 비해 압축속도와 해제속도가 준수한 편입니다.
- indexConfig.prefixCompression : wiredTiger 의 인덱스는 기본적으로 데이터 블록(페이지) 단위의 압축은 지원하지 않고 프리픽스 압축을 지원합니다.
해당 파라미터는 프리픽스 압축을 사용할지를 결정하는 파라미터입니다.
WiredTiger 스토리지 저장 방식
WiredTiger 스토리지 엔진은 다음과 같은 3가지 타입의 저장소를 가지고 있습니다.
• 레코드(Row,Record) 스토어
• 컬럼 스토어
• LSM(Long Structured Merge Tree) 스토어
레코드 스토어어는 일반적인 RDBMS 가 사용하는 저장 방식으로, 테이블의 레코드를 한꺼번에 같이 저장하는 방식이며, 일반적인(범용적인) DBMS 저장방식으로 여러 다양한 서비스 패턴에 적절하게 사용할 수 있는 타입이며, B-Tree 알고리즘을 사용합니다.
컬럼 스토어는 대용량 분석(OLAP 또는 Data WareHouse) 용도로 자주 사용되는데, 테이블의 레코드와 상관없이 각 컬럼 단위 또는 컬럼의 그룹 단위로 데이터 파일을 관리하게 됩니다. 컬럼 단위로 데이터 파일이 생성되기 때문에 파일당 사이즈가 작으며 테이블의 전체 데이터를 읽어 들이는 속도가 빨라서 대용량 분석 사용 용도에 적합합니다.
LSM 은 HBase 나 카산드라와 같은 NoSQL 데이터베이스에서 자주 사용하는 저장방식으로, 데이터 읽기 보다는 데이터의 쓰기 능력이 뛰어난 저장 방식입니다. LSM 은 내부적으로 B-TREE 알고리즘을 사용하지 않고 순차 파일 형태로 데이터를 저장합니다.
LSM-Tree 는 레벨이 낮을수록 최신 데이터이며, 레벨이 높을 수록 오래된 데이터 구성됩니다. 보통의 업무나 응용프로그램에서는 최신의 데이터를 주로 사용하기 때문에 레벨이 낮은 최신의 데이터 파일은 메모리 상주 가능성 높으며, 레벨이 높은 오래 된 데이터 파일일 수록 디스크에만 있을 확률이 큽니다.
LSM-Tree 는 조각 파일 단위로 인덱스를 가지지만, 일반적인 RDBMS에서 사용하는 복잡한 형태의 B-Tree 알고리즘을 사용하지는 않습니다.
LSM-Tree 를 도입한 이유는 서비스의 패턴이 다양화되고 패턴이 변경되면서 대용량의 INSERT 를 문제없이 처리할 수 있는 솔루션이 필요해졌기 때문입니다. 이러한 대용량 INSERT 처리에 대한 요건이 커지면서 HBase나 카산드라와 같은 NoSQL DBMS이 도입되기 시작했습니다.
LSM-Tree 는 데이터를 저장(INSERT 위주) 하는데 있어서 기존의 데이터 크기와 관계없이 거의 동일한 수준의 INSERT 성능을 보장하게 됩니다. B-Tree 알고리즘을 사용하는 데이터베이스에서는 레코드가 저장될 때 마다 B-Tree 를 계속 유지해야 하는 비용이 커지고, 갈수록 B-Tree가 커지기 때문에 기존 데이터가 크면 클수록 INSERT 성능에 대한 저장 비용이 더 커지는 구조입니다.
LSM-Tree는 새로운 데이터는 메모리에 저장하고, 메모리에 저장된 데이터가 충분히 커지면 이 데이터만 디스크로 저장하면 됩니다.
다만 LSM-Tree 알고리즘을 사용하는 테이블에서 데이터를 읽어야 할 경우 읽기 성능은 좋지 못하게 됩니다.
LSM-Tree 는 N개의 데이터 조각이 각각의 파일로 관리됩니다. 그래서 데이터 하나를 검색하려면 N개의 데이터 파일을 모두 검색해야만 원하는 데이터를 찾을 수 있다는 단점이 있습니다.
데이터 파일의 개수를 최소화하기 위해서 백그라운드에서 조각화된 데이터 파일들을 병합하는 작업을 계속 해서 실행하게 됩니다.
(다만 이 작업은 매우 많은 디스크 IO 와 CPU 자원을 사용하게 됨)
WiredTiger의 내부 작동 방식
WiredTiger 스토리지 엔진은 트랜잭션을 지원하는 대부분의 RDBMS와 거의 흡사한 내부 구조로 되어 있습니다.
MongoDB 서버가 트랜잭션을 지원하지 않지만, WiredTiger는 트랜잭션을 지원하며 MongoDB 인수되기 전에 InnoDB 스토리지 엔진과 같은 RDBMS 데이터 처리용 스토리지 엔진으로 개발되었습니다.
[그림1]
WiredTiger 스토리지 엔진은 다른 DBMS와 동일하게 B-Tree 구조의 데이터 파일과 서버의 장애시 데이터 복구를 위한 저널 로그(WAL,Write Ahead Log) 기능을 가지고 있습니다.
WiredTiger의 저널 로그는 데이터 디렉터리 하위에 있는 journal 이라는 디렉토리에 저장되며, 다른 RDBMS의 리두 로그 처럼 로테이션 되면서 로그 파일의 로그 슬롯이 재활용되는 방식이 아닌 새로운 파일이 계속 생성되게 되게 됩니다.
체크포인트 시점에서 이전의 저널 로그는 더이상 필요하지 않음으로 이후 시점의 파일만 남기고 이전의 로그 파일은 자동으로 삭제가 합니다.
MMAPv1 스토리지 엔진과 달리 WiredTiger 스토리지 엔진은 내장된 공유 캐시(버퍼 풀)을 가지고 있습니다.
WiredTiger 의 내장된 공유 캐시는 디스크의 인덱스나 데이터 파일을 메모리에 캐시 하여 조회를 빠르게 처리할 뿐만 아니라, 데이터 변경을 모아서 한 번에 디스크로 기록하는 배치 쓰기 기능을 모두 가지고 있습니다.
위의 그림1 에서 점선으로 된 화살표는 데이터 변경으로 발생한 더티 페이지를 디스크로 기록하는 과정을 표현하고 있습니다.
실선으로 된 화살표는 디스크이 데이터 파일이나 인덱스를 공유 캐시로 읽어드리는 과정을 보여주고 있습니다.
사용자가 쿼리를 실행하면 블록 매니저를 통해서 필요한 데이터 블록을 디스크에서 읽어서 공유 캐시에 적재하여 쿼리를 합니다.
사용자가 데이터를 변경하면 스토리지 엔진은 트랜잭션을 시작하고 커서를 이용해서 원하는 도큐먼트 내용을 변경합니다.
도큐먼트의 변경 내용은 먼저 공유 캐시에 적용되는데 WiredTiger 스토리지 엔진은 변경된 데이터가 디스크에 기록되는 과정을 기다리지 않고 먼저 저널 로그에 기록한 다음에 사용자에게 작업 처리 결과를 리턴 하게 됩니다.
WriteConcern 옵션에 따라 달라질 수는 있으나 기본적으로 저널 로그에 완료된 다음 사용자에게 처리 결과를 반환하게 됩니다.
공유 캐시에 변경 내용이 어느정도 쌓이게 되면 체크포인트를 발생시켜서 공유 캐시의 더티 페이지를 모아서 디스크에 기록하게 됩니다. 이때 더티 페이지는 디스크에 기록하기 전에 가공 작업(원본 레코드와 변경된 정보의 병합)을 거쳐야 하는데, WiredTiger 스토리지 엔진의 리컨실리에이션(Reconciliation) 모듈이 이 작업을 수행하게 됩니다.
WiredTiger 스토리지 엔진의 이빅션(Eviction) 모듈은 공유 캐시가 적절한 메모리 사용량을 유지하도록 공유 캐시에서 자주 사용되지 않은 데이터 페이지들을 제거하는 작업을 수행합니다. 제거해야 하는 데이터 페이지가 더티(dirty) 페이지라면 리컨실리에이션 모듈을 이용해 디스크에 데이터를 기록하고 공유 캐시에서 제거하게 됩니다.
WiredTiger 스토리지 엔진의 데이터 페이지(블록)은 블록 크기에 대한 상한선은 있지만 모두 가변 사이즈입니다. 오라클 DBMS 나 MySQL DBMS 와 같은 DB는 모두 고정된 크기의 블록 사이즈를 사용하고 있습니다.
고정 사이즈, 가변 사이즈의 각각 장단점은 있으며 고정 사이즈에 비해 가변 사이즈를 사용하는 WiredTiger 스토리지 엔진에서는 압축이 더 좋다는 것이 장점입니다. 그래서 WiredTiger 스토리지 엔진에서는 데이터 파일 압축이 선택이라는 것보다는 디폴트 옵션처럼 자주 사용되고 있습니다.
블록 매니저(Block Manager)는 변경된 데이터 블록을 기록할 때, 프레그멘테이션을 최소화하면서 데이터 블록의 크기에 최적인 위치를 찾아서 저장을 하게 됩니다. 추가로 블록 매니저는 데이터 블럭의 압축과 암호화 등과 같이 응용 프로그램에 투명하게 작동하는 기능을 모두 내장하고 있습니다.
내용이 긴 관계로 이번 포스팅은 여기서 마무리하고 다음 포스팅에서 이어서 진행하도록 하겠습니다.
• 다음 글

해당 포스팅은 Real MongoDB 책의 많은 내용 중에서 일부분의 내용만 함축적으로 정리한 것으로 모든 내용 확인 및 이해를 위해서 직접 책을 통해 모든 내용을 확인하시는 것을 권해 드립니다.
Reference
Reference Book
• Real MongoDB
Reference URL
• mongodb.com/what-size-wiredtiger
• mongodb.com/serverStatus/wiredtiger
• mongodb.com/mongodb-setting-storage.wiredTiger
• mongodb.com/4.0/deprecate-mmapv1
• mongodb.com/4.2/removed-mmapv1-storage-engine
연관된 다른 글



Principal DBA(MySQL, AWS Aurora, Oracle)
핀테크 서비스인 핀다에서 데이터베이스를 운영하고 있어요(at finda.co.kr)
Previous - 당근마켓, 위메프, Oracle Korea ACS / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Python, Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io