6.2 Vacuum/BLOAT/Wraparound
Vacuum 문제는 dead tuple 하나로 판단하지 않습니다. Table 변화 속도, vacuum 실행, 오래된 snapshot, transaction ID age, disk 증가를 함께 봅니다.
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_tup과 n_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으로 더 큰 장애를 만들 수 있습니다.
진단 순서
- XID wraparound 여유 확인
- 오래된 transaction/slot/prepared transaction 확인
- Autovacuum 진행과 worker 포화 확인
- Dead tuple 증가 속도와 table 크기 확인
- Query latency와 I/O 영향 확인
- Table별 autovacuum parameter와 maintenance 방법 결정