Furkan KapukayaYazılım geliştirme
Backend, API ve Veritabanı3 dk okuma

Transaction ve ACID: Veritabanında Ya Hep Ya Hiç

Veritabanı transaction kavramı, ACID özellikleri, izolasyon seviyeleri, kirli okuma ve kayıp güncelleme sorunları, deadlock ve uygulama kodunda transaction kullanımı.

Bir siparişi kaydederken stoğu düşüyor, cari hesaba borç yazıyor ve fatura oluşturuyorsunuz. İkinci adımdan sonra elektrik kesilirse ne olur? Stok düşmüş ama sipariş yoktur. Transaction, bu tür yarım kalmış işlemleri imkânsız kılar: ya tüm adımlar gerçekleşir ya hiçbiri.

ACID

ÖzellikAnlamıÖrnek
Atomicity (Bütünlük)İşlem bölünmezHavalede para bir hesaptan çıkıp diğerine girmezse hiçbir şey olmaz
Consistency (Tutarlılık)Kurallar her zaman korunurStok negatife düşmez, yabancı anahtar bozulmaz
Isolation (Yalıtım)Eşzamanlı işlemler birbirini bozmazİki kasiyer aynı son ürünü satamaz
Durability (Kalıcılık)Onaylanan işlem kaybolmazSistem çökse bile kayıt yerindedir

Kodda transaction

EF Core'da tek bir SaveChanges çağrısı zaten bir transaction içinde çalışır. Birden fazla kaydetme adımı varsa açıkça transaction başlatılır:

await using var tx = await db.Database.BeginTransactionAsync();

siparis.Onayla();
urun.StokDus(siparis.Adet);
await db.SaveChangesAsync();

await cariServis.BorcYazAsync(siparis);   // aynı DbContext üzerinden
await db.SaveChangesAsync();

await tx.CommitAsync();   // hata olursa commit edilmez, tümü geri alınır

Eşzamanlılık sorunları

  • Kirli okuma: Henüz onaylanmamış bir değişikliği başka işlemin görmesi.
  • Tekrarlanamayan okuma: Aynı işlem içinde aynı satırı iki kez okuyunca farklı değer görmek.
  • Kayıp güncelleme: İki kullanıcı aynı kaydı açar, ikisi de kaydeder; ilkinin değişikliği kaybolur.

İzolasyon seviyeleri

Veritabanları, yalıtım ile performans arasında farklı dengeler sunar: Read Uncommitted, Read Committed, Repeatable Read, Serializable ve satır sürümlemeye dayalı Snapshot. SQL Server ve PostgreSQL'in varsayılanı Read Committed'dır ve çoğu iş uygulaması için uygundur. Daha yüksek seviyeler daha güvenlidir ama daha çok kilit ve bekleme demektir.

Kayıp güncellemeyi önlemek: İyimser eşzamanlılık

Her satıra bir sürüm alanı (rowversion) eklenir. Kaydederken "bu satır ben okuduğumdan beri değişti mi?" kontrol edilir; değiştiyse kullanıcıya uyarı verilir. EF Core bunu yerleşik destekler ve stok, bakiye gibi kritik alanlarda çok değerlidir.

Deadlock

İki işlem birbirinin kilitlediği kaynağı beklediğinde ortaya çıkar; veritabanı birini kurban seçip iptal eder. Azaltmak için:

  • Transaction'ları kısa tutun; içinde kullanıcı girişi, dosya işlemi veya dış API çağrısı beklemeyin.
  • Tablolara her yerde aynı sırayla erişin.
  • Doğru indekslerle kilitlenen satır sayısını azaltın.
  • Kurban seçilen işlemi güvenle tekrar deneyin (idempotency).

Dağıtık sistemlerde

Transaction tek bir veritabanı içinde geçerlidir. Veritabanı kaydı ile e-posta gönderimi veya başka bir servis çağrısını aynı transaction'a sokamazsınız. Bunun için "outbox" deseni kullanılır: mesaj önce aynı transaction içinde bir tabloya yazılır, sonra arka planda gönderilir. Bkz. mesaj kuyruğu.

Sık sorulan sorular

NoSQL veritabanlarında transaction var mı?

Birçok modern NoSQL veritabanı belirli kapsamlarda transaction destekler; ancak ilişkisel veritabanları kadar geniş değildir. Bkz. SQL ve NoSQL.

Her sorguyu transaction içine almalı mıyım?

Hayır. Yalnızca birlikte başarılı olması gereken birden fazla değişiklik varsa açık transaction gerekir.

Sonuç

Transaction'lar, verinin yarım kalmasını ve eşzamanlı işlemlerin birbirini bozmasını önler. Kısa, odaklı transaction'lar ve iyimser eşzamanlılık kontrolü; güvenilir bir iş uygulamasının görünmez temelidir.