Sql & Veritabanı İle Uygulamalar İçin Veri Dağıtık İşlem Yönetimi Nasıl Yapılır?

Sql & Veritabanı İle Uygulamalar İçin Veri Dağıtık İşlem Yönetimi Nasıl Yapılır?
Sql & Veritabanı İle Uygulamalar İçin Veri Dağıtık İşlem Yönetimi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Dağıtık işlem yönetimi uygulamaları için temel gereksinimler şunlardır:

  • PostgreSQL veya MySQL gibi ACID uyumlu bir ilişkisel veritabanı yönetim sistemi.
  • İşlem yönetimi için bir mesaj kuyruğu (RabbitMQ veya Apache Kafka).
  • Dağıtık işlemleri takip etmek için bir orkestrasyon katmanı.
  • İşlem kayıtlarını tutmak için "Outbox" tablosu yapısı.

Tüm örneklerimizde, veritabanı işlemlerini güvenli hale getirmek için PDO (PHP Data Objects) veya benzeri parametreli sorgu destekleyen kütüphaneler kullanılacaktır. SQL Injection riskine karşı asla doğrudan kullanıcı girdilerini sorguya dahil etmeyin.

Dağıtık İşlem Yönetiminde Temel Yaklaşımlar

Dağıtık işlemleri yönetmek için kullanılan yöntemleri anlamak, doğru mimariyi seçmenizi sağlar. Aşağıdaki tablo, yaygın yöntemlerin karşılaştırmasını sunar:

Yöntem Avantajı Dezavantajı
2PC (Two-Phase Commit) Tam tutarlılık sağlar. Performansı düşürür, kilitlenme riski yüksektir.
Saga Pattern Yüksek ölçeklenebilirlik sunar. Uygulaması karmaşıktır, nihai tutarlılık (eventual consistency) vardır.
TCC (Try-Confirm-Cancel) İş mantığı üzerinde tam kontrol sağlar. Her servis için üç ayrı metot yazılmalıdır.

Adım Adım Outbox Pattern Uygulaması

Dağıtık sistemlerde en büyük sorun, veritabanı işlemi gerçekleştikten sonra mesaj kuyruğuna veri gönderilememesidir. Outbox pattern, bu sorunu çözmek için işlemle birlikte bir "outbox" tablosuna kayıt atar. İşte SQL yapısı:

CREATE TABLE outbox (
    id UUID PRIMARY KEY,
    aggregate_type VARCHAR(255),
    aggregate_id VARCHAR(255),
    type VARCHAR(255),
    payload JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Bu tablo, veritabanı işleminizle aynı transaction bloğu içerisinde doldurulur. Böylece veri tutarlılığı garanti altına alınır.

Saga Pattern ile İşlem Koordinasyonu

Saga, bir dizi yerel işlemden oluşur. Eğer bir adım başarısız olursa, önceki adımları geri almak için "telafi edici" (compensating) işlemler çalıştırılır. Aşağıdaki kod, bir sipariş süreci için örnek bir mantığı gösterir:

// Örnek: Sipariş oluşturma ve stok azaltma süreci
$pdo->beginTransaction();
try {
    $pdo->prepare("INSERT INTO orders (id, status) VALUES (?, 'PENDING')")->execute([$orderId]);
    $pdo->prepare("INSERT INTO outbox (payload) VALUES (?)")->execute([json_encode(['action' => 'REDUCE_STOCK', 'id' => $orderId])]);
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
}

Bu kod bloğu, veritabanı işleminin atomik olmasını sağlar. Eğer sipariş kaydedilemezse, mesaj kuyruğuna hiçbir veri gitmez.

Telafi Edici İşlemlerin Yönetimi

Saga pattern'in en kritik parçası telafi edici işlemlerdir. Eğer stok servisi hata verirse, sipariş durumunu "CANCELLED" olarak güncellemeniz gerekir. Bu, sistemin nihai tutarlılığa ulaşmasını sağlar.

function compensateOrder($orderId, $pdo) {
    $stmt = $pdo->prepare("UPDATE orders SET status = 'FAILED' WHERE id = ?");
    $stmt->execute([$orderId]);
}

Bu fonksiyon, başarısız olan bir işlemin etkilerini veritabanı seviyesinde temizlemek için kullanılır.

Güvenlik ve Hata Yönetimi

Kritik Uyarı: Dağıtık işlemlerde veritabanı kilitleri (deadlocks) oluşabilir. İşlem sürelerini kısa tutun ve mutlaka "retry" (tekrar deneme) mekanizmaları ile "idempotency" (aynı isteğin tekrar işlenmesi durumunda hata vermeme) prensibini uygulayın.

İşlemlerinizi güvenli kılmak için sorgularınızda her zaman parametre bağlama yöntemini kullanın. SQL Injection saldırılarına karşı en etkili savunma budur.

// Güvenli sorgu örneği
$stmt = $pdo->prepare("SELECT * FROM inventory WHERE product_id = :id");
$stmt->execute(['id' => $productId]);
$product = $stmt->fetch();

Sıkça Sorulan Sorular

Dağıtık işlemlerde neden 2PC yerine Saga tercih edilmelidir?

2PC, modern mikro hizmet mimarilerinde "blocking" (engelleyici) yapısı nedeniyle performans darboğazı yaratır. Saga ise asenkron yapısı sayesinde sistemin ölçeklenmesini sağlar.

İşlem başarısız olduğunda veriler ne kadar sürede tutarlı hale gelir?

Saga pattern "nihai tutarlılık" prensibine dayanır. Hata anında telafi edici işlemler tetiklendiğinde, sistem milisaniyeler veya saniyeler içinde tutarlı duruma döner.

Outbox tablosu çok büyürse ne yapmalıyım?

İşlenen verileri düzenli olarak bir arşiv tablosuna taşıyabilir veya belirli bir süre sonra silen bir "cleanup" cron job'ı çalıştırabilirsiniz.

Idempotency neden bu kadar önemlidir?

Ağ hataları nedeniyle aynı mesajın iki kez gönderilmesi durumunda, sistemin veriyi tekrar işlemesi hatalı sonuçlar doğurabilir. Idempotency, işlemin bir kez uygulanmasını garanti eder.

SQL veritabanı dışında NoSQL kullanabilir miyim?

Evet, ancak ACID garantileri farklılık gösterebilir. Dağıtık işlemlerde SQL'in sağladığı transaction kontrolü, hata yönetimini çok daha kolaylaştırır.

Dağıtık İşlemlerde Performans Optimizasyonu ve İzleme

Dağıtık sistemlerde veri tutarlılığını sağlamak için kullanılan Outbox veya Saga gibi yöntemler, doğal olarak sistem üzerinde ek bir yük oluşturur. Veritabanı üzerinde sürekli okuma-yazma işlemleri yapmak, özellikle yüksek trafikli sistemlerde darboğazlara yol açabilir. Performansı optimize etmek için şu stratejileri izleyebilirsiniz:

  • Veritabanı İndeksleme: Outbox tablosundaki processed veya status sütunlarını mutlaka indeksleyin. Bu, mesaj gönderici (message relay) servisin bekleyen kayıtları tararken tüm tabloyu okumasını engeller.
  • Batch Processing: Mesajları tek tek işlemek yerine, belirli aralıklarla veya belirli bir sayıya ulaştığında toplu (batch) olarak işleyin.
  • Partitioning: Çok büyük Outbox tabloları için veritabanı seviyesinde bölümleme (partitioning) yaparak, eski verilerin daha hızlı temizlenmesini sağlayın.

Performans İzleme İçin Basit Bir SQL Sorgusu

Sisteminizdeki darboğazları tespit etmek için Outbox tablonuzun doluluk oranını ve işlenme süresini düzenli olarak kontrol etmelisiniz. Aşağıdaki SQL sorgusu, işlenmeyi bekleyen kayıtların durumunu analiz etmenize yardımcı olur:

-- Bekleyen mesaj sayısını ve en eski mesajın yaşını sorgulama
SELECT 
    status, 
    COUNT(*) as total_count, 
    MIN(created_at) as oldest_message_time
FROM outbox_events
WHERE processed = false
GROUP BY status;

Dağıtık İşlemlerde Hata Ayıklama ve Test Stratejileri

Dağıtık bir sistemde hata ayıklamak, monolitik yapılara göre çok daha zordur. Bir işlemin nerede koptuğunu anlamak için "Correlation ID" kullanımı zorunludur. Her bir Saga süreci başladığında benzersiz bir ID oluşturun ve bu ID'yi tüm servisler arasında taşıyın.

Test Senaryosu: Hata Durumunu Simüle Etme

Sisteminizin "telafi edici işlemlerinin" (compensating transactions) doğru çalışıp çalışmadığını test etmek için "Chaos Engineering" prensiplerini uygulayın. Örneğin, ikinci servis adımında kasıtlı olarak bir hata fırlatarak, ilk servisin veritabanı değişikliğini geri alıp almadığını (rollback) doğrulayın.

Senaryo Beklenen Sonuç Test Yöntemi
Servis B başarısız oldu Servis A'daki işlem geri alınmalı Hata enjeksiyonu (Mock Failure)
Mesaj kuyruğu doldu Outbox tablosu veriyi tutmalı Kuyruğu durdurma (Pause Consumer)

Testlerinizi otomatize ederken, veritabanı durumunu test öncesi ve sonrası karşılaştıran bir yapı kurmanız, veri tutarlılığını garanti altına almanızı sağlar. Aşağıdaki örnek, bir entegrasyon testinde veritabanı durumunu doğrulamak için kullanılan basit bir mantıksal kontrolü gösterir:

// Örnek: Saga hata yönetimi entegrasyon testi mantığı
public void testSagaRollbackOnFailure() {
    // 1. İşlemi başlat
    var sagaId = sagaManager.startProcess(orderData);
    
    // 2. Servis B'de hata simülasyonu yap
    simulateServiceFailure(sagaId);
    
    // 3. Veritabanı kontrolü: Servis A'daki kayıt iptal edilmiş mi?
    var order = db.query("SELECT status FROM orders WHERE saga_id = ?", sagaId);
    assert(order.status == "CANCELLED");
}

Bu test yaklaşımı, sisteminizin sadece "mutlu yol" (happy path) senaryolarında değil, beklenmedik hata durumlarında da veriyi koruduğunu kanıtlar. Dağıtık işlem yönetiminde başarının anahtarı, sistemin her zaman "kısmi başarısızlık" (partial failure) durumuna hazır olmasıdır.

Sonuç

SQL ve veritabanı seviyesinde veri dağıtık işlem yönetimi, sabır ve dikkat gerektiren bir süreçtir. Outbox pattern ve Saga mimarisi, 2026 yılı yazılım dünyasında bu karmaşıklığı yönetmek için en güvenilir yollardır. Uygulamanızda bu yöntemleri adım adım devreye alarak, sisteminizin hata toleransını ve veri bütünlüğünü ciddi oranda artırabilirsiniz. Bir sonraki adım olarak, dağıtık izleme (distributed tracing) araçlarını (OpenTelemetry gibi) sisteminize entegre ederek işlemlerinizi uçtan uca izlemeyi deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Hobi projeleri ve kendin yap (DIY) içerikleri üzerine uzmanlaşmış bir içerik editörüyüm. Adım adım rehberlerle okuyucuların teknik becerilerini geliştirmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz