📢 본 문서에서는 ①Vacuum의 목적과 ②Vacuum 동작 Mode에 대해 먼저 알아보도록 하겠습니다. 이후 조금은 특별하게 동작하는 ③Vacuum Freeze의 동작원리를 설명한 후 마지막으로 ④전체적인 Vacuum 수행 프로세스에 대해 알아보도록 하겠습니다. 더불어 지난 문서들을 통해 소개되었던 개념들이 모두 혼용되어 사용되는 만큼, 충분한 이해를 바탕으로 읽기를 추천합니다.
Manual Vacuum
Vacuum 이란?
진공청소기라는 뜻을 지닌 Vacuum은 PostgreSQL에만 존재하는 특수한 개념입니다. 앞선 문서에서 강조했다시피 MVCC 동작원리에 따른 공간 비효율과 XID Wraparound발생 등 PostgreSQL의 특성에 기인한 부작용을 회피하기 위해 등장했습니다.
Vacuum은 명령어 조합에 따라 VACUUM
, VACUUM FULL
, VACUUM FREEZE
등으로 나뉘기도 하는데, 본 문서에서는 Autovacuum Launcher에 의해 수행되는 Vacuum이 아닌 사용자가 직접 수행한 Manual Vacuum에 대해 알아보도록 하겠습니다.
Vacuum의 목적
Vacuum의 주요 목적을 4가지로 정리하면 다음과 같습니다.
1. 디스크 공간 확보
2. Transaction ID Wraparound로 인한 오래된 자료의 손실 방지
3. 통계 정보 갱신
4. Visibility Map(VM) 갱신 작업
이 중 본 문서에서는 Vacuum의 핵심 목표인 디스크 공간 확보와 XID Wraparound 방지에 대한 내용을 정리한 후 Vacuum 동작 Mode에 대한 내용을 확인해 보도록 하겠습니다.
디스크 공간 확보
PostgreSQL은 MVCC 모델 구현을 위해 예전 버전의 데이터도 삭제하지 않은 상태로 남겨놓기 때문에 변경이 빈번한 테이블의 사이즈는 증가할 수밖에 없습니다. 하지만 예전 버전의 데이터들이 현재 진행 중인 트랜잭션들에 의해 더 이상 참조되지 않는다는 것만 보장된다면, 해당 버전의 데이터는 삭제되거나 재사용 가능한 상태로 변경되어도 무방합니다.
Vacuum은 이처럼 구 버전 데이터를 재사용 가능한 상태로 변경하거나 구 버전 데이터의 물리적인 공간을 OS로 반환함으로써 디스크 공간을 확보하는 역할을 수행합니다.
전자의 경우를 Standard Vacuum이라고 부르며, VACUUM
명령어에 의해 수행됩니다. 반면, 후자는 구 버전 데이터를 제외하여 파일을 재구성하는 방식으로 VACUUM FULL
명령어에 의해 수행됩니다.
Standard Vacuum의 수행 절차는 다음과 같습니다
1. VM 파일 정보를 기반으로 Vacuum 대상 페이지를 선정
2. 해당 페이지에서 Dead Tuple에 대한 정리 작업을 수행
Standard Vacuum은 공간관리 측면에서 보면 최소의 공간 사용과는 거리가 있어 보입니다. 그러나 주기적인 Vacuum수행으로 인한 재사용 공간의 확보는 데이터 증가 량을 억제하는 효과가 있기 때문에 최적의 공간 유지라는 일부 목적은 달성할 수 있습니다.
반면, Vacuum Full 작업의 경우 앞서 이야기한 Standard Vacuum과는 전혀 다른 방식으로 동작하게 됩니다.
Standard Vacuum이 기존 데이터에 대해 재사용 가능한 공간을 확보하고 반환하는 과정이라 한다면, Vacuum Full은 일종의 Table Reorganization 작업과 유사하다 할 수 있습니다.
즉, Live Tuple 들만을 모아서 새로운 테이블을 구성하고, 기존 테이블을 삭제하는 과정을 통해 물리적인 공간 반환이 가능한 것입니다. 하지만 이러한 재구성 방식의 동작 과정은 Table에 대한 Exclusive Lock의 획득 과정이 필요하며, 이는 동시성을 떨어뜨리는 원인이 되므로 사용에 주의가 필요합니다. 또한, 신규 테이블을 위한 일정량의 디스크 공간이 존재해야 작업을 시작할 수 있기도 합니다.
오래된 자료 손실의 방지
XID Wraparound 방지를 위한 Data Freezing 작업 역시 Vacuum의 주요 목적 중 하나입니다.
Data Freezing작업 절차는 다음과 같으며, 앞서 설명한 디스크 공간 정리 작업 후 수행됩니다.
1. VM 파일 정보를 기반으로 Vacuum 대상 페이지를 선정
2. 해당 페이지에서 Dead Tuple에 대한 정리 작업을 수행
3. 해당 페이지에서 Data Freezing 작업을 수행
Data Freezing 작업은 개별 Row(Tuple)의 Age가 VACUUM_FREEZE_MIN_AGE
보다 큰(=오래된) Row를 대상으로 한다고 이야기한 바 있습니다. VACUUM_FREEZE_MIN_AGE
값을 줄일 경우보다 많은 Row를 Freezing 시킬 수 있지만 더 많은 시간과 자원을 필요로 합니다.
얼핏, VACUUM_FREEZE_MIN_AGE
를 작게 설정하면, 이후 Data Freezing을 수행할 대상 Row들이 줄어드는 이점이 있다고 생각할 수 있습니다. 하지만, 만약 최근 데이터에 대한 조작(Delete/Update)이 빈번한 테이블의 VACUUM_FREEZE_MIN_AGE
수치를 작게 설정하면 애써 Freezing 한 최근 데이터들이 다시 ALL_FROZEN=0인 상태로 변경될 수 있습니다. 이 경우 최근 변경 데이터에 대한 지속적인 Data Freezing 과정을 수행하는 비효율이 발생할 수 있으므로 테이블 용도와 사용 패턴에 맞는 설정이 필요합니다.
📌 vacuum_freeze_min_age
Vacuum이 Freeze 할 Row의 최소 Age이며, 기본값은 5천만(50,000,000)입니다.
Standard Vacuum Mode
Standard Vacuum은 내부적으로 두 가지 Mode로 동작하게 됩니다. 각각을 Eager Mode와 Lazy Mode라고 부르며 각 Mode의 동작 기준 및 내부 처리 동작에 대해 알아보도록 하겠습니다.
📌 사실 두 Mode는 Document에 존재하는 정식 용어는 아닌 것으로 확인됩니다. Eager Mode/ Lazy Mode를 각각 Aggressive Vacuum / Vacuum으로도 칭하기도 하지만, 본 문서에서는 Vacuum Freeze에 사용될 Aggressive Vacuum과 구분하기 위해 Eager Mode / Lazy Mode를 사용하도록 하겠습니다.
Mode의 기준
두 Mode 중 무엇을 선택할지 여부는 오로지 Table의 Age에 의해 결정됩니다.
Vacuum이 수행되는 시점에 Table의 Age가 VACUUM_FREEZE_TABLE_AGE
보다 크면(=오래됐다) Eager Mode로 동작하며, 반대로 VACUUM_FREEZE_TABLE_AGE
보다 작은 경우라면 Lazy Mode로 수행됩니다.
📌 vacuum_freeze_table_age
Vacuum Mode를 결정하는 기준이 되는 Age이며, 기본값은 150,000,000입니다.
Mode의 차이점
Table의 Age에 따라 달라지는 각 Mode의 차이점은 대상 페이지에 있습니다. 각 Mode는 대상이 되는 페이지를 아래와 같이 정의합니다.
Lazy Mode : Visibility Map의 ALL_VISIBLE Bit가 0인 모든 페이지
Eager Mode : Visibility Map의 ALL_FROZEN Bit가 0인 모든 페이지
즉, Lazy Mode에서는 Frozen여부와 상관없이 Dead Tuple이 있는 페이지(ALL_VISIBLE_=0)만을 대상으로 하며, Eager Mode에서는 Lazy Mode 보다 광범위하게 Frozen이 안된 모든 페이지(ALL_FROZEN=0)를 Vacuum의 대상으로 삼는다는 개념입니다. 이러한 차이를 두는 이유는 무엇일까요?
한 가지 예를 들어보겠습니다. 만약 데이터가 입력만 되고 변동이 없는 Table이 있다고 가정해보겠습니다. 데이터 입력 후, Row의 Age값이 VACUUM_FREEZE_MIN_AGE
에 도달하지 않은 상태에서 Standard Vacuum을 수행하였다면 해당 테이블의 모든 페이지는 ALL_VISIBLE=1, ALL_FROZEN=0 상태일 것입니다.
하지만 Vacuum이 Lazy Mode 방식으로만 동작한다면, 위 상태(ALL_VISIBLE=1, ALL_FROZEN=0)의 페이지는 Vacuum 대상 페이지에서 항상 제외될 수밖에 없습니다. 즉, 공간 정리를 위한 작업은 불필요하나, 잠재적으로 Data Freezing의 대상이 될 Row를 가지고 있는 페이지들조차 Vacuum의 대상에서 제외되는 문제가 발생할 수 있습니다.
이러한 상황을 막고자 Table의 Age가 VACUUM_FREEZE_TABLE_AGE
보다 큰 경우 ALL_FROZEN=0인 모든 페이지를 대상으로 하는 Eager Mode로 Vacuum이 동작하게 됩니다.
Eager Mode로 Vacuum이 수행되었다는 것은 전체 페이지에 대한 Data Freezing 상태를 모두 확인하였다는 뜻이기도 하므로 Table의 Age에 사용되는 relfrozenxid
에 대한 갱신작업 역시 가능합니다.
📌 Data Freezing 상태를 모두 확인하였다는 것은 모든 Row를 Data Freezing 하였다는 것이 아니라, 모든 Row가 Data Freezing이 불필요한 상태임을 확인하였다는 것을 의미합니다.
📌 9.6 이전 버전에서는 VM에 ALL_FROZEN Bit 가 없었기 때문에 Eager Mode 수행 시 테이블의 모든 페이지를 Scan 해야 하는 비효율이 존재했습니다. 하지만 9.6 버전에 ALL_FROZEN Bit가 추가되면서 Skip 해야 할 페이지를 식별할 수 있어졌고, Vacuum, 정확히 말하면 Eager Mode의 Vacuum 성능이 좋아지는 효과를 가져왔습니다.
Eager Mode 동작 후 relfrozenxid의 변화
- DB 인사이드 | PostgreSQL Vacuum - 3. Age 문서 中 -
Table의 Age에 사용되는 relfrozenxid 값은 특정 조건 만족 시 갱신 가능하다
해당 문서를 통해 미처 설명하지 못한 특정 조건이란, Eager Mode를 통해 ALL_FROZEN=0인 모든 페이지에 대해 Data Freezing 여부를 확인한 상태를 이야기합니다. Eager Mode로 Vacuum이 수행되면 Table의 relfrozenxid는 다음과 같이 변경됩니다.
relfrozenxid = Current XID - VACUUM_FREEZE_MIN_AGE
또한 변경된 relfrozenxid가 의미하는 바는 다음과 같습니다.
- Table의 가장 오래된 Row의 Age는
VACUUM_FREEZE_MIN_AGE
임을 보장한다. - Table의 가장 오래된 Row의 Age가
VACUUM_FREEZE_MIN_AGE
이므로, Table의 Age 역시VACUUM_FREEZE_MIN_AGE
로 변경된다. (어려진다)
Vacuum Freeze
Vacuum의 목적을 설명하며 언급한 VACUUM
과 VACUUM FULL
외에도 VACUUM FREEZE
라는 명령어가 존재합니다.
사실 FREEZE
옵션을 사용한 Vacuum의 처리과정은 Standard Vacuum과 완전히 동일합니다. 다만 내부적으로 다음 두 Parameter 값을 0으로 조정한 후 Vacuum을 수행한다는 차이가 있을 뿐입니다.
VACUUM_FREEZE_MIN_AGE = 0
VACUUM_FREEZE_TABLE_AGE = 0
내부적으로 VACUUM_FREEZE_TABLE_AGE
를 0으로 설정할 경우 Table의 Age는 항상 VACUUM_FREEZE_TABLE_AGE
보다 크므로 Vacuum이 Eager Mode로 동작하게 됩니다. 또한 Data Freezing 선정기준인 VACUUM_FREEZE_MIN_AGE
를 0으로 설정할 경우 대상 페이지 내 모든 Tuple들이 Data Freezing의 대상이 됩니다.
이와 같이 FREEZE
옵션을 사용한 Vacuum을 Standard Vacuum보다 공격적으로 수행된다 라는 의미에서 Aggressive Vacuum으로 부르기도 합니다.
Manual Vacuum Process
지금까지 이야기한 VACUUM
, VACUUM FULL
, VACUUM FREEZE
와 같은 Manual Vacuum의 동작 과정 및 의사결정에 관여하는 Parameter는 아래와 같습니다.
Parameter | Default Value |
vacuum_freeze_min_age | 50000000 |
vacuum_freeze_table_age | 150000000 |
기획 및 글 | 기술기획팀
이미지 제작 | 디자인그룹 이민석
'엑셈 경쟁력 > DB 인사이드' 카테고리의 다른 글
DB 인사이드 | MySQL Architecture - 1. MySQL 엔진 (0) | 2022.06.30 |
---|---|
DB 인사이드 | PostgreSQL Vacuum - 6. Autovacuum (4) | 2022.04.29 |
DB 인사이드 | PostgreSQL Vacuum - 4. Visibility Map (0) | 2022.04.29 |
DB 인사이드 | PostgreSQL Vacuum - 3. Age (2) | 2022.04.29 |
DB 인사이드 | PostgreSQL Vacuum - 2. Transaction ID (0) | 2022.04.29 |
댓글