TRANSACTION ISOLATION LEVELS NEDİR?

Dört basamaklı izolasyon merdiveni Read Uncommitted Read Committed Repeatable Read Serializable hiyerarşi

Bir banka uygulamasında hesap bakiyesini iki kullanıcı aynı anda güncellerken hangi yolu seçersiniz: en hızlı ama tutarsız okumaya izin veren Read Uncommitted mı, yoksa her şeyi sıraya dizen ama bekletmeleri patlatan Serializable mı? Bu seçim sadece teorik bir tercih değil; sipariş çakışmasından raporun yanlış toplam vermesine kadar her senaryoyu doğrudan etkiler. İki uç arasında veritabanlarının sunduğu dört izolasyon seviyesi vardır ve doğru olanı seçmek için her birinin neyi engelleyip neyi engellemediğini bilmek gerekir.

Transaction Isolation Kavramı ve ACID İçindeki Yeri

İlişkisel veritabanı dünyasında ACID prensiplerinin "I" harfi Isolation'ı temsil eder. İzolasyon, eş zamanlı çalışan transaction'ların birbirinin ara sonuçlarını ne ölçüde göreceğini tanımlar. Tam izolasyon ideal görünür ama pratikte performans cezası ağırdır; bu yüzden SQL standardı dört farklı seviye tanımlar ve geliştiriciye trade-off'u bırakır.

Eş zamanlılık problemleri üç ana başlıkta toplanır:

  • Dirty Read: Henüz commit edilmemiş bir değişikliği başka bir transaction'ın okuması.
  • Non-Repeatable Read: Aynı transaction içinde aynı satırın iki kez okunduğunda farklı değer dönmesi.
  • Phantom Read: Aynı sorgunun ikinci kez çalıştırıldığında araya yeni satırların girmiş olması.

Her izolasyon seviyesi bu üç anomaliden hangilerini engellediğine göre konumlanır. Daha fazla bilgi için resmi belgeleri başvurulabilir.

Read Uncommitted: En Düşük Seviye

Read Uncommitted, transaction'ın diğer transaction'ların commit etmediği değişiklikleri bile görmesine izin verir. Kilit alınmadığı için en hızlı seviyedir, ancak dirty read tamamen serbesttir. Bir kullanıcı bakiyeyi 1000'den 500'e düşürürken rollback ederse, paralel transaction o 500'ü gerçekmiş gibi raporlayabilir.

Pratikte yalnızca finansal hassasiyet gerektirmeyen, "yaklaşık değer yeterli" senaryolarda kullanılır: anlık dashboard sayaçları, hızlı log taramaları gibi durumlar tipik adaylardır. Üretim verisinde varsayılan olarak seçmek tehlikelidir.

Read Committed: SQL Server ve PostgreSQL'in Varsayılanı

Bu seviyede transaction sadece commit edilmiş veriyi okur, dirty read kapanır. Ancak aynı sorguyu iki kez çalıştırırsanız arada başka bir transaction veriyi değiştirip commit etmişse farklı sonuç görebilirsiniz — yani non-repeatable read hâlâ mümkündür.

Çoğu OLTP uygulaması için makul bir denge sunar. SQL Server'da varsayılan davranıştır; PostgreSQL de bu seviyeyi varsayılan kabul eder. Lock süresi okuma anıyla sınırlı tutulduğundan throughput yüksek kalır.

Üç anomali Dirty Read Non-Repeatable Phantom Read seviye matrisi check ve x işaretleri ile

Repeatable Read: Satır Sabitlenir, Aralık Sabitlenmez

Repeatable Read, transaction süresince okunan satırların değişmeyeceğini garanti eder. Aynı SELECT id, balance FROM accounts WHERE id = 42 sorgusunu transaction boyunca kaç kez çalıştırırsanız çalıştırın, aynı satır aynı değeri döner. MySQL InnoDB'nin varsayılanıdır.

Buradaki incelik şudur: okuduğunuz mevcut satırlar kilitlenir ama aralık kilitlenmez. WHERE created_at > '2026-01-01' sorgunuza başka bir transaction yeni satır INSERT edip commit ederse, ikinci çağrıda o satırı da görürsünüz. Bu phantom read olarak adlandırılır ve raporlama mantığını sessizce bozabilir.

Serializable: En Yüksek Garanti, En Yüksek Maliyet

Serializable, transaction'ları sanki tek tek sıralı çalışmış gibi davranmaya zorlar. Aralık kilitleri (range lock) sayesinde phantom read da elenir. Sonuç: ACID açısından kusursuz bir izolasyon, ancak yüksek eş zamanlılıkta bekleme ve deadlock olasılığı belirgin biçimde artar.

Stok rezervasyonu, çift kayıt önleme veya muhasebe kapanışı gibi senaryolarda hâlâ ilk tercihtir. Performans cezasını dengelemek için transaction'ları olabildiğince kısa tutmak ve serializable'ı yalnızca gerçek tutarlılık ihtiyacı olan bloklarda kullanmak gerekir. Eş zamanlılığı yüksek sistemlerde sorgu planı ve indeks tasarımının önemini ayrıca anlamak için SQL performance ve query tuning eğitimi içeriğinden yararlanabilirsiniz.

Performans Trade-Off'u ve Seviye Seçimi

İzolasyon seviyesi yükseldikçe tutarlılık artar, throughput düşer. Karar verirken şu üç soruyu cevaplamak işe yarar:

  1. Bu transaction yanlış veri okursa iş kuralı kırılır mı, yoksa kullanıcı sadece eski değer mi görür?
  2. Çakışma olasılığı yüksek mi (aynı satıra çok sayıda paralel yazma)?
  3. Transaction ne kadar sürüyor — milisaniye mi, saniye mi?

Kısa, çakışması düşük ama tutarlılığı kritik olan işlemler Serializable'ı kaldırır. Uzun raporlama sorguları için snapshot isolation (PostgreSQL ve SQL Server'da mevcut) çoğu zaman daha iyi bir orta yoldur: MVCC üzerinden tutarlı bir okuma penceresi sunar, yazarları engellemez.

Pratik Tuzaklar

İzolasyon seviyesini yükselterek bir tutarlılık problemini "çözdüğünüzü" düşünmek yaygın hatadır. Çoğu zaman gerçek sorun, transaction sınırlarının yanlış çizilmiş olmasıdır: gereğinden geniş transaction, gereksiz uzun süre tutulan kilit, veya uygulama tarafında yapılması gereken kontrolün veritabanına yüklenmesi.

  • Her transaction için izolasyon seviyesi varsayım yapmadan açıkça belirtilmelidir.
  • ORM'lerin (Hibernate, Entity Framework) varsayılan seviyesi her zaman beklediğiniz olmayabilir.
  • Deadlock loglarını izleyin: seviye yükseltildikten sonra artışı normalleştirmeyin.
  • Snapshot isolation seçeneklerini değerlendirin; özellikle raporlama yüklerinde fark yaratır.
Performans hız göstergesi ile tutarlılık ağır kilit terazisi izolasyon seviyesi denge metaforu

Doğru izolasyon seviyesi tek bir "en iyi" cevap olarak gelmez; uygulamanın okuma/yazma karakterine, çakışma yoğunluğuna ve iş kuralının hata toleransına göre seçilir. Read Committed çoğu OLTP için yeterliyken, finansal kapanış ve rezervasyon senaryolarında Serializable veya Snapshot kaçınılmaz olur. SQL Server motorunda transaction davranışını ve plan etkilerini daha derin incelemek isteyenler SQL performans ve sorgu optimizasyonu içeriklerini inceleyebilirsiniz.