MySQL Error 1040 "Too many connections" — Sızıntı mı, Fırtına mı?
1040 hatasında sızıntı ile fırtınayı ayırt etme, ayrılmış yönetici bağlantısı, open_files_limit sınırı ve max_connections artırmanın gerçek maliyeti.
Operasyonel Doğrulama & Güvenilirlik Standardı
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR 1040 (HY000): Too many connectionsBu hatanın PostgreSQL karşılığı H-01'de (too many clients already) incelenmişti. Temel mantık benzer olsa da MySQL mimarisinde teşhis ve çözümü kökten değiştiren iki hayati fark bulunur:
- 1Ayrılmış Yönetici Yuvası (+1 Reserved Slot): MySQL,
max_connectionstavanına ulaşıldığında bir adet fazladan bağlantı yuvası ayırır. Bu yuva yalnızcaCONNECTION_ADMIN(MySQL 8.0+) veyaSUPER(MySQL 5.7) yetkisine sahip hesaplara açıktır. Dolayısıyla "sunucuya hiçbir şekilde bağlanamıyorum" diyorsanız standart uygulama hesabıyla deniyorsunuz demektir;rootveya yönetim yetkili bir hesapla hemen içeri girip darboğazı inceleyebilirsiniz. - 2`open_files_limit` Tuzağı:
max_connectionsparametresi işletim sisteminin dosya tanıtıcı (file descriptor) sınırından bağımsız değildir. MySQL başlatılırken işletim sistemininopen_files_limitdeğerini yetersiz bulursamax_connectionsdeğerini sessizce düşürür:
[Warning] Could not increase number of max_open_files to more than 1024, please change --open_files_limit
[Warning] Changed limits: max_openfiles: 1024 max_connections: 151 table_open_cache: 400my.cnf içinde max_connections = 1000 yazmış olmanızın hiçbir hükmü yoktur; MySQL fiilen 151 bağlantı ile çalışır. Çalışma zamanı ayarlarını sorgulamadan asla sonuca varmayın.▸Nedenini Doğrulayan Teşhis Sorguları
Yönetici hesabıyla giriş yapın ve önce yürürlükteki gerçek sınırları öğrenin:
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'max_user_connections';
SHOW VARIABLES LIKE 'open_files_limit';
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL STATUS LIKE 'Aborted_connects';Ardından bağlantı havuzunu kimin doldurduğunu tek tek listelemek yerine gruplayarak deseni ortaya çıkarın:
SELECT user, host, IFNULL(db,'-') AS db, command, state, COUNT(*) AS adet,
MAX(time) AS en_uzun_saniye
FROM information_schema.processlist
GROUP BY user, host, db, command, state
ORDER BY adet DESC;▸Üç Temel Senaryoyu Ayırt Etme
Aynı 1040 hatası üç tamamen farklı operasyonel kök nedenden kaynaklanır:
1. Bağlantı Sızıntısı (Connection Leak)
- •Belirti:
command = 'Sleep',timedeğerleri yüzlerce saniye, bağlantılar genellikle tek bir uygulama sunucusu IP'sinden (host) geliyor. - •Kök Neden: Uygulama kodu
connection.close()çağırmıyor veya ORM havuzu bağlantıları serbest bırakmıyor. - •Kritik: Bu senaryoda
max_connectionsdeğerini artırmak sorunu çözmez; yalnızca bellek tüketimini artırır ve sunucu çöküşünü birkaç dakika geciktirir.
2. Bağlantı Fırtınası (Connection Storm)
- •Belirti: Farklı hostlardan aynı saniyede yüzlerce kısa ömürlü bağlantı açılıyor.
- •Kök Neden: Yeni bir mikroservis pod dağıtımı (rolling deploy), aynı dakikaya denk gelen cron işleri, yük dengeleyicinin (ALB/HAProxy) agresif sağlık kontrolleri veya uygulamanın yeniden bağlanma (reconnection storm) döngüsü.
3. Yavaş Sorgu & Kilit Tıkanması (Lock Bottleneck)
- •Belirti:
Threads_runningdeğeri çok yüksek,Sleepdurumu az. - •Kök Neden: Bağlantılar boşta değildir; aktif olarak çalışmaktadır ancak eksik indeksler veya satır/tablo kilitleri yüzünden yanıt dönememektedir. Arkadan gelen her yeni HTTP isteği yeni bir DB oturumu açar ve havuz tavana vurur. Çözüm bağlantı sayısını artırmak değil, kilitleyen sorguyu optimize etmektir.
▸Adım Adım Acil Müdahale ve Çözüm
1. Acil Durumda Boşta Kalan (Sleep) Bağlantıları Sonlandırın
Önce hangi oturumların uzun süredir boşta beklediğini belirleyin:
SELECT id, user, host, time, LEFT(info, 100) AS sorgu
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 300
ORDER BY time DESC;Hedef oturumu sonlandırın:
KILL CONNECTION 123456;KILL CONNECTION hem çalışan sorguyu hem de soket bağlantısını kapatır. KILL QUERY ise yalnızca o an yürütülen sorguyu iptal eder, oturum açık kalmaya devam eder. Boşta bekleyen (Sleep) bir bağlantı için KILL QUERY çalıştırmak hiçbir işe yaramaz.2. Boşta Kalma Sürelerini Uygulama Havuzuyla Uyumlayın
MySQL'in wait_timeout ve interactive_timeout değerleri, uygulama havuzunuzun (örneğin HikariCP maxLifetime) değerinden daha uzun olmalıdır. Sunucu bağlantıyı havuzdan önce keserse, havuz sunucunun kapattığı bayat bağlantıyı uygulamaya verir ve sorgu ortasında Communications link failure patlar.
3. Kullanıcı Başına Bağlantı Sınırı Koyun (Blast Radius İzolasyonu)
Tüm uygulamaların tek bir havuzu tüketmesini önlemek için kullanıcı bazlı tavan belirleyin:
CREATE USER 'app_rapor'@'10.0.2.%' IDENTIFIED BY 'GuvenliSifre'
WITH MAX_USER_CONNECTIONS 25;Bu sayede rapor servisinde bir sızıntı olduğunda sadece o servis 1040 alır; ana e-ticaret veya ödeme altyapısı kesintisiz çalışmaya devam eder.
4. max_connections Artırmadan Önce Bellek Maliyetini Hesaplayın
MySQL'de her bağlantı için ayrılan thread_stack ve işlem bazlı dinamik tamponlar (sort_buffer_size, read_buffer_size, join_buffer_size) bulunur: Toplam_Ek_Bellek = max_connections * (thread_stack + buffer_ortalamasi) Sınırı 200'den 2.000'e körlemesine çıkarmak işletim sistemi OOM-Killer mekanizmasını tetikleyip mysqld sürecini öldürebilir. Doğru mimari çözüm, araya ProxySQL yerleştirerek binlerce uygulama bağlantısını 50-100 adetlik kararlı veritabanı multiplexing havuzuna dönüştürmektir.
▸İlgili Hata Rehberleri & Hub Bağlantıları
- •PostgreSQL Too Many Clients Already (H-01) — PostgreSQL tarafındaki bağlantı sınırı karşılığı
- •PostgreSQL Remaining Connection Slots (H-13) — Rezerve süperkullanıcı yuvaları
- •SQL Server Connection Pool Timeout (H-08) — SQL Server havuz tükenmesi
- •MySQL Hub — MySQL yönetim ve performans mimarisi
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
MySQL ERROR 1045 Access denied: root Şifresi Sıfırlama Rehberi
MySQL 1045 hatasının dört nedeni, "using password: YES/NO" ayrımının anlamı ve kilitli kalınca --init-file ile güvenli şifre sıfırlama.
MySQL Deadlock ERROR 1213: Grafiği Okuma ve Kalıcı Önleme
MySQL 1213 deadlock hatasının nedeni, LATEST DETECTED DEADLOCK çıktısını okuma, gap lock kaynaklı kilitlenmeler ve uygulama tarafında retry tasarımı.
MySQL Lock wait timeout exceeded: Bloklayan İşlemi Bulma
1205 lock wait timeout hatasında bloklayan işlemi performance_schema ile bulma, KILL kararını verme ve kilidi kalıcı olarak azaltma yöntemleri.