PostgreSQL Transaction ID Wraparound Acil Durumu: Dondurma (Freeze) Planı
XID yaşı kritik seviyeye ulaştığında veritabanını yazmaya kapanmaktan kurtaran adımları verir. Engelleyicileri temizler ve VACUUM FREEZE'i doğru sırayla çalıştırır.
Operasyonel Güvenlik ve Risk Uyarısı
Bu runbook müdahale adımları içerir; birçok adım yazma etkilidir (KILL, terminate, DROP, RESIZE). Önce test ortamında deneyin, üretimde adımları sırayla ve doğrulayarak uygulayın.
1. Belirti / Symptom
- 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. Etki / 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. Teşhis / Diagnosis
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;-- 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;4. Müdahale / Response
- 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');`.
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;ALTER SYSTEM SET vacuum_cost_delay = 0;
SELECT pg_reload_conf();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. Doğrulama / Verification
- `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. Geri Alma / Rollback
- `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.