Gereksinimler ve Ön Hazırlık
Bu uygulamaları hayata geçirmek için güncel bir SQL veritabanı yönetim sistemine (PostgreSQL 17+ veya MySQL 9.0+ önerilir) ihtiyacınız vardır. Ayrıca, veritabanı bağlantılarını yönetmek için modern bir ORM (Object-Relational Mapping) aracı veya güçlü bir veritabanı sürücüsü kullanmanız, veri paylaşım mimarisini kod seviyesinde yönetmenizi kolaylaştıracaktır.
- Veritabanı: PostgreSQL 17 veya MySQL 9.0.
- Dil: Node.js veya Python 3.12+ (Örneklerde modern sözdizimi kullanılacaktır).
- Araçlar: Docker (veritabanı konteynerleri için), DBeaver (veritabanı yönetimi).
- Bilgi Seviyesi: Temel SQL sorguları ve ilişkisel veritabanı tasarımı (Primary Key, Foreign Key, Indexing).
Adım 1: Paylaşımlı Veritabanı Şeması Tasarımı
Veri paylaşımının ilk adımı, verilerin mantıksal olarak nasıl ayrıştırılacağını belirlemektir. Uygulamalarınızın aynı veritabanı üzerinde çakışmadan çalışması için "Schema-based multi-tenancy" veya "Shared-table with Discriminator" yöntemlerini kullanabilirsiniz. Aşağıdaki SQL örneğinde, farklı uygulamaların verilerini ayırt etmek için bir app_id sütunu kullanıyoruz.
CREATE TABLE shared_data (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
app_id VARCHAR(50) NOT NULL,
data_payload JSONB NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
INDEX idx_app_id (app_id)
);
Bu yapı, veritabanı seviyesinde indeksleme yaparak sorguların sadece ilgili app_id üzerinden filtrelenmesini sağlar. İndeksleme, veri paylaşımında performans kaybını önleyen en kritik adımdır.
Adım 2: Güvenli Veri Erişim Katmanı Oluşturma
Uygulamalar arasında veri paylaşırken SQL Injection riskine karşı hazırlıklı olmalısınız. Dinamik sorgular yerine parametreli sorgular kullanmak, veri paylaşım mimarisinin güvenliğini sağlar. Aşağıdaki örnekte, Node.js ve pg kütüphanesi ile güvenli bir veri çekme işlemi gösterilmiştir.
async function getSharedData(appId) {
const query = 'SELECT * FROM shared_data WHERE app_id = $1';
const values = [appId];
try {
const res = await pool.query(query, values);
return res.rows;
} catch (err) {
console.error('Veri çekme hatası:', err.stack);
throw new Error('Veritabanı erişiminde hata oluştu.');
}
}
Bu kodda $1 kullanımı, veritabanı sürücüsünün girdiyi temizlemesini sağlar. Kullanıcıdan gelen veriyi doğrudan sorguya eklemek, sistemin tüm güvenliğini riske atar.
Adım 3: Veri Paylaşımında Eşzamanlılık ve İşlemler (Transactions)
Birden fazla uygulama aynı satırı güncellediğinde "Race Condition" (yarış durumu) oluşabilir. Bunu engellemek için SQL'in SELECT FOR UPDATE mekanizmasını kullanmalısınız. Bu komut, satırı kilitler ve işlem bitene kadar diğer uygulamaların o satırı değiştirmesini engeller.
BEGIN;
SELECT * FROM shared_data WHERE id = 'hedef-id' FOR UPDATE;
-- İşlemler burada yapılır
UPDATE shared_data SET data_payload = '{"status": "processed"}' WHERE id = 'hedef-id';
COMMIT;
Bu yöntem, veri bütünlüğünü garanti altına alır. Ancak, kilitlerin çok uzun süre tutulması sistem performansını düşüreceği için işlemlerinizi mümkün olduğunca kısa tutmalısınız.
Adım 4: Veritabanı Görünümleri (Views) ile Veri İzolasyonu
Veri paylaşım mimarisinde, her uygulamanın sadece kendi görmesi gereken veriye erişmesini sağlamak için SQL VIEW yapılarını kullanabilirsiniz. Bu, veritabanı seviyesinde bir güvenlik katmanı oluşturur.
CREATE VIEW app_alpha_data AS
SELECT * FROM shared_data WHERE app_id = 'ALPHA_APP';
-- Uygulama sadece bu görünümü sorgular
SELECT * FROM app_alpha_data;
Bu yaklaşım, uygulama kodunuzdaki karmaşık filtreleme mantığını veritabanına taşır ve hata payını azaltır. Uygulama geliştiricisi sadece SELECT * FROM app_alpha_data yazdığında, veritabanı otomatik olarak izolasyonu sağlar.
Veri Paylaşım Yöntemleri Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Paylaşımlı Tablo (Discriminator) | Düşük maliyet, kolay yönetim | Veri izolasyonu uygulama seviyesinde |
| Schema İzolasyonu | Güçlü izolasyon | Yönetimi daha karmaşık |
| Veritabanı Görünümleri (Views) | Güvenli ve temiz kod | Performans ek yükü (az miktarda) |
Adım 5: Veri Senkronizasyonu ve Olay Odaklı Mimari
Veri paylaşımlı mimarilerde, bir veritabanındaki değişiklik diğer uygulamaları etkileyebilir. 2026 yılı pratiklerinde, veritabanı tetikleyicileri (triggers) veya "Change Data Capture" (CDC) araçları ile değişiklikleri izlemek standarttır.
CREATE OR REPLACE FUNCTION notify_data_change()
RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify('data_changed', row_to_json(NEW)::text);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER data_update_trigger
AFTER UPDATE ON shared_data
FOR EACH ROW EXECUTE FUNCTION notify_data_change();
Bu tetikleyici, shared_data tablosunda bir güncelleme olduğunda diğer servislere bildirim gönderir. Bu, sistemlerin birbirini beklemeden güncel kalmasını sağlar.
Kritik Güvenlik Uyarısı: Veritabanı tetikleyicileri ve paylaşımlı erişim noktaları, yetkisiz erişime karşı mutlaka veritabanı kullanıcı rolleri (GRANT/REVOKE) ile sınırlandırılmalıdır. Uygulama kullanıcısına asla SUPERUSER yetkisi vermeyin.
Sıkça Sorulan Sorular
Veri paylaşımında en büyük performans sorunu nedir?
En büyük sorun, çok fazla uygulamanın aynı tablo üzerinde yoğun işlem yapması sonucu oluşan "Lock Contention" (kilit çekişmesi) durumudur. Bunu aşmak için indeksleri optimize etmeli ve işlemleri kısa tutmalısınız.
SQL Injection'ı tamamen nasıl engellerim?
Kullanıcıdan gelen hiçbir veriyi doğrudan sorgu dizesine eklemeyin. Her zaman ORM'lerin sunduğu parametreli sorgu yöntemlerini veya hazırlanan ifadeleri (prepared statements) kullanın.
Shared-table mimarisinde veriler nasıl gizli tutulur?
Veritabanı seviyesinde RLS (Row Level Security) kullanarak, kullanıcıya özel erişim politikaları tanımlayabilirsiniz. Bu, uygulama kodundan bağımsız bir güvenlik katmanı sağlar.
Veritabanı tetikleyicileri (triggers) yavaşlatır mı?
Doğru tasarlandığında (sadece gerekli durumlarda çalıştığında) yavaşlatmaz. Ancak karmaşık mantığı tetikleyicilerin içine yazmak yerine, bunu bir message broker (RabbitMQ, Kafka) üzerinden asenkron yapmak 2026 standartlarında daha doğrudur.
Hangi veritabanı bu mimari için en iyisidir?
PostgreSQL, JSONB desteği, gelişmiş RLS özellikleri ve güçlü tetikleyici mekanizmaları ile veri paylaşımlı mimariler için endüstri standardıdır.
Sorumluluk Reddi: Yukarıdaki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce mutlaka yük testleri yapın ve veritabanı yedekleme stratejilerinizi (backup) gözden geçirin. Yazılım güvenliği sorumluluğu geliştiriciye aittir.
Veri Paylaşımlı Mimarilerde Performans Optimizasyonu ve İndeksleme Stratejileri
Paylaşımlı veritabanı mimarilerinde, farklı kiracıların veya servislerin aynı tabloları kullanması, özellikle veri hacmi arttığında sorgu performansını ciddi şekilde etkileyebilir. Standart indeksleme yöntemleri, paylaşımlı yapılarda genellikle yetersiz kalır. Bu noktada, Composite Indexing (Bileşik İndeksleme) ve Partitioning (Bölümleme) tekniklerini devreye almak kaçınılmazdır.
Örneğin, tenant_id sütununun her sorguda kullanıldığı bir yapıda, indekslerinizi bu sütunu içerecek şekilde optimize etmelisiniz. Aşağıdaki SQL örneği, performans odaklı bir indeksleme stratejisini göstermektedir:
-- Tenant tabanlı sorguları hızlandırmak için bileşik indeks kullanımı
CREATE INDEX idx_orders_tenant_created_at
ON orders (tenant_id, created_at DESC);
-- Sadece aktif verileri getiren filtrelenmiş indeks (Partial Index)
CREATE INDEX idx_active_orders_tenant
ON orders (tenant_id)
WHERE status = 'active';
Bu yaklaşım, veritabanı motorunun tüm tabloyu taramak yerine, doğrudan ilgili kiracının verilerine odaklanmasını sağlar. Ayrıca, Query Execution Plan analizi yaparak, EXPLAIN ANALYZE komutu ile sorgularınızın ne kadar sürede çalıştığını düzenli olarak kontrol etmelisiniz.
Dağıtık Sistemlerde Hata Ayıklama ve İzlenebilirlik (Observability)
Veri paylaşımlı mimarilerde en büyük zorluk, bir hata oluştuğunda bu hatanın hangi servis veya hangi kiracıdan kaynaklandığını tespit etmektir. Geleneksel loglama yöntemleri, paylaşımlı veritabanlarında karmaşaya yol açar. Bu nedenle, Correlation ID (İlişkilendirme Kimliği) kullanımı standart haline getirilmelidir.
Her veritabanı işlemine benzersiz bir ID atayarak, işlemin veritabanı katmanındaki hareketlerini izleyebilirsiniz. Aşağıdaki örnek, bir veritabanı fonksiyonu içerisinde hata loglamasının nasıl yapılandırılacağını gösterir:
-- Hata takibi için özel bir log tablosu yapısı
CREATE TABLE system_audit_logs (
log_id SERIAL PRIMARY KEY,
correlation_id UUID NOT NULL,
tenant_id INT,
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- İşlem sırasında hata yakalama ve loglama
CREATE OR REPLACE PROCEDURE secure_data_update(
p_tenant_id INT,
p_correlation_id UUID,
p_data TEXT
)
LANGUAGE plpgsql AS $$
BEGIN
UPDATE shared_data SET content = p_data
WHERE tenant_id = p_tenant_id;
EXCEPTION WHEN OTHERS THEN
INSERT INTO system_audit_logs (correlation_id, tenant_id, error_message)
VALUES (p_correlation_id, p_tenant_id, SQLERRM);
RAISE;
END;
$$;
Bu yöntem, sisteminizdeki darboğazları veya hatalı veri girişlerini tespit etmenizi kolaylaştırır. Özellikle mikroservis mimarilerinde, veritabanı katmanındaki bu izlenebilirlik, sistemin genel sağlığını korumak için kritik bir öneme sahiptir.
İleri Düzey İpucu: Veritabanı Havuzu (Connection Pooling) Yönetimi
Paylaşımlı yapılarda çok sayıda servis aynı veritabanına bağlandığında, bağlantı limitleri (connection limits) hızla tükenebilir. PgBouncer veya benzeri bir bağlantı havuzu yöneticisi kullanarak, veritabanı bağlantılarını daha verimli yönetebilir ve "Too many connections" hatasını engelleyebilirsiniz.
Sonuç
SQL & Veritabanı ile veri paylaşımlı mimari kurmak, sisteminizin ölçeklenebilirliğini ve veri tutarlılığını doğrudan etkileyen stratejik bir karardır. Bu rehberde öğrendiğiniz RLS, parametreli sorgular, veritabanı görünümleri ve tetikleyiciler, modern bir mimarinin temel taşlarıdır. Bir sonraki adım olarak, bu veritabanı yapısını bir "Message Broker" ile entegre ederek asenkron veri akışlarını nasıl yöneteceğinizi araştırmanızı öneririm.
Yorumlar (0)
Yorum Yaz