E-ticaret sunucuları için veritabanı optimizasyonu: Magento 2.4'te MySQL 8 ve MariaDB
güncellendi ilk yayın 20165 dk okuma
Bu yazı ilk kez 2016'de yayımlandı; 23 Ekim 2026 tarihinde Magento 2.4, Redis ve PHP-FPM dönemi için baştan yazıldı.
E-ticaret siteleri için sunucu hızının önemini çok kez duymuşsunuzdur. Ülkemizde bu konu genellikle güçlü donanımla, yani daha pahalı sunucuyla çözülmeye çalışılıyor ve aylık kiralama maliyetleri yükseliyor. Bu yazının ilk hâlini 2016'da yazmıştım; ana fikri hâlâ geçerli: özellikle yeni başlayan bir e-ticaret girişimi için büyük bütçeli sunucuya gerek yok, birkaç doğru ayarla istenen performansa ulaşılabilir. Ama MySQL 5 döneminin ayarlarının çoğu bugün geçersiz. Bu yüzden yazıyı MySQL 8, MariaDB ve Magento 2.4 için baştan yazdım.
Binlerce kişinin ziyaret ettiği bir mağaza hedefliyorsanız güçlü donanım tek başına yetmez. Doğru yapılandırılmamış bir veritabanı sunucusu, ciddi yatırımla aldığınız sunucunun gerçek performansını size vermez.
Magento 2.4'te veritabanının işi değişti
- Bütün tablolar InnoDB. 2016'da ilk sıraya koyduğum
key_buffer_sizeyalnızca MyISAM tablolarını ilgilendirir; Magento 2 için önemi yok. - Arama veritabanından çıktı. 2.4 serisinde arama ve katmanlı gezinme OpenSearch üzerinden yapılıyor; MySQL ile arama seçeneği kaldırıldı.
- Önbellek ve oturumlar Redis'e ya da Valkey'e taşınabilir; böylece bu yük veritabanına ve diske binmez.
- Tablo sayısı yüksek. Yönettiğim bir mağazanın veritabanında 543 tablo var. Tablo önbelleği ayarlarında bunu hesaba katın.
Hangi veritabanını seçeceğiniz de önem kazandı. Adobe'nin sistem gereksinimleri sayfasına göre (Ekim 2026 itibarıyla) MySQL 8.0'ın desteği 30 Nisan 2026'da sona erdi. 2.4.7'nin son yaması MySQL yerine MariaDB 10.11 ve 11.8'i, 2.4.8 serisi ise MySQL 8.4'ü ve MariaDB 11.4'ü destekliyor. Bu tablo yama sürümleriyle değiştiği için kurulumdan önce güncel hâline mutlaka bakın.
MySQL'den MariaDB'ye geçmek de "aynı şeyi kurmak" değil. Bir taşımada MySQL 8'den alınan döküm, MariaDB'nin tanımadığı utf8mb4_0900_ai_ci karşılaştırma kuralı yüzünden yarıda kesildi ve tabloların bir kısmı hiç yüklenmedi. Taşımadan sonra tablo ve kayıt sayılarını mutlaka kaynakla karşılaştırın.
Bellek bütçesi: veritabanı sunucuda yalnız değil
Küçük ve orta ölçekli mağazalarda veritabanı çoğu zaman PHP-FPM, OpenSearch ve Redis ile aynı sunucuda çalışıyor. MySQL belgelerindeki "belleğin %80'ine kadarını tampon belleğe verin" önerisi yalnızca veritabanına ayrılmış sunucular için geçerli. Paylaşılan bir sunucuda önce PHP-FPM'in en kötü durumda ne kadar bellek isteyeceğini hesaplayın. Bir kurulumda PHP-FPM süreç sınırı yanlış ayarlandığı için bellek tükendi ve işletim sistemi önce PHP'yi, ardından veritabanı sunucusunu kapattı.
Ne kadar tampon belleğe ihtiyacınız olduğunu görmek için önce veritabanınızın gerçek boyutunu öğrenin:
SELECT table_schema, ROUND(SUM(data_length + index_length) / 1024 / 1024) AS mb
FROM information_schema.tables
GROUP BY table_schema;
my.cnf ayarları
2016'da CentOS ve cPanel üzerinden anlatmıştım; CentOS'un yerini bugün AlmaLinux ve Rocky Linux gibi dağıtımlar aldı. Bu sistemlerde ayarlar genellikle /etc/my.cnf ya da /etc/my.cnf.d/ altındaki bir dosyanın [mysqld] bölümünde yapılır. Çoğunun geçerli olması için servisin yeniden başlatılması gerekir (systemctl restart mysqld ya da systemctl restart mariadb).
innodb_buffer_pool_size: En önemli ayar. InnoDB veriyi ve indeksleri bu tamponda tutar. İdeali, sık kullanılan verinin tamamının sığmasıdır; veritabanınız 2 GB ise 10 GB ayırmanın faydası yok.
innodb_redo_log_capacity / innodb_log_file_size: Büyük veritabanlarında yazma yoğunsa önem kazanır. MySQL 8.0.30 ve sonrasında innodb_log_file_size'ın yerini innodb_redo_log_capacity aldı; MariaDB'de hâlâ innodb_log_file_size kullanılıyor.
innodb_log_buffer_size: Varsayılan değer çoğu mağaza için yeterli; gereksiz yere yükseltmeyin.
innodb_flush_log_at_trx_commit: 2016'da hız için "2" yapmayı önermiştim. Bugün sipariş ve ödeme kaydı tutan bir mağaza için varsayılan "1"de bırakmanızı öneriyorum.
- 1: her işlemde günlük diske yazılır; en güvenlisi.
- 2: günlük her işlemde işletim sistemine verilir, diske saniyede bir aktarılır; elektrik kesintisinde ya da işletim sistemi çöktüğünde son bir saniyelik işlemler kaybolabilir.
- 0: veritabanı servisi çöktüğünde bile son bir saniyelik işlemler kaybolabilir.
Diskiniz yavaşsa çözüm bu ayarı gevşetmek değil, SSD'ye geçmektir.
table_open_cache ve table_definition_cache: 2016'daki adıyla table_cache. MySQL 8'in varsayılanları yüzlerce tablolu bir Magento için genellikle yeterli; Opened_tables durum değişkeni hızla artıyorsa yükseltin.
thread_cache_size: MySQL 8'de otomatik boyutlanıyor. Threads_created sürekli artıyorsa elle yükseltebilirsiniz.
max_connections: Her PHP süreci veritabanına kendi bağlantısını açar. Bu değer PHP-FPM'deki toplam süreç sayısını, cron'u ve kuyruk tüketicilerini rahatça karşılamalı; Adobe'nin önerisi de PHP iş parçacığı sayısıyla uyumlu olması yönünde.
tmp_table_size ve max_heap_table_size: Karmaşık sorgularda oluşan geçici tabloların bellekte mi diskte mi oluşacağını etkiler. Created_tmp_disk_tables hızla artıyorsa bakın. MySQL 8'de dahili geçici tablolar TempTable motoruyla yönetildiği için temptable_max_ram ayarı da devreye girer.
query_cache_size: 2016'da önerdiğim bu ayar MySQL 8.0 ile tamamen kaldırıldı. MariaDB'de hâlâ var ama varsayılan olarak kapalı geliyor; Magento gibi sürekli yazılan bir uygulamada açmanızı önermem.
slow_query_log: 2016'daki listede yoktu ama bugün ilk açtığım ayar. Uzun süren sorguları kaydeder; neyi iyileştireceğinizi tahmin etmek yerine görürsünüz.
16 GB bellekli, Magento, OpenSearch ve Redis'in aynı makinede çalıştığı bir sunucu için örnek başlangıç noktası (kendi ölçümlerinize göre değiştirin). MariaDB kullanıyorsanız innodb_redo_log_capacity satırını yazmayın; MariaDB bu ayarı tanımaz ve servis başlamaz.
[mysqld]
innodb_buffer_pool_size = 2G
# MySQL 8.0.30 ve sonrası:
innodb_redo_log_capacity = 1G
# MariaDB'de bir üstteki satırın yerine:
# innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
max_connections = 150
tmp_table_size = 64M
max_heap_table_size = 64M
slow_query_log = 1
long_query_time = 1
Magento tarafında veritabanını rahatlatan ayarlar
bin/magento indexer:set-mode schedule
bin/magento cron:install
bin/magento indexer:status
İndeksleyiciler "Update on Save" modundayken yönetim panelinde bir ürünü kaydetmek, ilgili indekslerin o anda yeniden hesaplanması demek. "Update by Schedule" modunda değişiklikler ayrı tablolara not edilir ve cron bunları arka planda işler. Bunun için cron'un gerçekten çalışması gerekir; çalışmayan bir cron, fark edilmeden indeksleri bayatlatır.
Cron geçmişi (cron_schedule tablosu) ve günlük dosyaları da zamanla büyür. Cron geçmişinin ne kadar tutulacağını Mağazalar › Yapılandırma › Gelişmiş › Sistem › Cron bölümünden ayarlayabilirsiniz. Günlük dosyalarının döndürüldüğünü de ayrıca kontrol edin; yönettiğim sunucularda yüzlerce megabaytlık cron günlüklerinin biriktiğini gördüm. Yedek alırken InnoDB tablolarını kilitlemeden tutarlı bir döküm için mysqldump --single-transaction kullanın.
Ölçmeden ayar yapmayın: MySQLTuner
Bu değerleri verdikten sonra MySQLTuner ile ölçüm yapıp daha doğru değerlere ulaşabilirsiniz:
wget https://mysqltuner.pl/ -O mysqltuner.pl
perl mysqltuner.pl --user kullanici_adi --pass parola
Veritabanı yeniden başlatıldıktan hemen sonra çalıştırırsanız öneriler yanıltıcı olur; en az 24 saat gerçek trafik aldıktan sonra çalıştırın. Program, veritabanının durumunu değerlendirip değiştirilmesi gereken ayarları listeler. Her seferinde tek bir ayarı değiştirin, servisi yeniden başlatın ve bir sonraki ölçümü bekleyin. Yavaş sorgu günlüğünü özetlemek için mysqldumpslow ya da Percona Toolkit'teki pt-query-digest işinizi görür.
Kolay gelsin.