Çoklu Eşzamanlı İşlem Çatışması
Smart Tech Devs’teki B2B SaaS platformunuz, binlerce eşzamanlı işlemi yönetmek için ölçeklenirken, arka uç mühendisliğinde karşılaşacağınız en can sıkıcı veritabanı hatası ile kaçınılmaz olarak karşılaşacaksınız: Deadlock (örneğin, PostgreSQL 40P01: deadlock detected veya MySQL 1213 Deadlock found when trying to get lock).
Deadlock, iki eşzamanlı işlemin birbirlerinin satır kilitlerini serbest bırakmaları için beklediği durumdur. Örneğin, İşçi A Satır 1’i kilitler ve Satır 2’ye ihtiyaç duyar. Tam aynı anda, İşçi B Satır 2’yi kilitler ve Satır 1’e ihtiyaç duyar. Bu, sonsuz bir Meksika engeli durumuna yol açar. Veritabanı motorunun çözümü, bu işlemlerden birini sonlandırmaktır ve bu durum kullanıcıya kritik bir 500 hatası verebilir veya arka planda çalışan işlerin çökmesine neden olabilir.
Kurumsal Çözüm: Otomatik Tekrar Denemeler
Yüksek derecede eşzamanlı, karmaşık bir ilişkisel veritabanında deadlock’ları tamamen ortadan kaldıramazsınız. Ancak, bunları son kullanıcıya görünmez hale getirebilirsiniz. Bir işlem “deadlock kurbanı” olarak seçildiğinde ve sonlandırıldığında, işlem aslında geçerli bir işlemdir; sadece kötü bir zamanlama ile çakışmıştır. Basitçe birkaç milisaniye bekleyip tekrar denerseniz, büyük ihtimalle başarılı olacaktır.
Dayanıklı İşlemler Tasarlamak
Laravel, bu durumu ele almak için son derece şık, yerleşik bir mekanizma sağlar. DB::transaction() yöntemi, isteğe bağlı bir ikinci parametre olan tekrar sayısını kabul eder.
namespace App\Services;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\QueryException;
class FinancialLedgerService
{
public function transferFunds($fromAccountId, $toAccountId, $amount)
{
// ❌ ANTI-PATTERN: Buradaki bir deadlock kritik bir 500 hatası verir
// DB::transaction(function () use (...) { ... });
// ✅ KURUMSAL PATTERN: Büyülü "5" parametresi
// Eğer bir deadlock oluşursa, Laravel istisnayı yakalar, kısa bir süre bekler
// ve güvenli bir şekilde işlemi 5 kez yeniden dener.
return DB::transaction(function () use ($fromAccountId, $toAccountId, $amount) {
// 1. Kaynak hesaptan düş
$fromAccount = Account::where('id', $fromAccountId)->lockForUpdate()->first();
$fromAccount->balance -= $amount;
$fromAccount->save();
// 2. Hedef hesaba ekle
$toAccount = Account::where('id', $toAccountId)->lockForUpdate()->first();
$toAccount->balance += $amount;
$toAccount->save();
// 3. Defter kaydı oluştur
Ledger::create([
'from_id' => $fromAccountId,
'to_id' => $toAccountId,
'amount' => $amount
]);
return true;
}, 5); // Bu işlemi en fazla 5 kez denemek için ayarla
}
}
Mühendislik Yatırım Getirisi
Kritik işlemlerinize bir tekrar sınırı ekleyerek, kendi kendini onaran bir veri katmanı oluştursunuz. Bir deadlock, büyük bir trafik artışı sırasında meydana geldiğinde, uygulamanız artık kritik istisnalar fırlatmaz veya kullanıcı isteklerini düşürmez. Framework, çakışmayı sessizce absorbe eder, işlemi yeniden dener ve isteği başarıyla sonuçlandırır, böylelikle veritabanı çatışmasını müşterilerinize tamamen maskelemektedir.
Kaynak: Orijinal Makale


