🚨 KRİTİK SORUN Production 9 Ocak 2026 - 14:50

Database Connection Leak Analizi

MySQL "Too Many Connections" Hatası - Production Site Çöküyor

Max Connections: 151
Max Kullanılan: 152 ⚠️
Toplam Hata: 251 kez

📝 Basit Anlatım (Herkes İçin)

🔴 Ne Oluyor?

Muzibu.com.tr sitesi bazen "Internal Server Error" veriyor ve sayfa açılmıyor. Kullanıcı sayfayı yenilediğinde tekrar çalışıyor. Bu durum site güvenilirliğini olumsuz etkiliyor.

Hata Mesajı: "SQLSTATE[HY000] [1040] Too many connections"
Anlamı: Veritabanı "Çok fazla bağlantı var, yeni bağlantı kabul edemiyorum" diyor.

🎯 Sorunun Basit Açıklaması

Veritabanını bir restoran gibi düşünün:

  • 151 masa var (max_connections = 151)
  • Her kullanıcı bir masa tutuyor (her HTTP request = 1 bağlantı)
  • 51 garson sürekli çalışıyor (Horizon worker'lar)
  • Bazı masalar kullanılmadığı halde boşaltılmıyor (connection leak!)
  • Yeni müşteri geldiğinde "masamız kalmadı" deniyor (too many connections)

💡 Neden Önemli?

  • Kullanıcı Deneyimi: Site çöküyor, müşteri kaybı yaşanıyor
  • SEO Sorunu: Google error sayfaları görürse sıralama düşer
  • Gelir Kaybı: Premium üyelik satışları etkileniyor
  • İtibar Zararı: "Muzibu açılmıyor" yorumları gelebilir

✅ Çözüm Nedir?

Üç ana aksiyonla sorun çözülecek:

  1. Gereksiz bağlantıları kaldır - Her sayfa yüklendiğinde veritabanına giden gereksiz sorguları durduracağız
  2. Çift çalışan sistem kapat - İki adet aynı servis çalışıyor (Horizon duplicate), birini kapatacağız
  3. Masa sayısını artır - Veritabanı bağlantı limitini 151'den 300'e çıkaracağız

⏱️ Süreç

Bu düzeltmeler yapıldıktan sonra site kesintisiz çalışacak. Kullanıcılar "Too many connections" hatası almayacak.

🔧 Teknik Detaylar (Geliştiriciler İçin)

🚨 Kritik Bulgular

MySQL Stats
max_connections: 151
Threads_connected: 53
Max_used_connections: 152 ⚠️
Connection_errors_max: 251
Max_used_time: 2026-01-09 11:15:28
Process Stats
Horizon Master: 2 (duplicate! ⚠️)
Horizon Workers: 51
PHP-FPM Pools: ?
Nginx Workers: ?
Total Potential Conn: ~104

🔍 Sorun Kaynakları

KRİTİK #1

routes/web.php:157 - Her Request'te DB Query

Dosya: routes/web.php:155-158

Route dosyası her HTTP request'te yüklendiği için, bu sorgu her sayfa yüklenişinde çalışıyor:

$muzibuDomains = \Illuminate\Support\Facades\DB::table('domains')
    ->where('tenant_id', 1001)
    ->pluck('domain')
    ->toArray();

Etki: Anasayfa 1000 kez ziyaret edildi → 1000 DB connection açıldı → Limit aşıldı!

ORTA #2

Duplicate Horizon Master Process

İki adet Horizon master process çalışıyor (aynı supervisor config'i yüklüyor):

PID 1354897: /opt/plesk/php/8.5/bin/php artisan horizon
PID 1359267: /opt/plesk/php/8.5/bin/php artisan horizon

Her master 4 supervisor spawn ediyor:
- ai-supervisor (max 2 worker)
- tenant-supervisor (max 2 worker)
- muzibu-supervisor (max 3 worker)
- background-supervisor (max 1 worker)

Toplam: 2 master × (2+2+3+1) = 16 supervisor
Gerçek worker: 51 (her supervisor multiple worker spawn etmiş)

Etki: Gereksiz process → Gereksiz DB connection → CPU ve Memory yükü

ORTA #3

Düşük max_connections Limiti

Mevcut Limit: max_connections = 151

Gereksinim Hesabı:

Horizon Workers:        51
PHP-FPM pm.max_children: 50 (tahmini)
Nginx Connections:      20 (tahmini)
System/Admin:           10
Buffer:                 20
─────────────────────────────
TOPLAM:                ~151 (tam limit!)

Yoğun saatlerde trafik artınca: 151+ → "Too many connections"

Etki: Yüksek trafikte sistem limit aşımı → Site çöküyor

📊 Stack Trace Analizi

Hata Zamanı: GET https://muzibu.com/ (Anasayfa)

Illuminate\Database\QueryException
SQLSTATE[HY000] [1040] Too many connections
Connection: mysql
SQL: select `domain` from `domains` where `tenant_id` = 1001

routes/web.php:157
→ \Illuminate\Support\Facades\DB::table('domains')
→ ->where('tenant_id', 1001)
→ ->pluck('domain')

⚠️ Hata routes yüklenirken oluşuyor, yani middleware'lerden önce!

⚙️ Mevcut Database Config

Dosya: config/database.php:45-68

'mysql' => [
    'driver' => 'mysql',
    'host' => env('DB_HOST', '127.0.0.1'),
    'database' => env('DB_DATABASE', 'tuufi_4ekim'),
    'username' => env('DB_USERNAME', 'tuufi_4ekim'),
    'charset' => 'utf8mb4',
    'options' => [
        PDO::ATTR_TIMEOUT => 30,
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
        PDO::ATTR_PERSISTENT => false,  ← Connection pooling KAPALI!
    ],
]

⚠️ ATTR_PERSISTENT => false her request yeni connection açıyor!

Çözüm Planı (Adım Adım)

1️⃣

routes/web.php - Domain Query Cache Sistemi

EN ÖNCELİKLİ

Sorun: Her HTTP request'te DB::table('domains') query'si çalışıyor.

Çözüm: Domain listesini Redis cache'e al, TTL: 3600 saniye (1 saat).

Strateji:

  • Cache key: muzibu_domains_list
  • TTL: 3600 saniye (1 saat)
  • Cache miss → DB query → Cache'e yaz
  • Cache hit → Direkt kullan (DB query YOK)
  • Tenant değişikliğinde cache invalidation

Beklenen Sonuç:

1000 request → 1000 DB query (eski) | 1000 request → 1 DB query (yeni)
Kazanç: 999 DB connection azalma!

2️⃣

Duplicate Horizon Process Temizleme

ÖNEMLİ

Sorun: İki adet Horizon master process çalışıyor (PID: 1354897, 1359267).

Çözüm: Tüm Horizon process'lerini temizle, Supervisor config kontrol et, tek master başlat.

Aksiyon:

  1. php artisan horizon:terminate (graceful shutdown)
  2. pkill -9 -f "artisan horizon" (zorla temizle)
  3. Supervisor config kontrol: /etc/supervisor/conf.d/
  4. Tek Horizon master başlat: php artisan horizon
  5. Process kontrolü: ps aux | grep horizon

Beklenen Sonuç:

51 worker → ~25 worker (yarı yarıya azalma)
Kazanç: ~26 DB connection azalma + CPU/Memory rahatlaması

3️⃣

MySQL max_connections Artırma (Opsiyonel)

GÜVENLİK BUFFER

Durum: Yukarıdaki düzeltmelerle sorun çözülecek, ancak güvenlik için limit artırılabilir.

Öneri: max_connections = 151 → 300 (2x artış)

Konfigürasyon (Plesk MySQL):

# /etc/my.cnf.d/server.cnf
[mysqld]
max_connections = 300

# Restart gerekli
sudo systemctl restart mariadb

Beklenen Sonuç:

151 limit → 300 limit (yüksek trafik buffer)
Kazanç: Peak zamanlarda sistem çökmez

🎯 Uygulama Önceliği

🔥

1. routes/web.php Cache Sistemi

En büyük etki, hemen uygula! (999 DB query azalacak)

⚠️

2. Horizon Duplicate Temizleme

Orta etki, sistem performansı artacak (~26 process azalacak)

🛡️

3. max_connections Artırma

Güvenlik buffer, yukarıdaki düzeltmeler yeterli ama ekstra koruma

Tahmini Toplam Süre: 15-20 dakika
Downtime: YOK (Horizon restart hariç, ~30 saniye)
Risk Seviyesi: Düşük (cache ve process yönetimi)

🧪 Düzeltme Sonrası Test Planı

1. DB Connection Monitoring

mysql -u tuufi_4ekim -p'XZ9Lhb%u8jp9#njf' -e "SHOW STATUS LIKE 'Threads_connected';"
mysql -u tuufi_4ekim -p'XZ9Lhb%u8jp9#njf' -e "SHOW STATUS LIKE 'Max_used_connections';"

# Beklenen: Threads_connected < 80 (151'in yarısından az)

2. Horizon Process Count

ps aux | grep -E "(horizon|queue)" | grep -v grep | wc -l

# Beklenen: ~25-30 (51'den azalmalı)

3. Cache Test

php artisan tinker
>>> Cache::get('muzibu_domains_list');  // Domain listesi dönmeli
>>> Cache::has('muzibu_domains_list');  // true olmalı

4. Production Test

  • Anasayfayı 20 kez yenile (F5) → Error olmamalı
  • Farklı sayfalara git (artist, playlist, song) → Error olmamalı
  • Giriş yap, çıkış yap → Error olmamalı
  • Logs kontrol: tail -f storage/logs/laravel.log