본문으로 건너뛰기

6.2 Vacuum/BLOAT/Wraparound

Vacuum 문제는 dead tuple 하나로 판단하지 않습니다. Table 변화 속도, vacuum 실행, 오래된 snapshot, transaction ID age, disk 증가를 함께 봅니다.

PostgreSQL vacuum 지연과 bloat wraparound 위험 경로

Dead tuple 추세

topk(20,
pg_stat_user_tables_n_dead_tup
)

Table 크기가 다르므로 비율도 계산합니다.

pg_stat_user_tables_n_dead_tup
/
clamp_min(
pg_stat_user_tables_n_live_tup
+ pg_stat_user_tables_n_dead_tup,
1
)

n_live_tupn_dead_tup은 추정치입니다. 정확한 row count처럼 사용하지 않고 증가 방향과 vacuum 전후 변화를 봅니다.

Vacuum이 실행되는가

time() - pg_stat_user_tables_last_autovacuum

1970 timestamp나 0에 가까운 초기값은 아직 autovacuum 기록이 없다는 뜻일 수 있습니다. 작은 append-only table은 오랫동안 vacuum이 필요 없을 수도 있으므로, 마지막 시각만으로 경보하지 않습니다.

진행 중인 vacuum은 원본 view로 확인합니다.

SELECT pid,
datname,
relid::regclass AS relation,
phase,
heap_blks_total,
heap_blks_scanned,
heap_blks_vacuumed,
index_vacuum_count
FROM pg_stat_progress_vacuum;

Vacuum을 막는 transaction

오래된 snapshot은 dead tuple 제거 경계를 뒤로 미룹니다.

SELECT pid,
usename,
application_name,
state,
age(backend_xmin) AS xmin_age,
now() - xact_start AS xact_age,
left(query, 200) AS query
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
ORDER BY age(backend_xmin) DESC;

Replication slot과 prepared transaction도 xmin을 붙잡기도 합니다.

SELECT slot_name,
slot_type,
active,
age(xmin) AS xmin_age,
age(catalog_xmin) AS catalog_xmin_age,
pg_size_pretty(
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)
) AS retained_wal
FROM pg_replication_slots;

Wraparound 위험

Database별 가장 오래된 frozen XID age를 봅니다.

SELECT datname,
age(datfrozenxid) AS xid_age,
current_setting('autovacuum_freeze_max_age')::bigint AS freeze_max_age,
round(
age(datfrozenxid)::numeric
/ current_setting('autovacuum_freeze_max_age')::numeric * 100,
1
) AS percent_of_freeze_max_age
FROM pg_database
ORDER BY age(datfrozenxid) DESC;

autovacuum_freeze_max_age에 가까워지면 aggressive vacuum이 시작되지만, storage/lock/긴 transaction 때문에 진행하지 못하면 최종적으로 쓰기 중단 위험이 생깁니다. 일반 BLOAT보다 우선순위가 높습니다.

Exporter의 database_wraparound collector는 기본 비활성입니다. 운영에서 XID age를 지속 추적하려면 활성화 여부와 metric을 배포 version에서 확인합니다.

BLOAT와 dead tuple은 같지 않다

Dead tuple은 재사용 가능한 공간이 될 수 있고, file이 OS로 즉시 줄어들지는 않습니다. BLOAT 판단에는 다음이 필요합니다.

  • table와 index 실제 크기 추세
  • dead tuple 비율과 update/delete rate
  • free space map과 page-level 추정
  • query I/O 증가 여부
  • VACUUM FULL, pg_repack, rebuild의 lock과 추가 공간 비용

크기만 줄이려고 즉시 VACUUM FULL을 실행하면 긴 exclusive lock으로 더 큰 장애를 만들 수 있습니다.

진단 순서

  1. XID wraparound 여유 확인
  2. 오래된 transaction/slot/prepared transaction 확인
  3. Autovacuum 진행과 worker 포화 확인
  4. Dead tuple 증가 속도와 table 크기 확인
  5. Query latency와 I/O 영향 확인
  6. Table별 autovacuum parameter와 maintenance 방법 결정

참고: PostgreSQL routine vacuuming, Progress reporting