2 puan yazan GN⁺ 2026-02-24 | 1 yorum | WhatsApp'ta paylaş
  • Transaction, veritabanında birden fazla işlemi tek bir atomik birim olarak yürütmek için kullanılan yapıdır; okuma, yazma, güncelleme ve silmeyi kapsar
  • MySQL ve Postgres, transaction'ları begin; ve commit; ile kontrol eder; başarısızlık veya hata durumunda değişiklikler rollback; ile geri alınır
  • Her iki veritabanı da tutarlı okuma (consistent read) garantisi verir; ancak Postgres çok sürümlü satır saklama (MVCC), MySQL ise undo log kullanır
  • Yalıtım seviyesi (isolation level), transaction'lar arasındaki veri etkileşimini kontrol eder ve Serializable'dan Read Uncommitted'a kadar dört seviyeye ayrılır
  • Postgres ve MySQL, eşzamanlı yazma çakışmalarını farklı şekillerde ele alır; Postgres iyimser doğrulama, MySQL ise satır düzeyi kilitleme (row-level locking) kullanır

Transaction'ın temel kavramı

  • Transaction, veritabanında birden fazla SQL işlemini tek bir atomik yürütme birimi olarak gruplandıran yapıdır
    • begin; ile başlar, commit; ile sona erer ve arada birden fazla sorgu çalıştırılabilir
    • commit; anında tüm değişiklikler tek seferde uygulanır
  • Beklenmedik arızalarda (güç kesintisi, disk hatası vb.) veya bilinçli iptal durumunda değişiklikler rollback; ile geri alınır
    • Postgres, kurtarma için WAL (Write-Ahead Log) desteği sunar
  • Transaction sırasında değiştirilen veriler yalıtılır ve diğer oturumlarda görünmez
    • rollback; durumunda tüm değişiklikler iptal edilir ve veritabanı ilk durumuna döner

Tutarlı okumalar (Consistent Reads)

  • Bir transaction, çalışırken dış değişikliklerden etkilenmeyen tutarlı bir veri görünümünü korumalıdır
  • MySQL ve Postgres bunu REPEATABLE READ modu ve üzerinde destekler, ancak uygulama biçimleri farklıdır
    • Postgres: Her satırın sürümünü çok sürümlü satır saklama (MVCC) ile yönetir
    • MySQL: Geçmiş sürümleri yeniden oluşturmak için undo log kullanır

Postgres'te çok sürümlü satır saklama

  • Bir satır her güncellendiğinde yeni bir sürüm oluşturulur; önceki sürüm xmax, yeni sürüm ise xmin ile transaction ID'sini kaydeder
  • Transaction commit edilmeden önce diğer oturumlar değişiklikleri göremez
  • Commit sonrasında yeni sürüm tüm veritabanına yansır
  • rollback; durumunda değişiklikler atılır ve orijinal veri korunur
  • Eski satır sürümleri VACUUM FULL komutuyla temizlenerek depolama alanı geri kazanılır

MySQL'in Undo Log'u

  • MySQL, satırı doğrudan üzerine yazar; ancak önceki değerleri undo log içinde kaydederek gerektiğinde geri yüklenmesini sağlar
  • Her satır meta veri olarak xid (son değiştiren transaction ID'si) ve ptr (undo log işaretçisi) taşır
  • Birden fazla transaction aynı anda çalıştığında, her transaction undo log üzerinden ihtiyaç duyduğu sürümü seçerek okur
  • Aynı satır için birden fazla undo log kaydı bulunabilir ve uygun sürüm transaction ID'sine göre seçilir

Yalıtım seviyeleri (Isolation Levels)

  • Transaction'lar arasındaki veri etkileşimini kontrol eden ayardır; Serializable → Repeatable Read → Read Committed → Read Uncommitted sırasıyla gevşer
  • Serializable: Tüm transaction'lar sanki sıralı çalışmış gibi davranır
  • Repeatable Read: Aynı sorgu yeniden çalıştırıldığında sonuç aynı kalır, ancak phantom read mümkündür
  • Read Committed: Başka transaction'ların commit edilmiş değişiklikleri okunabilir
  • Read Uncommitted: dirty read'e izin verir; en düşük koruma seviyesidir ama performansı yüksektir

Eşzamanlı yazmalar (Concurrent Writes)

  • İki transaction aynı satırı aynı anda değiştirdiğinde bunun nasıl ele alınacağı veritabanına göre değişir

MySQL: Satır düzeyi kilitleme (Row-level Locking)

  • Paylaşımlı kilit (S lock), birden fazla transaction'ın aynı anda okuma yapmasına izin verir
  • Özel kilit (X lock), yalnızca bir transaction'ın satırı değiştirmesine izin verir
  • SERIALIZABLE modunda her güncellemede X lock alınmalıdır ve çakışma durumunda deadlock oluşabilir
  • MySQL deadlock'u algılar ve transaction'lardan birini sonlandırır

Postgres: Serializable Snapshot Isolation

  • Postgres, satır kümeleri düzeyinde erişimi izlemek için predicate lock kullanır
    • Örnek: WHERE id BETWEEN 10 AND 20 koşulu için alınan kilit
  • Gerçek erişimi engellemez; bunun yerine çakışmayı tespit eder ve ihlal durumunda transaction'ı sonlandırır
  • İyimser çakışma çözümü (optimistic conflict resolution) ile deadlock'tan kaçınır
  • MySQL'de olduğu gibi, çakışma halinde transaction'lardan biri sonlandırılır ve uygulamanın yeniden deneme mantığını uygulaması gerekir

Sonuç

  • Transaction, veritabanının temel bileşenlerinden biridir ve atomiklik, tutarlılık, yalıtım ve kalıcılığı (ACID) garanti eder
  • Postgres ve MySQL aynı hedefe farklı iç yapılarla ulaşır
  • Dört yalıtım seviyesini ve transaction çalışma mantığını anlamak, veritabanını daha güvenli ve istikrarlı işletmeyi sağlar

1 yorum

 
GN⁺ 2026-02-24
Hacker News görüşleri
  • Bu yazı bana biraz yetersiz geldi.
    İzolasyon seviyelerini SQL standardında tanımlanan fenomenler (phenomena) üzerinden açıklamak yerine, serileştirilebilirlik (serializability) kavramından başlamanın daha sezgisel olduğunu düşünüyorum.
    Serileştirilebilirlik, thread safety'nin genelleştirilmiş bir hali olarak görülebilir; bu garanti kaybolduğunda, yürütme sırasına göre sonucun değiştiği hatalar ortaya çıkar.
    Veritabanındaki farklı izolasyon seviyeleri, bu garantinin gevşetilmiş biçimlerinden ibarettir ve kullanıcının başka yollarla bu garantiyi sağlaması gerekir.
    Fenomenler, yalnızca serileştirilemeyen durumları görselleştirmeye yarayan araçlardır; serileştirilebilirlikle doğrudan bağlantılı değildir.
    Örneğin Kubernetes kümesi de iyi tasarlanmış controller'lar kullanılırsa serileştirilebilir şekilde çalışabilir.

    • Ben yazarıyım. Güzel geri bildirim için teşekkürler.
      Transaction, izolasyon seviyeleri ve MVCC'yi birden fazla DB arasında karşılaştırmaları da kapsayacak şekilde tek seferde ele almak oldukça kapsamlı bir iş.
      Teknik derinlik, erişilebilirlik ve yazının uzunluğu arasında denge kurmaya çalıştım.
    • Jepsen: MariaDB Galera Cluster analizi bağlantısını paylaşmış.
      Daha fazla gösterim ve alıntı olsa iyi olurdu görüşünde.
    • Çoğu RDBMS, gerektiğinde serileştirilebilir izolasyon sunar.
      Ancak gereksiz yere kullanıldığında transaction'lar arasındaki koordinasyon maliyeti artar, bu da eşzamanlılığı ve throughput'u düşürür.
    • O halde daha iyi bir açıklama önermesini söyleyen bir yanıt.
  • Transaction'ları copy-on-write dosya sistemi (btrfs, zfs) snapshot'ları gibi düşünmek mümkün, ama bunu Git branch'leriyle benzetmenin daha sezgisel olduğunu düşünüyorum.
    BEGIN branch oluşturmak, UPDATE commit atmak, ROLLBACK branch'i silmek, COMMIT ise git merge ile aynıdır.
    Çakışma olursa DB satır düzeyinde merge etmeye çalışır; başarısız olursa ayara göre rollback yapar ya da zorla merge eder.
    READ UNCOMMITTED hızlı merge'ü, SERIALIZABLE ise doğruluğu önceliklendirir.
    Böyle bir benzetme, birinin transaction kavramını "hah, tamam!" diye anlamasına yardımcı olabilir.

    • (Kısa yorum) Eşzamanlılığa (concurrency) işaret eden bir tepki.
  • Pek çok kişinin şaşırdığı nokta, Postgres ve MySQL'in varsayılan olarak serileştirilebilir modda değil, read committed modunda olduğudur.
    Performans farkı “biraz” değil, gerçekte çok daha büyüktür.
    read committed kullanıldığında lock yönetimine dikkat etmek gerekir ve UNIQUE kısıtı da yarış durumlarını önlemek için gereklidir.
    Yine de serileştirilebilir modun performans kaybını ve retry sorunlarını göze almaktansa bu yaklaşımı tercih ediyorum.
    Referans: PostgreSQL resmi dokümantasyonu

    • Modern MySQL ve MariaDB (InnoDB) varsayılan olarak repeatable read kullanır.
      MySQL dokümantasyonu, MariaDB dokümantasyonu bkz.
      MyISAM artık neredeyse hiç kullanılmıyor.
    • SERIALIZABLE'ın sorunu sadece performans değildir; çatışma·deadlock·timeout nedeniyle transaction başarısız olabilir.
      Uygulamanın bunu algılayıp bir retry stratejisine sahip olması gerekir.
    • Oracle ve SQL Server'ın varsayılanı da read committed'dır.
      Serileştirilebilir mod ders kitaplarında havalı görünür ama pratikte neredeyse hiç kullanılmaz.
  • Bugünlerde birçok veritabanı aracı, ACID'den çok gerçek zamanlı güncelleme paylaşımını önceliklendiriyor.
    Örneğin Airtable'da bir alanı düzenlediğinizde bu değişiklik ekip arkadaşınızın ekranına anında yansır, ancak transaction olmadığı için veri tutarsızlığı riski vardır.
    İlgili içerik için VisualDB blog yazısı bkz.

    • Rakibi eleştiriyormuş gibi yapıp aslında ürün tanıtımı yapıyor gibi göründüğünü söyleyen bir tepki.
  • PlanetScale blogunu okumak gerçekten çok keyifli.
    Görselleştirmelerde hangi araçları kullandıklarını merak ediyorum.

    • Ben yazarıyım. Teşekkürler!
      Görselleştirmeler js + gsap(https://gsap.com) ile hazırlandı.
  • Bu konuyla ilgileniyorsanız 『Designing Data-Intensive Applications』 kitabını güçlü biçimde tavsiye ederim.
    Sadece farklı izolasyon seviyelerini değil, ACID tanımındaki belirsizliği de ele alıyor.
    2. baskının yakında çıkacağını duymuştum.

  • Postgres gibi MVCC sistemlerindeki transaction'lar, copy-on-write dosya sistemlerinin snapshot'larına benzer.
    BEGIN anında verinin bir snapshot'ı alınır, UPDATE ise yalnızca kişisel kopyaya uygulanır.
    ROLLBACK olduğunda bu kopya atılır, COMMIT olduğunda yeni snapshot resmi sürüm haline gelir.
    Bu benzetme, birinin transaction kavramını net biçimde anlamasına yardımcı olabilir.
    Not: Git branch benzetmesi de yapılabilir.

    • Tam olarak doğru değil. DB, branching ve locking'i birlikte kullanır.
      SELECT'ten sonra UPDATE gibi durumlarda bir thread bloklanabilir.
      Bugün MySQL'de bunu tek bir sorguya dönüştürmenin mümkün olup olmadığını denemeyi planlıyorum.
  • Eskiden backend mülakatlarında transaction konusu sıkça sorulurdu.
    Herkes kullanmıştır ama anlama düzeyi deneyime göre değişir.
    Tüm izolasyon seviyelerini ezbere bilmese bile, farklı davrandıklarını biliyor olmak bile merak ve sistem anlayışı hakkında fikir verir.

    • Aynı isimdeki izolasyon seviyesi olsa bile davranış DB'ye göre değiştiğinden, durum bazında ayrıntılı davranışı kontrol etmek gerekir.
  • “phantom read” açıklaması yanlış anlaşılmaya açık olabilir.
    repeatable read'de mevcut satırların değeri değişmez ama yeni satırlar eklenebilir.
    Mevcut satırların değişmesi ya da silinmesi söz konusu olmadığından, bunun açıkça belirtilmesi gerekir.

  • “xmin/xmax ile ilgili değil” cümlesi bana eksik geldi.
    Commit sırasında görselleştirmenin tablo başlığını göstermesi de tuhaf.
    Aslında xmax/xmin, commit durumunu belirlemenin temel mekanizması değil mi?
    Alt transaction'lar da hesaba katılınca iş daha karmaşık hale geliyor.
    Yine de görselleştirme ve açıklamaları genel olarak keyifle okudum.

    • Ben de xmax/xmin kavramının eksik olmasına üzüldüm.
      İzolasyon seviyelerini anlamak için kritik bir unsur ama sanki ilgili bölüm atlanmış gibi hissettirdi.