dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Runbooks Library/postgresql/#2
Runbook #2
postgresql
AvailabilitySEV1 · CRITICAL OUTAGE15-30 dakika / 15-30 minssuperuser / postgres / rds_superuser

PostgreSQL Transaction ID Wraparound Emergency: Freeze Plan

Steps to save a database from going read-only when XID age reaches a critical level. Clears blockers and runs VACUUM FREEZE in the right order.

Related Metrics:M5M6M7
Related Scripts:S7S3S19S13
#xid#wraparound#vacuum-freeze#critical

Operational Safety & Risk Notice

This runbook contains operational intervention steps; several are write-impacting (KILL, terminate, DROP, RESIZE). Verify in a staging environment first, and apply sequentially in production with verification.

🟢 Salt Okunur (Read-Only)·🟡 Geri Alınabilir (Reversible)·🔴 Yüksek Etkili / Geri Alınamaz (High Impact)

1. Symptom & Signals

- M5: `age(datfrozenxid)` 1,5 milyarın üzerinde ve artıyor.

- Log: `WARNING: database "x" must be vacuumed within N transactions`.

- Son aşama: `ERROR: database is not accepting commands that assign new transaction IDs to avoid wraparound data loss`.

2. Business & Technical Impact

Sınıra yaklaşıldığında PostgreSQL **yazmaları reddeder** (veritabanı fiilen salt okunur olur). Kurtarma, veritabanı kapalıyken tek kullanıcı modunda VACUUM gerektirebilir ve uzun kesinti yaratır.

3. Diagnosis & Root-Cause Analysis

🟢 Read-Only1. Hangi veritabanı ve tablolar eski (S7):
sql
SELECT datname, age(datfrozenxid) AS xid_age FROM pg_database ORDER BY 2 DESC;
-- Sorunlu veritabanına bağlanıp:
SELECT c.oid::regclass AS table_name, age(c.relfrozenxid) AS xid_age,
       pg_size_pretty(pg_total_relation_size(c.oid)) AS size
FROM pg_class c WHERE c.relkind IN ('r','m','t')
ORDER BY age(c.relfrozenxid) DESC LIMIT 15;
🟢 Read-Only2. **Vacuum'u engelleyenleri** bulun. En eski XID'i tutan her şey freeze'i engeller:
sql
-- Uzun transaction'lar
SELECT pid, usename, state, now()-xact_start AS age, backend_xmin
FROM pg_stat_activity WHERE backend_xmin IS NOT NULL ORDER BY age(backend_xmin) DESC LIMIT 5;
-- Unutulmuş prepared transaction'lar
SELECT gid, prepared, owner, database FROM pg_prepared_xacts ORDER BY prepared;
-- Replikasyon slotları (S13)
SELECT slot_name, active, xmin, catalog_xmin FROM pg_replication_slots;
-- Standby'lardan gelen feedback
SELECT pid, application_name, backend_xmin FROM pg_stat_replication;
🟢 Read-Only3. Autovacuum çalışıyor mu (S19)? `pg_stat_progress_vacuum` içinde anti-wraparound vacuum görünüyorsa dokunmayın, bitmesini bekleyin.

4. Remediation & Action Plan

🔴 HIGH RISK / IRREVERSIBLE1. **Engelleyicileri kaldırın:**

- Uzun/idle transaction: `pg_terminate_backend(pid)`.

- Unutulmuş prepared transaction: `COMMIT PREPARED 'gid';` veya `ROLLBACK PREPARED 'gid';` (sahibine danışın).

- Terk edilmiş replikasyon slotu: `SELECT pg_drop_replication_slot('slot_adi');`.

🟡 Reversible2. En eski ve **küçük** tablolardan başlayarak elle dondurun (hızlı kazanım, en büyük tablo en sona):
sql
VACUUM (FREEZE, VERBOSE) kucuk_eski_tablo;
-- PG 12+, acil durumda indeks temizliğini atlayıp hızlandırmak için:
VACUUM (FREEZE, INDEX_CLEANUP OFF, VERBOSE) buyuk_tablo;
🟡 Reversible3. Paralel çalıştırın (farklı oturumlarda farklı tablolar), disk I/O sınırını göz önünde bulundurun. Gerekirse geçici olarak:
sql
ALTER SYSTEM SET vacuum_cost_delay = 0;
SELECT pg_reload_conf();
🔴 HIGH RISK / IRREVERSIBLE4. Veritabanı yazmayı tamamen reddediyorsa: PostgreSQL'i durdurun ve **tek kullanıcı modunda** vacuum çalıştırın:
bash
postgres --single -D /var/lib/postgresql/data <veritabani_adi>
backend> VACUUM FREEZE;

Bu mod kesinti gerektirir; yedeğiniz olduğundan emin olun.

5. **Kalıcı çözüm:** Büyük ve hızlı değişen tablolar için tablo bazında `autovacuum_freeze_max_age` ve `autovacuum_vacuum_cost_limit` ayarlayın. PG 14+ `vacuum_failsafe_age` ile failsafe modu devreye girer. M5 için %50'de uyarı kurun.

5. Verification & Health Checks

- `age(datfrozenxid)` 500 milyonun altına indi (veya düşme eğiliminde ve engelleyici yok).

- Yazmalar normal, log'da wraparound uyarısı yok.

- Autovacuum'un en büyük tablolarda yeniden çalıştığı `pg_stat_user_tables.last_autovacuum` ile görülüyor.

6. Rollback & Contingency Plan

- `VACUUM FREEZE` geri alınmaz ama zararsızdır (yalnızca kaynak tüketir).

- `vacuum_cost_delay` ayarını işiniz bitince eski değerine çevirin: `ALTER SYSTEM RESET vacuum_cost_delay;`.

- Prepared transaction ve slot silme geri alınamaz.

More POSTGRESQL Runbooks