dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Runbook #2
postgresql
AvailabilitySEV1 · KRİTİK KESİNTİ15-30 dakika / 15-30 minssuperuser / postgres / rds_superuser

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.

İlişkili Metrik:M5M6M7
İlişkili Script:S7S3S19S13
#xid#wraparound#vacuum-freeze#critical

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.

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

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

🟢 Salt Okunur1. 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;
🟢 Salt Okunur2. **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;
🟢 Salt Okunur3. Autovacuum çalışıyor mu (S19)? `pg_stat_progress_vacuum` içinde anti-wraparound vacuum görünüyorsa dokunmayın, bitmesini bekleyin.

4. Müdahale / Response

🔴 YÜKSEK RİSK / GERİ ALINAMAZ1. **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');`.

🟡 Geri Alınabilir2. 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;
🟡 Geri Alınabilir3. 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();
🔴 YÜKSEK RİSK / GERİ ALINAMAZ4. 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. 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.

Diğer POSTGRESQL Runbook'ları