İki kullanıcının aynı anda aynı veriyi değiştirmesi, yazılımın en sessiz hata sınıfıdır: hata mesajı vermez, log'a düşmez; sadece veri yanlış olur. Veritabanının bize sunduğu kalkan izolasyon seviyeleridir; ama çoğu ekip varsayılanı hiç sorgulamadan yaşar ve gün olur, stok eksiği, çift bakiye, tek koltuğa satılmış iki bileş çıkar. Anomalilerin adını bilmek, savunmanın yarısıdır.
Dört seviye, dört tehlike
SQL standardı dört seviye tanımlar; her yukarı seviye, bir öncekinin engellemediği anomaliyi engeller:
READ UNCOMMITTED -> kirli okuma: yarım kalan işlem görür
READ COMMITTED -> tekrarlanamayan okuma: aynı sorgu iki farklı sonuç
REPEATABLE READ -> hayalet satır: aynı arama yeni satır görür
SERIALIZABLE -> sıralı çalışır gibi; hepsi engellenir
Kayıp güncelleme ise bunlardan bağımsızdır: iki işlem aynı değeri okur, kendi hesabını yapar, yazar; biri diğerinin yazısını siler. Tüm seviyelerde kayıp güncelleme mümkündür, çünkü okuma ile yazma arasında dünya değişmiştir.
-- Yanlış: oku, hesapla, yaz (kayıp güncelleme riski)
SELECT stok FROM urunler WHERE id = 42;
UPDATE urunler SET stok = 37 WHERE id = 42; -- araya biri girdiyse kaybettiniz
-- Doğru: yazmayı atomik bırak
UPDATE urunler SET stok = stok - 1
WHERE id = 42 AND stok > 0;
İkinci formda artırma ve azaltma tek komuttur; veritabanı satırı kilitler, iki işlem aynı anda aynı hesabı yapamaz. Kayıp güncellemenin panzehiri çoğu zaman daha yüksek izolasyon değil, daha iyi yazılmış SQL'dir.
Varsayılan yetmezse ne yapmalı
Çoğu veritabanının varsayılanı READ COMMITTED'dir ve çoğu iş için yeterlidir. Ama rapor tutarlılığı gerektiren işler vardır: ödeme ekranı, bakiye toplamı, koltuk seçimi. Burada üç yol vardır: işlemi REPEATABLE READ ya da SERIALIZABLE'da açmak, satırı SELECT FOR UPDATE ile baştan kilitlemek ya da iyimser kilitleme ile sürüm kolonu üzerinden kontrol etmek.
-- İyimser kilitleme: okurken sürüm al, yazarken doğrula
UPDATE bakiyeler SET tutar = 750, surum = surum + 1
WHERE kullanici_id = 8 AND surum = 3;
-- etkilenen satır 0 ise arada biri yazdı; tekrar dene
Sonuç olarak izolasyon, bir ayar değil bir mühendislik kararıdır: verinin değerine, çakışma olasılığına ve işin kritikliğine göre seviye seçin; kritik akışlarda atomik SQL yazın ve çakışmayı erken tespit edin.
Seçim yaparken üç soruyu sıraya koyun. Çakışan yazma olasılığı düşük mü? Düşükse READ COMMITTED ile kalın; nadir çakışmayı iyimser kilitlemeyle yakalamak, her okumayı kilitlemenin bedelinden ucuza gelir. İşlem uzun mudur? Uzun işlemleri kısaltmak, seviyeyi yükseltmekten önce gelir; kilit, tutulduğu süre kadar tehlikedir. Anomali kabul edilebilir mi? Raporlamada birkaç saniyelik tutarsızlık kimseyi zarara sokmazken, bakiye işleminde tek satır fark dava demektir; seviyeyi akış bazında belirlemek, tablo bazında değil, bu yüzden mantıklıdır.
Son bir uyarı: seviyeyi yükselttiğinizde yalnız hata mesajlarını değil, ölçümleri de izleyin. Kilitleme beklemeleri, kilitlenme sayaçları ve yeniden deneme oranları, kararınızın bedelini anlatır; bu sayılar görünmeden yapılan sıkılaştırma, tahmin demektir. Anomali isimlerini ekipçe ortak dil haline getirmek, "bir ara stoklar yanlış düşüyor" şikayetini, adı konulmuş, testi yazılmış bir bug'a dönüştürür. Bu, yazılım ekiplerinin çoğu hata sınıfına veremediği en büyük lüstür.
Okur Yorumları (0)