Web uygulamaları, e-ticaret platformları ve SaaS projelerinde performans darboğazlarının %80'den fazlası uygulama kodundan değil, veritabanı (RDBMS) katmanından kaynaklanır. Web sunucuları durumsuz (stateless) çalıştıkları için kolayca yatayda ölçeklenebilir ve önbelleğe (cache) alınabilir; ancak veritabanları durumlu (stateful) yapılardır ve doğrudan bellek (RAM) ile disk I/O hızına bağımlıdır.
Birçok hosting kullanıcısı, siteleri yavaşladığında veya "Error establishing a database connection" hatası aldığında hemen daha yüksek vCPU'lu paketlere geçer. Oysa doğru yapılandırılmamış bir MySQL veya PostgreSQL sunucusu, 16 çekirdekli bir makinede dahi varsayılan ayarlarıyla birkaç yüz eşzamanlı sorguda kilitlenebilir.
Bu kapsamlı rehberde, MySQL/MariaDB ve PostgreSQL altyapılarınızı optimize etmek, bellek havuzlarını doğru hesaplamak ve donanım darboğazlarını ortadan kaldırmak için uygulamanız gereken adımları ele alıyoruz.
1. Donanım ve Sunucu Türü Seçimi: Veritabanı Nerede Barınmalı?
Veritabanı iş yükleri (OLTP - Online Transaction Processing), sıradan web hosting ortamlarından çok farklı donanım gereksinimlerine sahiptir:
| Donanım Bileşeni | Paylaşımlı Hosting / Düşük VPS | Önerilen Veritabanı Sunucusu (VDS / Bare-Metal) | Neden Önemli? |
|---|---|---|---|
| Disk Teknolojisi | SATA SSD / Paylaşımlı HDD | PCIe 4.0 / 5.0 Enterprise NVMe SSD | Rastgele 4K yazma (random I/O) ve WAL/Redo log gecikmesi doğrudan diske bağlıdır. |
| Disk IOPS Değeri | 1.000 – 3.000 IOPS | 50.000 – 500.000+ IOPS | Saniyedeki eşzamanlı sorgu ve transaction hacmini belirler. |
| RAM (Bellek) Türü | Standart DDR4 | ECC DDR5 (Hata Düzeltmeli) | Bellekteki veri sayfalarında bit kaymasını (silent corruption) önler. |
| CPU Çekirdek Tahsisi | Aşırı Paylaşımlı (Shared vCPU) | Dedike (Dedicated) Çekirdek / Bare-Metal | Komşu sanal sunucuların (noisy neighbors) CPU cache'ini tüketmesini engeller. |
[!IMPORTANT] IOPS ve Gecikme (Latency): Veritabanı işlemlerinde sıralı okuma/yazma hızından (GB/s) ziyade rastgele 4K IOPS ve mikrosaniye (µs) seviyesindeki disk erişim gecikmesi belirleyicidir. Bu nedenle paylaşımlı ağ depolaması (NFS/standart SAN) yerine doğrudan sunucuya bağlı (Direct Attached NVMe) yerel diskler tercih edilmelidir.
2. MySQL & MariaDB Bellek ve Çekirdek Optimizasyonu
MySQL ve MariaDB sunucularında varsayılan my.cnf ayarları, sunucunun minimum kaynakla çalışmasını hedefleyen muhafazakar değerlerle gelir. Üretim ortamında aşağıdaki parametreleri sunucunuzun RAM miktarına göre yeniden yapılandırmalısınız:
1. innodb_buffer_pool_size (En Kritik Ayar)
InnoDB motorunda veriler ve indeksler bellekteki "Buffer Pool" havuzunda tutulur. Sorgu bellekteki bir veriye eriştiğinde disk okuması yapılmaz (Cache Hit).
- Yalnızca Veritabanı Barındıran Sunucuda: Toplam fiziksel RAM'in %70 - %80'i.
- Web + Veritabanı Birlikte Barınan Sunucuda: Toplam fiziksel RAM'in %40 - %50'si.
# Örnek: 16 GB RAM'li dedike bir veritabanı sunucusu için my.cnf
[mysqld]
innodb_buffer_pool_size = 12G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_buffer_pool_instances: Buffer pool boyutu 1 GB'tan büyükse, bellek kilitlenme (mutex contention) sürelerini düşürmek için havuzu 4 veya 8 bağımsız örneğe bölün.innodb_flush_log_at_trx_commit:1(Varsayılan): Her işlemde (commit) diske yazar ve senkronize eder. %100 ACID güvenlidir ancak disk I/O yükü yüksektir.2: Her saniyede bir diske senkronize eder. Güç kesintisinde en fazla 1 saniyelik veri kaybı riski taşır ancak yazma performansını 3 ila 5 kat artırır.
innodb_flush_method = O_DIRECT: İşletim sisteminin çift önbellekleme (double buffering) yapmasını engelleyerek RAM tasarrufu sağlar.
3. PostgreSQL Bellek ve Performans Yapılandırması
PostgreSQL, Linux işletim sisteminin kendi sayfa önbelleği (OS Page Cache) ile simbiyotik bir ilişki içinde çalışır. Bu nedenle bellek tahsis mantığı MySQL'den farklıdır:
# Örnek: 16 GB RAM ve NVMe SSD'li bir sunucu için postgresql.conf
shared_buffers = 4GB # Toplam RAM'in %25'i
work_mem = 32MB # Karmaşık sıralama ve hash tabloları için işlem başına RAM
maintenance_work_mem = 1GB # VACUUM, CREATE INDEX gibi bakım işlemleri için
effective_cache_size = 12GB # Query Planner'a sistemdeki toplam önbelleği bildirir (%75)
random_page_cost = 1.1 # NVMe SSD disklerde 1.1 (HDD'lerde 4.0)
effective_io_concurrency = 200 # NVMe eşzamanlı okuma kapasitesi
wal_buffers = 16MB
min_wal_size = 1GB
max_wal_size = 16GB
work_mem Tuzağına Dikkat Edin!
work_mem, sunucu genelinde değil her sorgu işlemi başına ayrılır. Karmaşık bir sorgu birden fazla sıralama (sort) veya hash işlemi yapıyorsa ve aynı anda 50 eşzamanlı bağlantı gelirse:
Tüketilen RAM = Bağlantı Sayısı * İşlem Sayısı * work_mem
Bu değeri 512 MB gibi kontrolsüz yüksek bir seviyeye ayarlamak, Linux OOM Killer'ın (Out of Memory) tetiklenip PostgreSQL sürecini aniden sonlandırmasına neden olabilir.
4. Bağlantı Havuzu (Connection Pooling): Neden Şarttır?
Web uygulamalarında (PHP, Node.js, Python) her yeni HTTP isteğinde sıfırdan veritabanı bağlantısı açıp kapatmak büyük bir işlemci yükü (overhead) yaratır.
Bağlantı Sayısını Artırma Tuzağı (max_connections)
Birçok yönetici trafik arttığında max_connections = 1000 yapar. Ancak:
- Her aktif bağlantı kendi oturum belleğini tüketir.
- İşlemci çekirdekleri yüzlerce bağlantı arasında sürekli bağlam değişimi (context switching) yaparak kilitlenir.
Çözüm: Harici Connection Pooler Kullanımı
| Motor | Önerilen Havuz Aracı | Çalışma Modu & Avantajı |
|---|---|---|
| PostgreSQL | PgBouncer | Transaction Modu: İstemci bağlantısını tutar, fiziksel PostgreSQL bağlantısını ise sadece sorgu anında devreye sokar. 10.000 istemci bağlantısını 50 gerçek PostgreSQL bağlantısıyla sorunsuz yönetir. |
| MySQL / MariaDB | ProxySQL | Sorgu Yönlendirme & Önbellek: Okuma ve yazma sorgularını (Master/Replica) otomatik ayırır, sık tekrarlanan sorguları RAM'inde önbelleğe alır. |
5. İndeksleme Stratejileri ve Yavaş Sorgu (Slow Query) Analizi
Hiçbir sunucu veya bellek optimizasyonu, yanlış yazılmış veya indeksi eksik bir SQL sorgusunun yerini tutamaz:
1. EXPLAIN ve EXPLAIN ANALYZE ile Teşhis
Bir sorgunun neden yavaş çalıştığını anlamak için sorgu başına EXPLAIN ekleyin:
- MySQL:
type: ALLgörüyorsanız tablonun tamamı taranıyordur (Full Table Scan). İdeal durumref,eq_refveyarangegörmektir. - PostgreSQL:
Seq Scan on table_nameifadesi tablonun tamamının baştan sona okunduğunu gösterir.Index ScanveyaBitmap Index Scanhedeflenmelidir.
2. Bileşik İndekslerde Sol Kuralı (Leftmost Prefix Rule)
Birden fazla sütun içeren indekslerde (INDEX idx_user (status, created_at, country)), sorgu soldaki ilk sütunu (status) filtrelemiyorsa indeks devreye girmez.
3. Yavaş Sorgu Günlüğünü (Slow Query Log) Açın
# MySQL yavaş sorgu logunu aktif etme
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1.0 # 1 saniyeden uzun süren tüm sorguları kaydet
log_queries_not_using_indexes = 1 # İndeks kullanmayan sorguları yakala
6. Veritabanı İçin En İyi Hosting Mimarisi Kontrol Listesi
- İzolasyon: Veritabanınız yoğun trafik alıyorsa web sunucusundan (Apache/Nginx/PHP) ayrı bir VDS veya Bare-Metal sunucuya taşıyın.
- Yerel NVMe Depolama: Ağ üzerinden bağlanan yavaş iSCSI/NFS diskler yerine doğrudan PCIe NVMe disk tercih edin.
- Otomatik Yedekleme & WAL Arşivleme: MySQL için Percona XtraBackup, PostgreSQL için
pgBackRestile sıfır kilitlenmeli canlı yedekleme kurun. - İzleme & Metrikler: Prometheus + Grafana (
mysqld_exporter/postgres_exporter) ile Buffer Pool Hit Ratio değerinin %99 üzerinde olduğunu sürekli izleyin. - Güvenlik Duvarı: Veritabanı portlarını (3306 / 5432) asla genel internete açmayın; sadece web sunucunuzun özel iç IP adresine (Private LAN / VPC) izin verin.