Transaction, ACID ve Isolation

Para transferinin neden tek bir transaction olması gerektiğini; ACID, anomali, lock ve isolation seviyeleriyle öğrenin.

A hesabından para düşüp B hesabına ekleme sırasında sistem çökerse para kaybolabilir. İki SQL komutunun tek iş sonucu olarak ele alınması gerekir. Transaction bu sınırı kurar.

Transaction komutları

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

BEGIN transaction’ı başlatır. UPDATE satırları değiştirir. COMMIT bütün değişiklikleri kalıcı yapar. Bir hata varsa ROLLBACK transaction içindeki değişiklikleri geri alır. Bakiye kontrolü ve değişiklik aynı transaction sınırında olmalıdır.

ACID ne demek?

  • Atomicity: Ya bütün adımlar olur ya hiçbiri olmaz.
  • Consistency: Tanımlı constraint ve kurallar korunur.
  • Isolation: Eşzamanlı transaction’lar ara durumları kontrolsüz görmez.
  • Durability: Commit edilen sonuç çökme sonrasında korunur.

Consistency, veritabanının bütün iş kurallarını kendiliğinden bilmesi değildir. Constraint, veritabanının yazma sırasında zorunlu tuttuğu kuraldır. CHECK (balance >= 0) negatif bakiyeyi, foreign key var olmayan ilişkili kaydı engeller; uygulama doğrulamaları daha geniş iş kurallarını ifade eder.

Isolation anomalileri

Dirty read commit edilmemiş veriyi okumaktır. Non-repeatable read aynı satırın transaction içinde değişmiş görünmesidir. Phantom read aynı sorgunun yeni veya eksik satırlar görmesidir. Lost update iki işlemin birbirinin değişikliğini ezmesidir.

READ COMMITTED birçok veritabanında iyi başlangıçtır fakat bütün anomalileri engellemez. REPEATABLE READ aynı satır okumalarını güçlendirir. SERIALIZABLE işlemler seri çalışmış gibi sonuç hedefler; çakışmada transaction iptal edilip retry gerekebilir.

SELECT ... FOR UPDATE seçilen satırları kilitleyerek başka yazarı bekletir. Optimistic locking ise version sütununu karşılaştırır ve çakışmayı hata olarak bildirir. Sık çakışmada lock, seyrek çakışmada optimistic yöntem uygun olabilir.

Production kontrolü

  • Transaction’ı kısa tutun; içinde uzak API çağrısı yapmayın.
  • Deadlock hatalarını tanıyıp sınırlı retry uygulayın. İstemcilerin aynı anda tekrar çakışmasını önlemek için bekleme süresine küçük rastgele fark eklemeye jitter denir.
  • Retry edilecek operasyonu idempotent tasarlayın.
  • Isolation seviyesini varsaymayın, kullanılan veritabanında doğrulayın.
  • Finansal hareketleri yalnızca balance ile değil, her borç ve alacak hareketini ayrı satırda saklayan değişmez ledger (hesap defteri) kayıtlarıyla izleyin.