Bir oyun sunucusunda ya da yoğun bir web uygulamasında darboğaz çoğu zaman MySQL'in kendisi değil, varsayılan ayarlarıyla çalışıyor olmasıdır. MySQL my.cnf dosyasını doğru ayarlamak, yeni donanım almadan elde edebileceğin en ucuz performans kazancıdır. Bu rehberde InnoDB buffer pool'dan bağlantı limitlerine, log ayarlarından sorgu önbelleğine kadar gerçekten fark yaratan parametreleri, neden önemli olduklarıyla birlikte anlatıyorum.
my.cnf nerede ve nasıl çalışır?
MySQL (ve MariaDB) açılışta yapılandırmayı bir dizi dosyadan okur. Linux'ta en yaygın yollar şunlardır:
/etc/my.cnf/etc/mysql/my.cnf/etc/mysql/mysql.conf.d/mysqld.cnf(Debian/Ubuntu)/etc/my.cnf.d/*.cnf(CentOS/Alma/Rocky)
Hangi dosyaların okunduğunu ve hangi sırayla yüklendiğini görmek için şu komutu çalıştır:
mysqld --verbose --help | grep -A1 "Default options"
Ayarlar [mysqld] bölümünün altına yazılır. Her değişiklikten sonra servisi yeniden başlatman gerekir:
sudo systemctl restart mysql # ya da mariadb
InnoDB buffer pool: en kritik ayar
Tek bir parametre seçmen gerekseydi bu innodb_buffer_pool_size olurdu. InnoDB, veri ve indeksleri bu bellek havuzunda tutar; havuz ne kadar büyükse disk yerine RAM'den o kadar çok okuma yaparsın. Genel kural, özel (dedicated) bir veritabanı sunucusunda toplam RAM'in %50–70'i kadar ayarlamaktır. Aynı makinede oyun sunucusu, PHP veya başka servisler de çalışıyorsa daha temkinli ol.
[mysqld]
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
Büyük havuzlarda (8 GB üzeri) innodb_buffer_pool_instances değerini birden fazla yaparak iç kilit çekişmesini azaltabilirsin; her instance ideal olarak en az 1 GB olmalı. Havuzun yeterli olup olmadığını anlamak için isabet oranına bak:
SHOW ENGINE INNODB STATUS\G
Çıktıdaki Buffer pool hit rate 1000/1000'e yakınsa neredeyse tüm okumalar bellekten geliyor demektir. Düşükse havuzu büyütmeyi düşün.
InnoDB log ve disk yazma davranışı
Yazma yoğun iş yüklerinde redo log boyutu ve flush politikası belirleyicidir. innodb_log_file_size (MySQL 8'de innodb_redo_log_capacity olarak da yönetilebilir) çok küçükse MySQL sürekli checkpoint yapar ve yazma performansı düşer.
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 1tam ACID güvenliği sağlar; her commit diske yazılır. Finansal veri için bu kalsın.- Değeri
2yaparsan log her saniye diske aktarılır; ani elektrik kesintisinde son ~1 saniyeyi kaybetme riskiyle ciddi yazma hızı kazanırsın. Oyun sunucusu envanteri gibi kritik olmayan verilerde makul bir tercihtir. O_DIRECT, işletim sistemi önbelleğini atlayarak çift önbelleklemeyi (double buffering) engeller.
Bağlantı ayarları: max_connections ve thread havuzu
Çok sayıda eşzamanlı oyuncu ya da web isteği geldiğinde max_connections yetersizse "Too many connections" hatası alırsın. Ancak bu değeri körlemesine yükseltmek de tehlikelidir: her bağlantı bellek tüketir.
max_connections = 200
thread_cache_size = 32
wait_timeout = 120
interactive_timeout = 120
thread_cache_size, kapanan bağlantıların thread'lerini yeniden kullanarak yeni bağlantı maliyetini düşürür. wait_timeout ise boşta kalan bağlantıları kapatarak takılı kalan istemcilerin slot işgal etmesini önler. Uygulamanın bağlantı havuzu (örneğin Laravel'in persistent bağlantıları) varsa timeout'u ona göre dengele.
Sorgu önbelleği ve sürüm farkları
Eski içeriklerde sık geçen query_cache_size ayarına dikkat: query cache, MySQL 5.7'de varsayılan kapalı, MySQL 8.0'da ise tamamen kaldırıldı çünkü yüksek eşzamanlılıkta kilit çekişmesi yaratıyordu. MySQL 8 kullanıyorsan bu satırları my.cnf'e eklersen servis başlamaz. Modern yaklaşım, önbelleklemeyi uygulama katmanında (Redis, Memcached) ya da InnoDB buffer pool'a güvenerek yapmaktır.
Per-bağlantı tamponlarını da abartma; bunlar her bağlantı için ayrı ayrı ayrılır:
sort_buffer_size = 2M
join_buffer_size = 2M
tmp_table_size = 64M
max_heap_table_size = 64M
Değişiklikleri doğrulamak ve ölçmek
Ayar yapmak yarısı; etkisini ölçmek diğer yarısıdır. Çalışan değerleri kontrol et:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL STATUS LIKE 'Threads_connected';
Yavaş sorguları yakalamak için slow query log'u aç ve gerçek darboğazları gör:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
Hazır araçlardan mysqltuner.pl, çalışan sunucunu analiz edip somut öneriler verir; ancak önerilerini körü körüne uygulama, her birinin neden geldiğini anladıktan sonra uygula. Unutma: en iyi my.cnf bile kötü yazılmış bir sorguyu ya da eksik bir indeksi kurtarmaz. Önce EXPLAIN ile sorgularını ve indekslerini düzelt, sonra yapılandırmayı ince ayar yap.
Sık Sorulan Sorular
my.cnf değişiklikleri için MySQL'i yeniden başlatmam şart mı?
Çoğu InnoDB ayarı (buffer pool, log dosyası boyutu) için evet. Ancak birçok değişken çalışırken SET GLOBAL ile dinamik olarak değiştirilebilir; örneğin SET GLOBAL max_connections = 300;. Dinamik değişiklikler yeniden başlatınca kaybolur, kalıcı olması için yine my.cnf'e yazman gerekir.
innodb_buffer_pool_size'ı çok büyük yaparsam ne olur?
RAM'i tüketip işletim sisteminin ya da diğer servislerin swap'e düşmesine neden olabilirsin; bu durumda performans, küçük bir havuzdan bile kötü olur. Buffer pool dışında her bağlantının da bellek kullandığını hesaba katarak makineye toplamda yeterince boşluk bırak.
MySQL mi MariaDB mi kullanıyorum, ayarlar aynı mı?
Temel InnoDB ve bağlantı ayarları büyük ölçüde ortaktır. Yine de query cache, thread pool ve bazı varsayılan değerlerde farklar var. Sürümüne özel ayar isimlerini doğrulamak için SHOW VARIABLES çıktısını ölçüt al.
Veritabanın sunucunu yavaşlatıyor mu? Oyun sunucusu ya da web projesi için MySQL/MariaDB tuning, indeks tasarımı ve sorgu optimizasyonu konusunda yardıma ihtiyacın varsa benimle iletişime geç; mevcut yapılandırmana bakıp somut bir iyileştirme planı çıkarayım.