TRANSACTION ISOLATION LEVELS NEDİR?

Veri Akademi7 dk okuma
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.

1. 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.

2. 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.

3. 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

4. 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.

5. 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.

6. 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.

7. 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.

Sıkça Sorulan Sorular

Hangi izolasyon seviyesi varsayılan olarak en çok kullanılır?

SQL Server ve PostgreSQL'de varsayılan Read Committed, MySQL InnoDB'de ise Repeatable Read'dir. Uygulamanın hangi veritabanında çalıştığını bilmeden varsayılan davranış üzerine kod yazmak hatalı sonuçlara yol açabilir; bu nedenle her transaction için izolasyon seviyesinin açıkça belirtilmesi önerilir.

Dirty read ile non-repeatable read arasındaki temel fark nedir?

Dirty read henüz commit edilmemiş veriyi okumayı ifade eder ve rollback durumunda mantıksal olarak hiç var olmamış değeri görmüş olursunuz. Non-repeatable read ise commit edilmiş veriyi okur, fakat aynı transaction içinde ikinci okumada başka bir commit nedeniyle değer değişmiştir. Birincisi tutarlılığı, ikincisi tekrarlanabilirliği bozar.

Phantom read'i sadece Serializable mı engeller?

Klasik SQL standardına göre evet, phantom read'i tam olarak yalnızca Serializable engeller. Ancak MySQL InnoDB Repeatable Read seviyesinde next-key lock kullanarak phantom okumayı büyük ölçüde önler. PostgreSQL ise Serializable Snapshot Isolation (SSI) ile phantom durumunu MVCC üzerinden engelleyen farklı bir model uygular.

Snapshot isolation Serializable'a göre nasıl bir avantaj sunar?

Snapshot isolation MVCC üzerine kuruludur ve okuyucuları yazarlardan, yazarları okuyuculardan engellemez. Her transaction kendi başlangıç anındaki tutarlı veri görüntüsünü görür. Raporlama gibi uzun okuma yüklerinde Serializable'ın kilit maliyetini ödemeden tutarlı sonuç sağlar; ancak write skew gibi bazı anomalilere karşı dikkat gerektirir.

İzolasyon seviyesini yükseltmek deadlock riskini neden artırır?

Daha yüksek seviye, daha fazla satır ve aralık üzerinde daha uzun süre kilit tutmak demektir. Bu da iki transaction'ın birbirinin beklediği kaynağı tutma olasılığını yükseltir. Özellikle Serializable seviyesinde range lock'lar devreye girdiğinden, daha önce çakışmayan sorgular bile birbirini bekler hâle gelebilir ve deadlock sıklığı artar.

Bir transaction içinde izolasyon seviyesini değiştirebilir miyim?

Çoğu veritabanı motoru, izolasyon seviyesinin transaction başlamadan önce ayarlanmasını ister. SQL Server'da SET TRANSACTION ISOLATION LEVEL komutu sonraki transaction'lara uygulanır; aktif bir transaction içinde değiştirme genellikle desteklenmez. Doğru yaklaşım, işin gereksinimini bilerek transaction'ı doğru seviyede başlatmaktır.

Read Uncommitted production ortamında hiç kullanılmamalı mı?

Genel kural olarak kritik veri okumalarında kaçınılmalıdır. Yine de bazı yöneticilik sorgularında, örneğin canlı sistemi etkilemeden yaklaşık satır sayısı almak ya da büyük tabloda lock almadan keşif yapmak için NOLOCK ipucuyla kullanıldığı görülür. Sonucun yanlış çıkabileceği bilinerek uygulanmalıdır.

ORM kullanırken izolasyon seviyesini nasıl kontrol edebilirim?

Hibernate, Entity Framework gibi ORM'ler transaction başlatırken motor varsayılanını alır. Bağlantı string'inde, transaction scope tanımında veya framework'e özel attribute/anotasyonlarla seviye açıkça belirtilebilir. Uygulamanın kritik akışlarında varsayılana güvenmek yerine seviyenin loglanması ve test edilmesi yanlış sürprizleri önler.