MVCC Nedir? PostgreSQL ve MySQL Neden Farklı Yolları Seçti?
Çok Sürümlü Eşzamanlılık Denetimi (Multi-Version Concurrency Control - MVCC), okuyucuların yazarları, yazarların da okuyucuları kilitlemeden aynı anda çalışabilmesini sağlayan veritabanı temel direğidir. Ancak bu mekanizmanın uygulanış biçimi PostgreSQL ve MySQL InnoDB arasında kökten farklıdır:
- PostgreSQL (Append-Only): Satırlar güncellenirken eski satır disk sayfasında bırakılır ve sonlanma zamanı (
t_xmax) atanır. Yeni satır versiyonu ek bir kayıt olarak sayfaya eklenir. Tabloda ve indekslerde zamanla biriken bu eski versiyonlara ölü tuple (dead tuple) denir. - MySQL InnoDB (Delta + Undo Log): Satır, Clustered Index (Primary Key B+Tree) içinde doğrudan yerinde (in-place) güncellenir. Satırın eski hali ise Undo Log segmentine küçük bir delta olarak yazılır. Okuyucular eski bir anlık görüntüyü görmek isterse Undo Log zincirini takip eder.
PostgreSQL'de HOT (Heap-Only Tuples) ve Fillfactor Sırrı
PostgreSQL'de bir satırda 4 adet ikincil indeks varsa ve o satır güncellenirse, normal şartlarda 4 indeksin dördüne de yeni satırı işaret eden yeni yaprak kayıtları eklenir. Bu durum devasa bir yazma amplifikasyonuna (write amplification) ve indeks şişmesine neden olur.
Bu felaketi önlemek için PostgreSQL geliştiricileri HOT (Heap-Only Tuples) mimarisini geliştirdi. Eğer güncellenen kolonlar bir indeks içinde yer almıyorsa VE aynı 8KB disk sayfasında boş yer varsa, yeni satır aynı sayfaya yerleştirilir ve eski satırdan yeni satıra bir ctid zinciri çekilir. İndekslere dokunulmaz. Varsayılan fillfactor = 100 ayarı sayfayı tamamen doldurduğu için HOT güncellemeleri imkansız kılar. Tabloya fillfactor = 80 veya 85 tanımlamak, sayfa içinde nefes payı açarak HOT oranını %80'in üzerine çıkarır.
MySQL'de Sessiz Katil: History List Length (HLL) ve Uzun Transaction Tuzağı
MySQL InnoDB'de tablo şişmesi yaşanmasa da, sistemin yumuşak karnı Undo Log yönetimidir. InnoDB Purge Thread, aktif transaction'ların ihtiyaç duyabileceği hiçbir Undo kaydını silemez.
Bir geliştirici unutup açık bıraktığı bir konsol oturumunda BEGIN; dedikten sonra masadan kalkarsa veya saatler süren ağır bir analitik raporlama/yedekleme (mysqldump) çalıştırılırsa, o andan itibaren sistemde yapılan milyonlarca UPDATE/DELETE işleminin undo logları birikir. History List Length (HLL) yüz binleri aştığında, basit bir SELECT sorgusu bile eski satırı inşa etmek için binlerce undo bloğunu diskten okumak zorunda kalır ve sunucu I/O darboğazına girer.