“Concurrency bugs aren’t caused by fast systems – they’re caused by systems that assume they’re the only ones running.”
Önemli Çıkarımlar
- Veritabanı güncellemelerindeki eş zamanlılık sorunlarının neden veri bozulmasına neden olduğunu öğrenin.
- Race condition’ları basit gerçek dünya örnekleriyle anlayın.
- Optimistic ve Pessimistic Locking arasındaki farkı öğrenin.
- Her bir kilitleme stratejisinin ne zaman kullanılacağını bilin.
- Her iki tekniği de Laravel’de uygulayın.
- MySQL ve PostgreSQL davranışlarını karşılaştırın.
- Deadlock ve kaybolmuş güncellemelerden kaçının.
- Üretim en iyi uygulamalarını öğrenin.
İçindekiler
- Veritabanı Çatışmaları Neden Olur
- Race Condition’ları Anlama
- Veritabanı Kilitlemesi Nedir?
- Veritabanı Kilitleme Türleri
- Optimistic Locking
- Optimistic Locking Nasıl Çalışır
- Optimistic Locking Örneği
- Laravel Uygulaması
- Pessimistic Locking
- Pessimistic Locking Nasıl Çalışır
- Laravel Uygulaması
- Shared Lock vs Exclusive Lock
- Veritabanı İşlem İzolasyon Seviyeleri
- Deadlocks
- Performans Karşılaştırması
- Gerçek Dünya Örnekleri
- Hangisini Seçmelisiniz?
- Yaygın Hatalar
- İlginç Bilgiler
- Sıkça Sorulan Sorular
- Sonuç
Veritabanı Çatışmaları Neden Olur
Problem
Bir bankada hesabınızda
Balance = $1000
İki kullanıcı eş zamanlı olarak para çekmeye çalışıyor.
User A Withdraws $200
User B Withdraws $300
Her iki istek tam olarak aynı anda geldi.
Her ikisi de
Balance = $1000
User A yazıyor
800
User B yazıyor
700
Son bakiye
700
Beklenen
500
Para sihirli bir şekilde ortaya çıktı.
Bu bir Race Condition olarak adlandırılır.
Başka Bir Örnekte
Diyelim ki bir e-ticaret web sitesinde
1 iPhone left
İki müşteri tıklıyor
Buy Now
tam olarak aynı anda.
Kilitleme olmadan
Müşteri A satın alır.
Müşteri B de satın alır.
Şimdi envanter
-1
Bunun Sebebi Nedir?
Bir veritabanı işlemi genellikle
Read Data
↓
Process Data
↓
Update Data
İki kullanıcı bu sırayı eş zamanlı olarak gerçekleştirirse,
her ikisi de aynı eski değeri okur.
Race Condition’ları Anlama
Time →
User A
Read Balance =1000
------------------------
User B
Read Balance =1000
------------------------
User A
Write 800
------------------------
User B
Write 700
User A’nın güncellemesi kaybolur.
Bu Kaybolmuş Güncelleme Sorunu olarak adlandırılır.
Veritabanı Kilitlemesi Nedir?
Veritabanı kilitlemesi, birden fazla işlemin aynı veriyi çelişkili şekillerde değiştirmesini önleyen bir mekanizmadır.
Bunu bir toplantı odası olarak düşünün.
Eğer biri içerdeyse,
diğerleri beklemeli veya
oda değiştiyse kontrol etmelidir.
Veritabanı Kilitleme Türleri
“Bir işlem bir çalışma birimini korur; bir kilitleme stratejisi paylaşılan verinin bütünlüğünü korur.”
İki ana strateji vardır.
Optimistic Locking
Pessimistic Locking
Optimistic Locking
Optimistic locking, Çatışmaların nadir olduğunu varsayar.
Satırları kilitlemek yerine,
herkes okuyup değiştirebilir.
Kayıt kaydetmeden önce,
uygulama
“Biri bu kaydı zaten değiştirdi mi?” kontrol eder.
Eğer evet ise
Güncelleme başarısız olur.
Gerçek Hayat Örneği
Bir Google Dokümanını düzenlemeyi hayal edin.
İki kişi aynı belgeyi açar.
Siz önce kaydedersiniz.
İkinci kullanıcı kaydederken,
Google şöyle der:
This document has changed.
Please reload.
İşte bu optimistic locking.
Optimistic Locking Nasıl Çalışır
Genellikle sürüm veya updated_at ile yapılır.
Örnek tablo:
User A okurVersion =5User B okurVersion =5User A güncellerWHERE version =5Veritabanı değişiklikleriversion=6User B denerWHERE version=5No rows affected.
Çatışma tespit edildi.
Optimistic Locking Örneği
Örnek:
UPDATE products
SET stock = 5,
version = version +1
WHERE
id=1
AND version=5;
EğerAffected Rows =0olursa
Birisi değiştirdi.
Laravel Uygulaması
$product = Product::find(1);
$currentVersion = $product->version;
$updated = Product::where('id', 1)
->where('version', $currentVersion)
->update([
'stock' => 5,
'version' => $currentVersion + 1,
]);
if (! $updated) {
throw new Exception('Kayıt başka bir kullanıcı tarafından değiştirilmiş.');
}
Avantajları
- Çok hızlı
- Bekleme yok
- Harika ölçeklenebilirlik
- Yüksek throughput
Aşırmalıkları
- Güncelleme başarısız olabilir
- Kullanıcı tekrar deneyebilir
- Daha fazla uygulama mantığı gerektirir
Pessimistic Locking
Pessimistic locking, çatışmaların olası olduğu varsayımını taşır.
Güncellemeden önce,
veritabanı satırı kilitler.
Başka hiç kimse bunu değiştiremez.
Örnek
ATM’den çekim:Balance =1000User A işlem başlatır
Veritabanı satırı kilitlenir.
User B dener
Bekle...
User A taahhüt eder.
Ancak,bundan sonra User B ilerleyebilir.
Zaman ÇizelgesiUser A
Lock Row
↓
Update
↓
Commit
↓
Aç
User B
Bekle…
↓
Lock
↓
Update
↓
Commit
Pessimistic Locking Nasıl Çalışır
BEGIN;
SELECT *
FROM accounts
WHERE id=1
FOR UPDATE;
UPDATE accounts
SET balance = balance -200;
COMMIT;
Laravel Uygulaması
DB::transaction(function () {Laravel, otomatik olarak
$account = Account::where('id', 1)
->lockForUpdate()
->first();
$account->balance -= 200;
$account->save();
});SELECT ...üretir.
FOR UPDATE
Shared Lock vs Exclusive Lock
Shared Lock
Okumaya izin verir:Read
Read
Read
Ama güncelleme yoktur.
Laravel’de:DB::table('users')
->sharedLock()
->get();
SQL’de SELECT *(MySQL) veya FOR SHARE (PostgreSQL).
FROM users
LOCK IN SHARE MODE;
Exclusive Lock
Okuma ❌
Yazma ❌
Silme ❌
Sadece kilitleme işlemi devam eder.
Veritabanı İşlem İzolasyon Seviyeleri
Kilitleme ile etkileşimde bulunan önemli bir kavramdır. Farklı izolasyon seviyeleri, eş zamanlı işlemlerin neyi görebileceğini ve nasıl etkileşime girdiğini kontrol eder.
Davranış, veritabanı motoruna bağlıdır. Örneğin, MySQL’in InnoDB’si, phantom okunmalarını azaltmak için next-key kilitleme kullanır.
– Dirty Read: Taahhüt edilmemiş verileri okumak.
– Non-repeatable Read: Aynı satır, bir işlem içinde farklı değerler döner.
– Phantom Read: Tekrar edilen sorguda başka bir işlemin eklemesi/silmesi nedeniyle ek veya eksik satırlar döner.
Deadlocks
Bir deadlock, iki işlemin birbirlerini sonsuz bir şekilde beklemesine neden olur.
Örnek:Transaction A
Lock Order
↓
Ürün Bekleyin
Transaction B
Lock Product
↓
Wait Order
Hiçbiri devam edemez.
Modern veritabanları deadlock’ları otomatik olarak tespit eder ve bir işlemi geri alır.
Deadlock’ları azaltma yolları:
- Her zaman kaynakları aynı sırayla kilitleyin.
- İşlemleri kısa tutun.
- Gereksiz kilitlerden kaçının.
- Tahhüt veya geri almayı zamanında yapın.
Laravel Retry Örneği
Laravel’in işlem yardımcı programı, bir deadlock oluştuğunda otomatik olarak tekrar deneyebilir:DB::transaction(function () {
// Kritik veritabanı işlemleri
}, 5); // En fazla 5 kez tekrar dene
Performans Karşılaştırması
“Optimistic locking, çatışmaların nadir olduğunu varsayar. Pessimistic locking, onlardan önce fırsatları hazırlar. Harika mühendisler her birini nasıl seçeceğini bilir.”
Gerçek Dünya Örnekleri
Hangisini Seçmelisiniz?
Optimistic Locking seçin:
- Okuma, yazım sayısını büyük ölçüde aşar.
- Çatışmalar pek yaygın değil.
- Ölçeklenebilirlik öncelikli.
- Kullanıcılar başarısız güncellemeleri tekrar deneyebilir.
Pessimistic Locking seçin:
- Her güncellemenin sıra ile başarıyla gerçekleştirilmesi şart.
- Veri bütünlüğü kritik.
- Eş zamanlı güncellemeler yaygın.
- Geçici bloke olmaya müsaade edilebilir.
Bazı sistemler her iki yaklaşımı birleştirir – örneğin, genel düzenlemeler için optimistic locking ve ödeme işlemleri için pessimistic locking.
Yaygın Hatalar
- İşlemlerin kaybolan güncellemeleri otomatik olarak önleyeceği varsayımı.
- Externel API’lerini çağırırken işlemleri açık tutmak.
- Optimistic lock başarısızlıklarını yönetmeyi unutmak.
- Gerekenden daha fazla satırı kilitlemek.
- Deadlock istisnalarını görmezden gelmek.
- Yüksek trafikli okuma yoğun iş yüklerinde pessimistic lock kullanımı etkilerini ölçmeden gerçekleştirmek.
İlginç Bilgiler
- Amazon, Uber ve Stripe, birçok yüksek okuma sisteminde optimistic locking kullanır.
- Bankacılık sistemleri genellikle pessimistic locking’e güvenir.
- Çoğu geliştirici, eş zamanlılık hataları yalnızca üretim dağıtımından sonra yaşarlar.
- Kilitleme, hataların genellikle rastgele ve yeniden üretmesi zor olduğu için en zor arka uç konularından biridir.
- İşlemler yalnızca kaybolan güncellemeleri önlemez.
Sıkça Sorulan Sorular
İşlemler kilitlemeyi değiştirebilir mi?
Hayır. İşlemler işin birimlerinin sınırlarını tanımlar, ancak izolasyon seviyesi ve gerçekleştirilen işlemlere bağlı olarak eş zamanlı güncelleme çatışmalarını önleyemezler.
Laravel out of the box optimistic locking destekler mi?
Laravel, pessimistic locking için lockForUpdate() ve sharedLock() sağlar. Optimistic locking, Eloquent içinde yerleşik değildir, ancak bir sürüm sütunu veya zaman damgası kontrolü kullanarak uygulamak kolaydır.
updated_at optimistic locking için çalışır mı?
Evet, ancak bir integer sürüm sütunu, zaman damgalarının hassasiyet ve senkronizasyon sınırlamaları nedeniyle genellikle daha güvenilirdir.
Pessimistic locking yavaş mı?
Lockların serbest bırakılmasını beklemek zorunda kaldıkları için throughput’u azaltabilir.
Deadlock’lar hala olabilir mi?
Evet. Doğru kilitlemeye rağmen deadlock’lar mümkündür, bu nedenle uygulamalar deadlock istisnalarını yönetmeli ve uygun şekilde tekrar denemelidir.
Sonuç
Eş zamanlılık sorunları genellikle geliştirme aşamasında görünmez çünkü birden çok isteğin tam zamanında çakışmasını gerektirir. Ancak, birçok kullanıcının bulunduğu üretim sistemlerinde bu durumlar kaçınılmaz hale gelir.
Optimistic locking, performansa odaklanarak yalnızca güncellemeler meydana geldiğinde çatışmaları tespit eder, bu da onu okuma açısından yoğun uygulamalar için ideal hale getirir. Pessimistic locking ise, çelişkili güncellemeleri önleyerek tutarlılığı öne çıkarır; bu nedenle kritik finansal veya envanter işlemleri için uygundur.
Her iki stratejiyi anlamak – ve her birini ne zaman kullanacağınızı bilmek – temel bir arka uç mühendisliği becerisidir. İyi tasarlanmış işlemler, uygun izolasyon seviyeleri ve dikkatli hata yönetimi ile birlikte, gerçek dünya yükü altında güvenilir kalan uygulamalar geliştirmeye yardımcı olur.
Yazar Hakkında:Vatsal, AddWebSolution‘da web geliştiricisidir. Laravel, PHP, MySQL, Vue.js ve daha fazlasıyla web sihri yaratmaktadır.
Kaynak: Orijinal Makale
- Önemli Çıkarımlar
- İçindekiler
- Veritabanı Çatışmaları Neden Olur
- Race Condition’ları Anlama
- Veritabanı Kilitlemesi Nedir?
- Veritabanı Kilitleme Türleri
- Optimistic Locking
- Optimistic Locking Nasıl Çalışır
- Optimistic Locking Örneği
- Laravel Uygulaması
- Pessimistic Locking
- Aç
- Pessimistic Locking Nasıl Çalışır
- Laravel Uygulaması
- Shared Lock vs Exclusive Lock
- Veritabanı İşlem İzolasyon Seviyeleri
- Deadlocks
- Ürün Bekleyin
- Performans Karşılaştırması
- Gerçek Dünya Örnekleri
- Hangisini Seçmelisiniz?
- Yaygın Hatalar
- İlginç Bilgiler
- Sıkça Sorulan Sorular
- Sonuç



