Teknoloji

PostgreSQL Autovacuum Tuning ve Bloat’la Barışmak: VPS’te Pratik Ayarlar ve pg_repack ile Neredeyse Sıfır Kesinti

Bir Sabah CPU 100’e Vurur: Autovacuum’u Görmezden Gelmenin Bedeli

Hiç gece boyunca her şey sütliman giderken sabah bir bakmışsınız, VPS nefes alamıyor mu? Benim başıma geldi. CPU tepede, disk I/O kıpkırmızı, uygulama arada bir tökezliyor. Loglara bakınca suçlu çaktırmadan ortaya çıktı: autovacuum, tablo şişkinliğinin altından kalkmak için tüm gücüyle koşuyordu. O an anladım, bu iş “varsayılan ayarlar iyidir” rahatlığıyla yürümüyor; özellikle de küçük bir VPS üzerinde koşuyorsanız, birkaç ince ayar hayat kurtarıyor.

Bugün konuşacağımız şey aslında çok insani: bir şeyleri sürekli güncelleyip siliyoruz, PostgreSQL de buna ayak uydurmak için sahne arkasında uğraşıyor. Ama bazen sahne arkasındaki ekip yoruluyor, görevler birikiyor, bloat (şişkinlik) artıyor, sonra da o meşhur sabah krizi geliyor. Bu yazıda bloat’ın ne olduğunu insan gibi anlatacağım, autovacuum’u VPS gerçeklerine göre nasıl yumuşatabileceğimizi paylaşacağım, en sonunda da “kesinti olmadan nasıl toparlarız” diye sorup pg_repack ile pratik bir yol göstereceğim.

Mesela şöyle düşünün: Restoranda menüden çok şey sipariş ediyorsunuz ama tabaklar boşalınca bir türlü toplanmıyor. Masada artık yemek yok ama tabaklar yer kaplamaya devam ediyor. PostgreSQL’deki bloat tam olarak bu, autovacuum da boş tabakları toplayan garson. Garsonu doğru zamanda, doğru tempoyla çalıştırırsanız masa hep ferah kalır.

Bloat Nedir, Autovacuum Ne İş Yapar ve Neden Canımızı Sıkar?

PostgreSQL, veriyi güncellerken eskisini hemen silmiyor. “Çoklu sürüm” mantığı sayesinde eski ve yeni kayıtlar bir süre birlikte yaşıyor. Sizin işiniz bittiğinde, yani artık o eski kayda kimse bakmayacak hale geldiğinde, autovacuum bu ölü satırları fark edip alanı geri kazandırıyor. Ayrıca istatistikleri güncelliyor, bazen de freezing gibi daha derin temizliklere giriyor. Bu perde arkası rutin, trafiğe göre bazen masum, bazen de yoğun bir tempoya dönüşebiliyor.

Şişkinlik dediğimiz şey, bu ölü satırların ve parçalanmış sayfaların birikmesi. Diskte yer kaplıyor, index’lerin şişmesine yol açıyor, okuma ve yazmayı ağırlaştırıyor. Özellikle çok yazma yapan tablolarda, bir süre sonra sorguların ayaklarına küçük ağırlıklar bağlanmış gibi hissettiriyor. Autovacuum bunu düzene sokuyor ama yanlış zamanda agresifleşirse, küçük bir VPS’in kaynaklarını çekip alabiliyor. Tam tersi, fazla temkinliyse bu kez bloat yükseliyor ve yük anında tek seferde hesap sormaya geliyor.

İşin zor kısmı dengeyi kurmak. Disk I/O hafifken daha cesur, yoğun saatlerde nazik olmak istiyorsunuz. Bir de şu var: VACUUM FULL gibi ağır topçular masayı bir kerede silip süpürür ama uzun kilitler getirir. Çoğu zaman günlük koşuda buna cesaret edemeyiz. O yüzden bu yazının bir yerinde pg_repack’ten bahsedeceğim; çünkü tam o aradığımız “masayı sessizce temizle, müşteriyi rahatsız etme” hissini yaşatıyor.

Şişkinliği Nasıl Fark Ederiz? Basit Ölçümler, Loglar ve Küçük Tüyolar

Bir şeyi iyileştirmeden önce görmemiz lazım. Ben genelde ilk bakışı basit sorgularla atarım. Örneğin, hangi tabloda ölü satır birikmiş, en tepedekiler kim, şöyle bir yoklamak bile fikir verir:

SELECT schemaname, relname, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;

Bu sayı tek başına karar verdirmesin ama trendleri izlemekte çok işe yarar. Bir diğer pratik yol, autovacuum loglarını açmak. Kısa bir süre için detaylı kayda alıp sonra tekrar hafifletmek iyi bir taktiktir. Örneğin:

# postgresql.conf içinde bir dönemlik tanılama:
log_autovacuum_min_duration = 0   # bir süreliğine, sonra 5s veya 1s gibi bir değere çekin

Bu sayede hangi tablo, ne kadar sürede, ne kadar sayfa temizlenmiş görebilirsiniz. Loglarınıza düzenli bakmayı seviyorsanız, merkezi bir sistem kurma konusu size tanıdık gelebilir. Ben böyle durumlarda VPS loglarını tatlı tatlı toplayan bir düzen kurmayı seviyorum; hem alarm kurmak kolay oluyor, hem de trendler ortaya çıkıyor.

Daha detaylı bloat tahmini için pgstattuple eklentisi güzel bir büyüteç gibi çalışır. Tek bir tabloya bakıp gerçekten ne kadar boşluk, ne kadar canlı veri var görmek isterseniz çok yardımcıdır. Geliştiricilerin sevdiği pratik, anlaşılır bir çıktısı var. Bir de rutin vacuuming’in mantığına göz atmak isterseniz, resmi dokümantasyonun düzenli vacuum bölümüne arada bir dönmek iyi gelir; kısa, net ve yol gösterici.

VPS’te Autovacuum Ayarlarını Yumuşatmak: Pratik, Hafif ve Etkili

Küçük-orta bir VPS için en büyük hedefim, autovacuum’u işini yaparken nazikleştirmek ve yoğun saatlerde gölgede tutmak. Bunu birkaç ayarla hissedilir biçimde başarabiliyoruz. Hani bir odaya yavaşça süpürgeyle girer, çocuk uyurken gürültü yapmadan işinizi tamamlarsınız ya, tam öyle. Aşağıdaki ayarlar “başlangıç noktası” gibi düşünülmeli; sonra ölçüp küçük dokunuşlarla oturtmak ideal.

# Küresel (postgresql.conf) öneri-örnekleri — VPS için sakin başlangıç
autovacuum = on
autovacuum_naptime = '30s'                # daha sık yokla, küçük işleri biriktirme
autovacuum_max_workers = 2                 # 2-3 arası; CPU ve I/O durumuna göre
autovacuum_vacuum_scale_factor = 0.05      # büyüyen tablolarda daha erken temizle
autovacuum_analyze_scale_factor = 0.05
autovacuum_vacuum_threshold = 200          # çok küçük tablolarda tetikleyici taban
autovacuum_analyze_threshold = 200
vacuum_cost_delay = '5ms'                  # nazik adımlar
vacuum_cost_limit = 2000                   # her adımda ne kadar “maliyet” göze alınır
maintenance_work_mem = '256MB'             # reindex/pg_repack ve vacuum için alan
track_io_timing = on                       # I/O zamanlarını görüp ölçümlerde kullanın

Bu ayarları yazdıktan sonra bir iki gün gözlem yapmak önemli. “Çok nazik olmuş, bloat yükseliyor” hissederseniz cost_limit’i biraz artırın ya da naptime’ı kısaltın. Tersi durumda, yani yoğun saatlerde rahatsız ediyorsa cost_delay’i artırıp daha kibar hale getirin. Ben yoğun saat dışı pencerelerde biraz agresifleşmeyi seviyorum. Hatta ALTER SYSTEM ile değerleri değiştirip SELECT pg_reload_conf() diyerek günlük ritme uygun küçük geçişler yaptığınızda etkisini hemen hissedersiniz.

Büyük, bol yazma alan tablolara özel ayar vermek altın değerinde. O tablo için autovacuum’u daha sık ama küçük lokmalar halinde çalıştırmak tabloyu ferah tutar. Örneğin:

ALTER TABLE public.olaylar SET (
  autovacuum_vacuum_scale_factor = 0.02,
  autovacuum_analyze_scale_factor = 0.02,
  autovacuum_vacuum_threshold = 100,
  autovacuum_analyze_threshold = 100
);

Böylece genel ayarlarınızı bozmadan, sorun çıkaran tabloya özel reçete yazmış oluyorsunuz. Yeri gelmişken, uygulama tarafında okuma yükünü azaltmak da bloat’ın etkisini hafifletir. Dinamik sayfalarınız için küçük mikro önbellek katmanları kurmak, hem veritabanını dinlendirir hem de autovacuum’ın arada nefes almasını sağlar.

VACUUM FULL mı, pg_repack mı? Neredeyse Sıfır Kesinti Arayanlara

İtiraf edeyim, günlük koşuda VACUUM FULL beni gerer. Yaptığı iş çok net ama getirdiği uzun kilit yüzünden çoğu uygulamada cesaret edemeyiz. O yüzden bloat ciddi seviyeye geldiğinde ve alanı geri kazanmak istiyorsak, ben pg_repack’i tercih ediyorum. Arka planda masayı yeniden kurup, en sonda hızlı bir değişimle işleri yoluna koyuyor; kilit süreleri genelde çok kısa kalıyor.

pg_repack’i kullanmadan önce küçük bir şart var: tablonuzda birincil anahtar ya da benzersiz bir index olmalı. Bu sayede arka planda tutarlı bir şekilde yeni tabloyu dokuyabiliyor. Kurulum basit; paket yöneticilerinde ya da kaynak koddan kurulabiliyor. Sunucuda eklentiyi bir defa tanıtmak da gerekiyor:

-- veritabanında bir kereye mahsus
CREATE EXTENSION IF NOT EXISTS pg_repack;

Sonrasında komut satırından tablo bazında ilerlemek rahat. Önce küçük bir tablodan başlamak moral ve güven verir, sonra büyük tablolara geçilir:

# tek tabloyu repack etmek
pg_repack -h 127.0.0.1 -p 5432 -U app -d uygulama -t public.olaylar

# tüm veritabanını repack etmek (önce testte deneyin)
pg_repack -h 127.0.0.1 -p 5432 -U app -d uygulama -a

Komut çalışırken kısa süreli iki kritik an olur: başlarken ve en sonda “swap” yaparken çok kısa kilit alır. Genellikle kullanıcı fark etmez. Yine de trafik yoğunken değil, bir tık sakin bir zamanda yapmak iyi hissettirir. Araçla ilgili seçeneklere göz atmak isterseniz pg_repack’in resmi deposu açıklayıcıdır; ama gözünüzü korkutmasın, temel kullanım oldukça yalın.

Bu yaklaşımın güzelliği şu: uygulamayı ayakta tutarsınız, disk alanını geri kazanırsınız, index’ler toparlanır. Bunu dinamik şema değişikliklerine benzetebilirsiniz. Benzer “kesintiyi minimize etme” refleksini, farklı veritabanı dünyalarında da severiz; örneğin sıfır kesinti yaklaşımının mantığı burada da ilham veriyor.

Operasyon Akışı: Yedek, Gözlem, Küçük Pencereler ve Rahat Bir Nefes

Şimdi işin mutfak tarafını toparlayalım. Küçük bir planla, bloat ve autovacuum konusunu kontrol altına almak mümkün. Önce sağlam bir yedekle başlamak lazım; hem güven verir, hem de başımıza iş açmadan önce nefes aldırır. Ben böyle kritik dokunuşlardan önce tek düğmeyle geri dönebileceğim bir planı seviyorum. Bu konuda bir yol haritasına ihtiyaç duyuyorsanız, yedek ve kurtarma planlarını gözden geçirmek iyi gelir.

Sonra hafif bir ölçüm turu: en çok büyüyen tablolara bakın, loglardan autovacuum’ın nerelerde zorlandığını not alın. Gündüz yoğunluğunda nazik, gece daha kararlı bir profil çizmek için ayarları küçük dokunuşlarla açıp kapatın. Bir iki gün içinde ritim oturur. Çok inatçı şişkinliklerde pg_repack’i küçükten büyüğe doğru çalıştırmak iyi sonuç verir, bu sırada disk alanınızın yeterli olduğundan emin olun.

Uygulama tarafında, gereksiz yazmaları azaltmak ve “aynı satırı kısa sürede tekrar tekrar güncelleme” huyunu biraz törpülemek de fayda sağlar. Okuma yükünü CDN, sayfa önbelleği ya da uygulama içi kısa süreli cache ile hafifletmek, veritabanının daha sakin bir dengeye oturmasına yardım eder. Küçük bir değişiklik bile vakumun arayı kapatmasını kolaylaştırır. Bazen mesele sadece veritabanında değil, trafiğin ritminde gizlidir.

Saha Notları: Sık Yapılan Hatalar ve Yumuşak İniş Taktikleri

Şunu çok gördüm: varsayılan ayarlar küçük veriyle güzel çalışıyor, ama tablo büyüyünce tetikleme eşiği orantısız hale geliyor. Bir bakıyorsunuz, tablo yüz milyon satıra koşmuş, scale factor yüzünden autovacuum koşmamış, bloat birikmiş. Çözüm basit: büyük tablolara per-table ayar verin ve scale factor’ü küçültün. Diğeri de şu: logları tamamen kapatıp “her şey yolunda” demek. Oysa arada bir kısa süreli detaylı log almak, nerede aksadığınızı bir anda gösterir.

Bir de “VACUUM FULL yapar geçerim” coşkusu var. Evet, temizler ama kilit süreleri can sıkar. Üstelik ufak bir pencerede yakalamak zor. Onun yerine pg_repack ile küçük adımlarla ilerlemek çok daha huzurlu hissettiriyor. Tabii, burada da disk alanına ve index yapılarına dikkat etmek gerek. Anahtar yoksa önce uygun bir index yaratmak şart.

Son not: maintenance_work_mem’i gereksizce kısarsanız, reindex ve repack gibi işler uzun sürer. Çok yükseltirseniz küçük VPS’te başka işler dar boğaza girer. Bir iki denemede “işler akıyor ama sistem rahat” dengesini bulmak mümkün. Küçük değiştir, ölç, bir daha değiştir; ritim böyle kuruluyor.

Kapanış: Bloat’ı Ehlileştirmek İçin Küçük Adımlar, Büyük Rahatlık

Toparlayalım. Bloat, aslında günün sonunda masa üzerinde kalan boş tabaklar. Autovacuum o tabakları topluyor, istatistikleri yeniliyor ve veritabanının iç düzenini koruyor. Küçük bir VPS üzerinde yapacağınız birkaç ayar, bu işin gürültüsünü kısmaya yetiyor. Ölçerek ilerlemek, yoğun saatlerde nazik olmak ve per-table reçeteler yazmak, sistemi akışkan tutuyor. Sıkışmış tablolarda pg_repack ile neredeyse hiç hissettirmeden derin temizlik yapmak da cabası.

Pratik öneri olarak şunları aklınızda tutun: logları ara ara detaylandırıp izleyin, en çok büyüyen tablolara özel ayar verin, cost delay ve limit ile nazik/agresif dengesini bulun. Bloat inat ettiğinde, uygun bir pencerede pg_repack’i çalıştırıp masayı tazeleyin. Ayarları bir kerede değil, küçük adımlarla değiştirin; ölçmeden körlemesine gitmeyin. İsterseniz rutin vacuum mantığını kısa bir turla resmi dökümanda da tazeleyin; birkaç fikir hemen cebinize giriyor.

Umarım bu yazı size bir nefes aldırmıştır. Bir sonraki bakımda, sabahları panikle değil, “biz bu işi biliyoruz” rahatlığıyla güne başlamanızı isterim. Sorularınız olursa not alın, bir akşam kahvesinde birlikte üzerinden geçeriz. Şimdilik hoşça kalın; veritabanlarınız ferah, geceleriniz sakin olsun.

Sıkça Sorulan Sorular

Güncelleme ve silmelerden kalan ölü satırlar zamanla birikir; buna bloat diyoruz. Her bloat kötü değildir, ama büyüyüp disk ve indeksleri şişirince sorgular yavaşlar. Küçük ve düzenli temizlikle kontrol altında tutmak yeterlidir.

Ayarlar nazik olursa yormaz. vacuum_cost_delay ve vacuum_cost_limit ile tempo ayarlanabilir. Yoğun saatlerde nazik, sakin saatlerde biraz daha cesur davranmak genelde iyi sonuç verir.

Bloat çok yükselip alan geri kazanmak istediğinizde, kesintisiz diyebileceğimiz bir temizlik arıyorsanız pg_repack idealdir. Tabloda birincil anahtar ya da benzersiz indeks olmalı ve işlem için yeterli disk alanı bulunduğundan emin olun.