PostgreSQL 구조
날짜: 2025-06-29
목록으로
프로세스 구조
주요 프로세스
- Postmaster (메인 프로세스)
- 클라이언트 연결 요청 처리
- 백엔드 프로세스 생성 및 관리
- 시스템 종료 시그널 처리
- Backend Process (백엔드 프로세스)
- 클라이언트 요청 처리
- SQL 쿼리 실행
- 트랜잭션 관리
- Background Process (백그라운드 프로세스)
- WAL Writer: WAL 버퍼를 디스크에 쓰기
- Checkpointer: 체크포인트 수행
- Background Writer: 더티 페이지를 디스크에 쓰기
- Autovacuum Launcher: Autovacuum 워커 프로세스 관리
- Autovacuum Worker: 테이블 정리 작업 수행
- Archiver: WAL 파일 아카이빙
- Statistics Collector: 통계 정보 수집
메모리 구조
Shared Memory (공유 메모리)
- Shared Buffer: 테이블과 인덱스 데이터 캐싱
- WAL Buffer: WAL 레코드 임시 저장
- Commit Log: 트랜잭션 커밋 상태
- Lock Space: 락 정보 저장
- Shared Memory Context: 공유 데이터 구조
Local Memory (로컬 메모리)
- Work Memory: 정렬, 해시 조인 등에 사용
- Maintenance Work Memory: VACUUM, CREATE INDEX 등에 사용
- Temp Buffer: 임시 테이블 데이터
- Local Memory Context: 세션별 데이터
논리적 구조
클러스터 (Cluster)
- PostgreSQL 인스턴스 전체
- 여러 데이터베이스 포함
데이터베이스 (Database)
스키마 (Schema)
- 데이터베이스 내 논리적 네임스페이스
- 기본 스키마:
public
, information_schema
, pg_catalog
- 롤(Role): DB 관련 권한
데이터베이스 객체 (Database Objects)
- 테이블 (Table): 데이터 저장
- 인덱스 (Index): 검색 성능 향상
- 뷰 (View): 가상 테이블
- 시퀀스 (Sequence): 자동 증가 값
- 함수 (Function): 저장 프로시저
- 트리거 (Trigger): 이벤트 기반 동작
- 테이블스페이스 (Tablespace): 물리적 저장 위치 지정
릴레이션 (Relation)
- 테이블, 인덱스, 뷰의 통칭
- 시스템 카탈로그에서 관리
튜플 (Tuple)
페이지 (Page)
- 디스크 I/O의 기본 단위 (8KB)
- 튜플과 메타데이터 포함
물리적 구조
디렉토리 구조
$PGDATA/
├── base/ # 데이터베이스 파일
├── global/ # 글로벌 시스템 카탈로그
├── pg_wal/ # WAL 파일
├── pg_xact/ # 커밋 로그
├── pg_stat_tmp/ # 통계 정보
└── postgresql.conf # 설정 파일
포크 (Fork)
PostgreSQL 테이블은 여러 포크로 구성:
- Main Fork: 실제 데이터 (튜플)
- Free Space Map (FSM): 사용 가능한 공간 정보
- Visibility Map (VM): 튜플 가시성 정보
- Initialization Fork: 언로그 테이블의 초기 데이터
OID (Object Identifier)
- 데이터베이스 객체의 고유 식별자
- 시스템 카탈로그에서 관리
- 32비트 정수형
파일 구조
- Heap File: 테이블 데이터
- Index File: 인덱스 데이터
- TOAST File: 큰 값 저장
- WAL File: 트랜잭션 로그
FSM, VM 과 Vacuum의 관계
Vacuum이란?
Vacuum은 PostgreSQL에서 테이블의 데드 튜플(Dead Tuple)을 정리하고 저장 공간을 회수하는 중요한 유지보수 작업입니다.
Vacuum의 주요 목적:
- 데드 튜플 제거: DELETE나 UPDATE로 인해 더 이상 사용되지 않는 튜플 정리
- 저장 공간 회수: 삭제된 튜플이 차지하던 공간을 재사용 가능하게 만듦
- 통계 정보 업데이트: 테이블과 인덱스의 통계 정보 갱신
- 트랜잭션 ID 래핑 방지: XID 래핑 문제 해결
Vacuum의 종류:
- VACUUM: 데드 튜플만 제거 (공간 회수 안함)
- VACUUM FULL: 테이블 재구성하여 공간 회수
- VACUUM ANALYZE: 통계 정보도 함께 업데이트
- AUTOVACUUM: 자동으로 실행되는 백그라운드 Vacuum
FSM, VM이 Vacuum 작업과 어떤 관련이 있는지?
Free Space Map (FSM)과 Vacuum
FSM은 테이블의 각 페이지에서 사용 가능한 공간을 추적하는 데이터 구조입니다.
-- FSM 정보 확인
SELECT schemaname, tablename, attname, n_distinct, correlation
FROM pg_stats
WHERE tablename = 'your_table_name';
FSM과 Vacuum의 관계:
- Vacuum 전: FSM은 데드 튜플이 차지하는 공간을 “사용 중”으로 표시
- Vacuum 중: 데드 튜플을 제거하면서 FSM을 업데이트
- Vacuum 후: FSM이 새로운 사용 가능한 공간을 정확히 반영
FSM의 역할:
- 새로운 튜플 삽입 시 적절한 페이지 선택 도움
- 공간 효율성 향상
- 페이지 분할 최소화
Visibility Map (VM)과 Vacuum
VM은 각 페이지의 모든 튜플이 모든 트랜잭션에서 보이는지를 추적합니다.
-- VM 정보 확인 (PostgreSQL 내부 뷰)
SELECT * FROM pg_stat_all_tables
WHERE schemaname = 'public' AND relname = 'your_table_name';
VM과 Vacuum의 관계:
- VM 비트가 1인 페이지: 모든 튜플이 모든 트랜잭션에서 보임 → Vacuum 스킵 가능
- VM 비트가 0인 페이지: 일부 튜플이 일부 트랜잭션에서 안 보임 → Vacuum 필요
VM의 장점:
- Vacuum 성능 향상: 스킵할 수 있는 페이지 식별
- Index-Only Scan 최적화: 인덱스만으로 쿼리 실행 가능
- 트랜잭션 격리 수준 유지
Wraparound 문제란 무엇이고 VACUUM FREEZE로 이를 해결하는 방법
Wraparound 문제
PostgreSQL의 트랜잭션 ID (XID)는 32비트 정수로 제한되어 있습니다.
-- 현재 XID 확인
SELECT txid_current();
-- 데이터베이스별 XID 사용량 확인
SELECT datname, age(datfrozenxid) as xid_age
FROM pg_database
ORDER BY xid_age DESC;
문제 발생 과정:
- XID는 0부터 시작하여 증가
- 약 21억 개의 트랜잭션 후 최대값 도달
- XID가 다시 0부터 시작 → Wraparound 발생
- 이전 트랜잭션과 현재 트랜잭션의 순서 구분 불가
Wraparound의 위험성:
- 데이터 무결성 손상 가능
- 데이터베이스 접근 불가 (Emergency Mode)
- 복구 불가능한 상황 발생
VACUUM FREEZE로 해결하는 방법
VACUUM FREEZE는 모든 튜플의 XID를 특별한 값으로 고정하여 Wraparound를 방지합니다.
-- VACUUM FREEZE 실행
VACUUM FREEZE table_name;
-- 전체 데이터베이스에 대해 실행
VACUUM FREEZE;
-- 강제로 실행 (트랜잭션 ID 고정)
VACUUM FREEZE VERBOSE table_name;
VACUUM FREEZE의 동작:
- 모든 튜플의 XID를 FrozenXID로 설정
- FrozenXID는 항상 모든 트랜잭션보다 이전으로 간주
- Wraparound 문제 완전 해결
자동 FREEZE 설정:
-- postgresql.conf 설정
autovacuum_freeze_max_age = 200000000 -- 기본값
vacuum_freeze_min_age = 50000000 -- 기본값
모니터링 쿼리:
-- Wraparound 위험도 확인
SELECT
schemaname,
tablename,
age(relfrozenxid) as xid_age,
CASE
WHEN age(relfrozenxid) > 200000000 THEN 'CRITICAL'
WHEN age(relfrozenxid) > 150000000 THEN 'WARNING'
ELSE 'OK'
END as status
FROM pg_stat_user_tables
ORDER BY xid_age DESC;
FSM, VM과 FREEZE의 관계:
- FSM: FREEZE 후 공간 재사용 가능성 업데이트
- VM: FREEZE된 튜플은 모든 트랜잭션에서 보이므로 VM 비트 1로 설정
- 성능 향상: FREEZE 후 Index-Only Scan 최적화 가능
핵심 요약
-
PostgreSQL은 Postmaster(메인), Backend(쿼리처리), Background(유지보수) 프로세스로 구성되며, Shared Memory(공유)와 Local Memory(세션별)로 메모리를 관리한다.
-
논리적 구조는 클러스터 → 데이터베이스 → 스키마 → 객체(테이블, 인덱스 등)의 계층으로, 물리적으로는 디렉토리와 포크(Main, FSM, VM)로 데이터를 저장한다.
-
FSM(Free Space Map)은 페이지별 사용 가능한 공간을, VM(Visibility Map)은 튜플 가시성을 추적하여 Vacuum 성능을 최적화한다.
-
Vacuum은 데드 튜플 제거, 공간 회수, 통계 업데이트를 수행하며, VACUUM FREEZE는 32비트 XID 제한으로 인한 Wraparound 문제를 해결한다.
-
정기적인 모니터링(age(datfrozenxid)
)과 VACUUM 작업이 데이터 무결성과 성능 유지의 핵심이다.
목록으로