Locking (Concurrency Control)
Concurrency Control, birden fazla işlemin aynı anda veriyi okumasına ve değiştirmesine izin verirken veritabanı tutarlılığını koruyan DBMS mekanizmasıdır.
Bir veritabanında saniyede binlerce:
- Read (okuma)
- Write (yazma)
işlemi gerçekleşir. Eğer bu işlemler kontrol edilmezse race condition ortaya çıkar.
Concurrency Problemleri
1. Lost Update
İki işlem aynı veriyi okur ve günceller. Son kaydeden, önceki değişikliği fark etmeden ezer.
Örnek:
Stok = 10 Ali 1 satıyor → 9 olacak Veli 1 satıyor → 9 olacak
Ali kaydeder → 9 Veli kaydeder → 9
Gerçek sonuç 8 olmalıydı. Bir güncelleme kayboldu.
2. Double Spend (Çift Harcama)
Check ve Act arasındaki zaman boşluğundan kaynaklanır.
Senaryo:
Bakiye = 100 Aynı anda iki ATM’den 100 çekiliyor.
Her iki işlem de bakiyeyi 100 olarak görür. İkisi de parayı verir.
Sonuç: Bakiye -100
3. Inconsistent Analysis
Bir işlem veri üzerinde hesaplama yaparken başka bir işlem verinin bir kısmını değiştirir ve sonuç tutarsız olur.
Concurrency Çözüm Yöntemleri
Bu problemleri çözmek için üç temel yaklaşım vardır:
- Pessimistic Locking
- Optimistic Locking
- Atomic Update
1. Pessimistic Concurrency
Mantık: Çakışma olacak, veriyi baştan kilitle.
Veri okunduğu anda kilitlenir.
SELECT *
FROM products
WHERE id = 1
FOR UPDATE;
Bu satır başka bir işlem tarafından:
- Okunamaz
- Güncellenemez
Transaction bitene kadar bekletilir.
Avantaj
- Veri güvenliği maksimumdur.
- Double spend gibi kritik senaryolarda güvenlidir.
Dezavantaj
- Diğer işlemler bekler.
- Performans düşer.
- Deadlock riski vardır.
Deadlock Örneği
Ali → Veli para transferi Veli → Ali para transferi
Ali, Ali hesabını kilitler sonra Veli’yi bekler. Veli, Veli hesabını kilitler sonra Ali’yi bekler.
İki işlem birbirini bekler. Veritabanı birini “victim” seçer ve rollback yapar.
Deadlock genellikle kilitlerin farklı sırayla alınmasından kaynaklanır.
2. Optimistic Concurrency
Mantık: Herkes işlemini yapsın, kaydederken kontrol edelim.
Version kolonu kullanılır.
UPDATE products
SET stock = stock - 1,
version = version + 1
WHERE id = 1 AND version = 5;
Eğer version değişmişse:
- 0 satır etkilenir
- Çakışma anlaşılır
- İşlem iptal edilir
Avantaj
- Çok hızlıdır.
- İşlemler birbirini beklemez.
- Deadlock yoktur.
Dezavantaj
- Çakışma olursa işlem tekrar edilmelidir.
Kullanım Alanı
- Profil güncelleme
- Ürün düzenleme
- Kritik olmayan veriler
3. Atomic Update
Check ve update’i tek SQL içinde yapmak.
const [updatedRows] = await Stock.update(
{
quantity: sequelize.literal('quantity - 1')
},
{
where: {
productId: 1,
quantity: { [Op.gt]: 0 }
}
}
);
if (updatedRows === 0) {
throw new Error("Stok bitti");
}
Burada:
- quantity > 0 kontrolü
- quantity düşürme
tek adımda yapılır.
Flash sale gibi yüksek trafikli sistemlerde idealdir.
Lock Türleri
Shared Lock (S)
- Sadece okuma izni verir.
- Birden fazla işlem paylaşabilir.
Exclusive Lock (X)
- Okuma ve yazma yapabilir.
- Başka işlem erişemez.
Hangi Problemi Nasıl Çözeriz?
| Problem | Çözüm | Neden |
|---|---|---|
| Lost Update | Optimistic Locking | Performans kaybı olmadan çakışma yakalanır |
| Double Spend | Pessimistic Locking | Para hatası kabul edilemez |
| Stok Hatası | Atomic Update | Yüksek trafikte hızlı çözüm |
| Deadlock | Lock Ordering | Kilitleri aynı sırayla al |
Mimari ve Performans Notları
- Transaction içinde mümkün olduğunca az satır kilitle.
- Kilitliyken dış API çağrısı yapma.
- Isolation level’ı global değiştirme.
- Çoğu projede Optimistic Locking yeterlidir.
- Kritik finansal işlemlerde Pessimistic Lock kullan.
Isolation level tüm transaction’ı etkiler. Locking ise sadece ilgili satırı etkiler.