- Konu sahibi
- #1
Transaction izolasyon seviyeleri neyi değiştirir?
Transaction izolasyon seviyesi, aynı anda çalışan işlemlerin birbirlerinin henüz kesinleşmemiş veya değişmekte olan verilerini ne ölçüde görebileceğini belirler. Daha güçlü izolasyon tutarlılık güvencelerini artırabilir; bekleme, çakışma ve yeniden deneme davranışları motora bağlıdır.
Bir transaction içindeki iki sorgu arasında başka bir transaction aynı satırı güncellerse sonuç, seçilen izolasyona ve veritabanının uygulamasına göre değişir. Bu nedenle izolasyon yalnızca “okuma güvenliği” ayarı değildir; bekleme süresini, çakışma davranışını ve uygulamanın hata yönetimini de etkiler.
Hangi tutarsızlıklar kontrol edilir?
Kirli okuma: Bir transaction, başka bir transaction tarafından yazılmış ancak henüz
COMMIT edilmemiş veriyi okur. Yazma işlemi geri alınırsa ilk transaction gerçekte kalıcı olmayan bir değer görmüş olur.Tekrar edilemeyen okuma: Aynı transaction içinde aynı satır iki kez okunur, fakat arada başka bir transaction bu satırı kesinleştirerek değiştirir. İki sorgu farklı sonuç döndürür.
Phantom read: Bir koşula uyan satırlar iki kez sorgulanır; arada başka bir transaction yeni bir satır ekler veya mevcut satırı siler. İkinci sorgunun satır kümesi değişir.
Genel davranış aşağıdaki gibidir. Bu tablo, veritabanı motorlarının tüm ayrıntılarını değil, izolasyon seviyelerinin temel hedefini gösterir; aynı seviye farklı motorlarda kilit veya MVCC gibi farklı tekniklerle uygulanabilir.
Seviyelerin pratik etkisi
| Seviye | Genel olarak engellenen durum | Temel bedel | Uygun kullanım |
|---|---|---|---|
| READ UNCOMMITTED | Çok az kısıtlama | Kirli ve tutarsız okumalar mümkün | Tutarlılığın kritik olmadığı yaklaşık okumalar |
| READ COMMITTED | Kirli okumalar | Aynı transaction içindeki sorgular farklı sonuç verebilir | Kısa ve bağımsız iş mantığı işlemleri |
| REPEATABLE READ | Tekrar edilemeyen okumalar; motor ek güvenceler verebilir | Daha fazla bekleme veya çakışma | Aynı satırları transaction boyunca tutarlı kullanma |
| SERIALIZABLE | Başarılı transaction’lar bir seri çalışmayla eşdeğer sonuç verir | Bekleme, deadlock veya retry ihtimali | Kritik doğrulama ve çakışmayı kabul etmeyen işlemler |
SQL standart tablosu bir ürünün bütün davranışı değildir. PostgreSQL READ UNCOMMITTED seviyesini READ COMMITTED gibi uygular; PostgreSQL REPEATABLE READ phantom okumayı da önler, fakat serialization anomalileri kalabilir. InnoDB REPEATABLE READ içinde kilitsiz snapshot okuması ile kilitleyen okumanın görünümü aynı varsayılmamalıdır. Birçok sistemde snapshot veya MVCC tabanlı davranış bulunur. Bu yaklaşımda transaction, kilit beklemek yerine verinin uygun bir sürümünü okuyabilir. Ancak bunun hangi izolasyon seviyesine karşılık geldiği ve yazma çakışmalarının nasıl bildirildiği veritabanı motoruna bağlıdır; yalnızca seviye adını görerek aynı davranışı varsaymayın.
Somut örnek: stok düşme işlemi
Aşağıdaki ilk örnek güvenli uygulama önerisi değil, hatalı oku-sonra-yaz örüntüsüdür. products tablosunda id ve stock tamsayı alanları bulunduğunu varsayar. Stok 1 iken iki işlem ayrı bağlantıda bu deseni yürütürse sorun oluşabilir:
Kod:
START TRANSACTION;
SELECT stock FROM products WHERE id = 10;
-- stock > 0 ise
UPDATE products
SET stock = stock - 1
WHERE id = 10;
COMMIT;
İki transaction da önce 1 değerini okuyup sonra azaltırsa, uygulama düzeyinde iki satışın da başarılı sanılması mümkündür. İzolasyon seviyesi tek başına her zaman yeterli çözüm değildir; güncellemenin koşullu yapılması veya satırın kilitlenmesi gerekebilir. Örneğin mantık şu şekilde tek SQL işlemiyle ifade edilebilir:
Kod:
UPDATE products
SET stock = stock - 1
WHERE id = 10 AND stock > 0;
Ardından etkilenen satır sayısı kontrol edilir. Sonuç 1 ise stok düşmüştür; 0 ise stok yetersizdir veya ürün bulunamamıştır. Gerçek veritabanınızın döndürdüğü etkilenen satır sayısı API'sini kullanın. Transaction birden fazla tabloyu güncelliyorsa tüm adımları aynı transaction içinde kesinleştirin.
Seviye seçme ve uygulama adımları
- Önce iş kuralındaki tutarlılık ihtiyacını belirleyin. Raporlama ile ödeme, stok, bakiye veya kota işlemlerini aynı seviyede değerlendirmeyin.
- Kullanılan veritabanının varsayılan izolasyonunu ve desteklediği seviyelerin gerçek davranışını kontrol edin. Seviye adları aynı olsa bile MVCC, kilitlenme ve phantom read davranışı değişebilir.
- İzolasyonu mümkünse yalnızca ihtiyaç duyan transaction için ayarlayın; tüm bağlantı havuzuna rastgele en yüksek seviyeyi uygulamayın.
- Transaction kapsamını kısa tutun. Kullanıcıdan yanıt beklemek, ağ çağrısı yapmak veya uzun hesaplama yürütmek transaction açıkken yapılmamalıdır.
- Çakışma, deadlock, serialization failure ve lock timeout sonuçlarını uygulamada hata olarak ele alıp güvenli işlemlerde yeniden deneme politikası uygulayın.
- İki ayrı bağlantıyla aynı anda okuma ve yazma senaryolarını test edin. Yalnızca tek bağlantıda yapılan test, izolasyon sorunlarını göstermez.
Sık yapılan hatalar
İzolasyon seviyesini yükseltmenin tüm yarış koşullarını otomatik olarak çözeceğini sanmak yaygın bir hatadır. “Oku, sonra hesapla, sonra yaz” mantığı; koşullu güncelleme, uygun kilit veya veritabanının çakışma kontrolü olmadan yine hatalı olabilir.
Bir diğer hata,
COMMIT sonrasında aynı transaction görünümünün sürdüğünü varsaymaktır. Yeni transaction yeni bir görünüm alabilir ve sorguların sonucu değişebilir. Ayrıca autocommit açıkken her SQL cümlesinin ayrı transaction olabileceği unutulmamalıdır.Son olarak,
READ UNCOMMITTED seviyesini yalnızca sorgu hızlı olsun diye seçmek doğru değildir. Yanlış bakiye, stok veya rapor sonucu iş kuralını bozuyorsa daha düşük izolasyonun kazancı, düzeltme maliyetinden küçük kalabilir.