Site bir süre düzgün çalışıyor, ardından SQLSTATE[HY000] [1040] Too many connections hatası geliyor. İlk öneri genellikle belli: max_connections değerini yükselt. Fakat bağlantılar neden doluyor sorusunu atlayınca, aynı sorunu biraz daha yüksek bellek tüketimiyle yeniden yaşayabilirsin.
1040, yeni bağlantı açılırken sunucunun bağlantı sınırına takıldığını gösterir. Parola hatası veya yanlış socket yolu değildir. MySQL'in açıklaması da bağlantı sınırı ile yönetici erişimini ayrı ele alır. Buradaki SQL'leri yetkili bir yönetici oturumunda çalıştır; sorgu metinlerinde müşteri verisi bulunabileceğini unutma.
Önce hangi sunucuya baktığımızı öğrenelim
SELECT VERSION(), @@hostname, @@port;
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS WHERE Variable_name IN (
'Threads_connected', 'Threads_running', 'Max_used_connections',
'Connection_errors_max_connections', 'Uptime'
);
Uygulama bir veritabanı proxy'sine veya farklı bir sunucuya bağlanıyorsa kendi bilgisayarındaki MySQL'i incelemek işe yaramaz. Sürüm bilgisi de önemli: MySQL ve MariaDB'de benzer komutlar bulunsa bile yönetici yetkileri ve kalıcı ayar yöntemleri birebir aynı değildir.
Threads_connected o anda açık bağlantıları, Threads_running ise uyumayan iş parçacıklarını gösterir; doğrudan CPU çekirdeği sayacı değildir. Max_used_connections geçmişte görülen tepeyi anlatır. Bunun hangi çalışma veya sayaç sıfırlama dönemine ait olduğunu anlamak için Uptime ve bakım geçmişine de bak. Tanımlar MySQL durum değişkenleri belgesinde yer alıyor.
Örneğin hata bittikten sonra bağlantı sayısının düşük görünmesi, olay anında sınırın dolmadığını kanıtlamaz. Saatini kaydet, aynı ölçümü yoğunluk sırasında yeniden al. Sayacı sırf temiz bir görüntü elde etmek için sıfırlama; teşhiste kullanacağın izi silmiş olursun.
Bağlantıları kim tutuyor?
SHOW FULL PROCESSLIST;
Kullanıcı, kaynak adres, veritabanı, komut ve durum sütunlarını beraber oku. Sleep görmek tek başına bağlantı kaçağı demek değil; bir havuz boş bağlantıyı yeniden kullanmak için bekletiyor olabilir. Buna karşılık az sayıda uygulama örneğinin yüzlerce bağlantıyı uzun süre tutması araştırılacak bir işarettir.
Tüm oturumları göremiyorsan sorun sorguda olmayabilir; hesabın yalnız kendi oturumlarını görmeye yetkili olabilir. PROCESSLIST belgesindeki yetki ve sürüm notlarını kontrol et. Modern MySQL kurulumlarında Performance Schema tabanlı izleme de değerlendirilebilir; MariaDB'ye MySQL'e özgü izleme tablolarını aynen taşımaya çalışma.
- Bir kullanıcıda birikiyorsa: ilgili uygulamanın havuzunu, worker sayısını ve bağlantıyı bırakma davranışını incele.
- Uzun çalışan sorgular varsa: kilit beklemesi veya yavaş sorgu bağlantıları meşgul tutuyor olabilir. Sadece bağlantı limitiyle uğraşma.
- Aynı anda çok kullanıcı etkileniyorsa: ortak bir trafik artışı, cron dalgası veya altyapı sorunu aramaya değer.
Havuz boyutunu tek uygulama sanma
Basit bir kapasite hesabı yapalım. Sekiz uygulama örneğinin her biri en fazla yirmi bağlantı açabiliyorsa, yalnız bu uygulama için olası havuz toplamı 160'tır. Buna arka plan işleri, yönetim araçları ve diğer siteler de eklenir. Bunlar ölçüm değil, planlama örneği; her havuzun tamamı sürekli açık olmak zorunda değildir.
Yeni worker eklemek HTTP kuyruğunu azaltırken veritabanına daha fazla eşzamanlı iş gönderebilir. Bu yüzden uygulama ölçeklemesini bağlantı bütçesinden ayrı düşünme. Kalıcı bağlantı kullanan PHP süreçlerinde de “istek bitti, bağlantı kesin kapandı” varsayımıyla hesap yapma.
Yavaş sorgu tarafını inceleyeceksen EXPLAIN ANALYZE ile sorgu planı okuma yazısı yardımcı olabilir. Üretimde çalıştırılan analiz sorgusunun da iş yaptığını ve yük oluşturabileceğini hesaba kat.
Limit artırmak ne zaman çözümün parçası olur?
Meşru yoğunluğun mevcut sınırı aştığını, uygulamanın bağlantıları makul kullandığını ve sunucunun kaynaklarının buna uygun olduğunu gördüysen kontrollü artış düşünülebilir. Her bağlantıya sabit bir RAM rakamı çarparak karar verme; aktif sorguların bellek kullanımı da değişir. Önce mevcut değeri ve hangi yapılandırmadan geldiğini kaydet.
Kalıcı ayar için kullandığın ürünün ve paketin desteklediği yöntemi seç. MySQL'deki SET PERSIST davranışını MariaDB için varsayma. Yönetilen hostingde sunucu genelindeki ayarı değiştirmek yerine sağlayıcıyla uygulama havuzunu birlikte değerlendir. MariaDB'nin bağlantı kapasitesi notu da anlık sayı kadar tepe kullanımını izlemeyi öneriyor.
Bütün Sleep oturumlarını otomatik öldüren bir komut kullanma. Boş görünen bir oturum açık işlem tutabilir; bağlantıyı kesmek uygulamada hata ve geri alma yükü yaratabilir. wait_timeout değerini sert biçimde düşürmek de havuzdaki bağlantıların beklenmedik biçimde kopmasına neden olabilir.
Olay bittiğinde hangi ölçüme bakacağız?
SHOW GLOBAL STATUS WHERE Variable_name IN (
'Threads_connected', 'Threads_running',
'Connection_errors_max_connections', 'Uptime'
);
Ölçümü önceki kaydınla aynı çalışma dönemi içinde karşılaştır. Bağlantı reddi sayacının daha önce sıfırdan büyük olması sorun değil; yeni hataların eklenmemesi önemli. Yoğunluk sırasında uygulamadan yeni bağlantı açılabildiğini, hata günlüğünde 1040'ın tekrarlamadığını ve sorgu gecikmesinin kabul edilebilir kaldığını birlikte doğrula. Bağlantılar düşüyor ama kullanıcılar hâlâ bekliyorsa sıradaki iş sınırı tekrar artırmak değil, bekleyen sorguların nedenini bulmak.