데이터베이스 따라잡기

Vacuum과 유지보수

meellon 2026. 7. 9. 05:30

학습 목표

dead tuple·bloatMVCC UPDATE/DELETE성능미치는 이유를 설명할 수 있다.

autovacuum 트리거·모니터링·장시간 TX 차단을 설명할 수 있다.

VACUUM vs VACUUM FULL·ANALYZE 역할트레이드오프를 설명할 수 있다.

transaction id freeze·wraparound 위험을 설명할 수 있다.

InnoDB purgeundo 정리대응함을 개요 수준에서 설명할 수 있다.

문제 상황

  • orders UPDATE 대량테이블 크기 동일 · Seq Scan 2배 느림
  • n_dead_tup 40%autovacuum
  • 장시간 idle in transaction 하나 테이블 vacuum 정지
  • VACUUM FULL 피크 실행30분 exclusive lock · 서비스 중단
  • EXPLAIN rows 추정 10배 오차ANALYZE 6개월
  • MySQL undo tablespace 90%purge lag · long read TX

앞서 MVCCdead tuple 개념; 슬로우 쿼리bloat 의심. 이번 편은 운영 유지보수 절차다.

1. 왜 vacuum이 필요한가

MVCCUPDATE/DELETEin-place 삭제 아님old 버전 dead tuple 남음.

  live tuple dead tuple
가시성 active 스냅샷 가능 어느 TX
공간 데이터 재사용 대기
인덱스 참조 여전히 참조bloat
UPDATE row  →  old version dead  +  new version live
DELETE row  →  tombstone dead
VACUUM      →  dead space reusable · prune index pointers
미 vacuum  
테이블·인덱스 팽창 많은 I/O
Seq Scan 비용 슬로우 쿼리 (21편)
Index Only Scan 실패 visibility map stale
XID wraparound freeze 필요
  • 앞서 디스크·페이지 — 슬롯 재사용
  • InnoDBheap in-place + undopurge 대응

2. VACUUM과 autovacuum

VACUUM — dead tuple 공간 회수 · freeze · 통계 힌트.

종류  
autovacuum 백그라운드 worker설정 임계
VACUUM 수동·cronlock 가벼움
VACUUM ANALYZE vacuum + 통계 갱신
VACUUM FULL 재작성compactexclusive lock
-- code/vacuum-commands.sql
VACUUM (VERBOSE, ANALYZE) orders;

VACUUM (PARALLEL 4) orders_2025_01;  -- PG 13+

-- last resort — downtime window
VACUUM FULL orders;
autovacuum 트리거 (개념)  
autovacuum_vacuum_threshold + scale_factor × reltuples dead 비율
autovacuum_vacuum_insert_threshold insert-only bloat
anti-wraparound vacuum age (relfrozenxid) 임계
# code/autovacuum-config.example
autovacuum = on
autovacuum_vacuum_scale_factor = 0.1
autovacuum_analyze_scale_factor = 0.05
autovacuum_max_workers = 4
log_autovacuum_min_duration = 1s
차단 요인  
Long transaction oldest xmin — dead 정리 불가
Replication slot lagWAL·vacuum 압력
Disabled autovacuum per-table autovacuum_enabled = false

3. 모니터링

-- code/autovacuum-monitor.sql
SELECT relname,
       n_live_tup,
       n_dead_tup,
       round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 1) AS dead_pct,
       last_autovacuum,
       last_autoanalyze,
       age(relfrozenxid) AS xid_age
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
-- transactions blocking vacuum
SELECT pid, xact_start, state, backend_xmin,
       left(query, 80) AS query
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
ORDER BY xact_start;
지표 주의
dead_pct > 20% vacuum 지연 의심
last_autovacuum NULL·오래됨 임계·blocker
xid_age 높음 freeze vacuum
pg_stat_progress_vacuum 진행 작업
  • Observabilityn_dead_tup·autovacuum duration 메트릭
  • Hot 테이블낮은 scale_factor override

4. VACUUM vs VACUUM FULL

  VACUUM VACUUM FULL
동작 dead 슬롯 재사용 표시 파일 복사compact
크기 OS 파일 크기 유지 가능 파일 축소
Lock ShareUpdateExclusiveDML 대부분 가능 ACCESS EXCLUSIVE차단
빈도 상시·autovacuum 드묾·점검
대안 routine ops pg_repack·partition DROP
Bloat 80% but VACUUM ran  →  space reusable inside file, not returned to OS
Need disk back            →  VACUUM FULL or pg_repack or detach/drop partition
선택  
일상 autovacuum + ANALYZE
dead 높음 원인 (long TX) 먼저
디스크 급함 VACUUM FULL·repack·아카이브 partition DROP

5. ANALYZE

ANALYZE통계 갱신옵티마이저 rows·ndistinct (실행 계획 8편).

  VACUUM ANALYZE
목적 dead 공간·freeze 쿼리 플랜
autovacuum vacuum worker analyze 단계
수동 VACUUM ANALYZE / VACUUM ANALYZE
ANALYZE orders;
ANALYZE orders (user_id, created_at);  -- column stats (PG 11+)

SELECT relname, last_analyze, last_autoanalyze, n_mod_since_analyze
FROM pg_stat_user_tables
WHERE relname = 'orders';
시점  
대량 LOAD COPY ANALYZE
스키마 변경 인덱스 추가
플랜 급변 rows 추정 오차 — 21편
  • ANALYZEVACUUM 필요
  • default_statistics_target정밀 vs 속도

6. Freeze와 wraparound

Transaction ID (XID)32-bit 순환오래된 tuple freeze.

age(relfrozenxid) grows  →  anti-wraparound autovacuum
xid age > 2^31 - safety  →  database shutdown risk (forced vacuum)
   
freeze tuple xminFrozenXid모든 TX 가시
visibility map all-frozen pageindex-only skip heap
모니터 pg_database.datfrozenxid · per-table relfrozenxid
  • 장기 미 vacuum클러스터 전체 읽기 전용 강제 위험
  • 파티션오래된 partition DROP = freeze 부담 감소

7. InnoDB purge 개요

  PostgreSQL VACUUM InnoDB purge
대상 heap dead tuple undo log 정리
실행 autovacuum worker purge thread (background)
차단 long TX xmin long read view (MVCC)
compact VACUUM FULL OPTIMIZE TABLE (lock)
-- code/innodb-purge-notes.sql (MySQL)
SHOW VARIABLES LIKE 'innodb_undo_log_truncate';
SHOW VARIABLES LIKE 'innodb_max_undo_log_size';

SELECT * FROM information_schema.innodb_metrics
WHERE name LIKE '%purge%';
증상  
undo tablespace full purge lag
history list length 높음 long running query
  • 앞서 MVCC — 양쪽 다중 버전 · GC 메커니즘 다름
  • 공통long transaction enemy

8. 운영 체크리스트

항목 확인
autovacuum on · workers 충분?
dead_pct hot table TOP?
Blocker idle in transaction·slot?
Analyze last_autoanalyze·bulk load ?
xid_age wraparound 경고?
FULL 정말 필요· 있음?
InnoDB undo·purge lag?

9. 정리

  • dead tupleMVCC 부산물VACUUM 없으면 bloat
  • autovacuum일상 방어long TX 차단 주의
  • VACUUM재사용 표시 · VACUUM FULLcompact·
  • ANALYZE플랜 품질vacuum 별개
  • freezeXID wraparound 방지
  • InnoDBpurgeundo 정리 대응

다음에 다룰 것

  • 파티션 운영
  • detach·attach·drop, 핫 파티션

해당 내용은 Database System Concepts, 7/E (Avraham Silberschatz, Henry F. Korth, S. Sudarshan), PostgreSQL · MySQL InnoDB 공식 문서 의 내용을 기반으로 합니다.

'데이터베이스 따라잡기' 카테고리의 다른 글

CDC 심화  (0) 2026.07.11
파티션 운영  (0) 2026.07.10
슬로우 쿼리 진단  (0) 2026.07.08
CDC와 이벤트  (0) 2026.07.07
캐시와 DB  (0) 2026.07.06