MySQL Başlamıyor: Hata Log Analizi ile Sorun Giderme
Sabah 07:30, telefon çalıyor. “Hocam site açılmıyor, veritabanı çökmüş galiba.” Bu cümleyi kaç kez duydunuz? Ben saymaktan vazgeçtim. MySQL’in başlamayı reddettiği o panik anında yapmanız gereken tek şey var: soğukkanlılığı koruyun ve hata loglarına bakın. Çünkü MySQL, neden başlamadığını size zaten söylüyor. Sadece dinlemeyi bilmek gerekiyor.
Bu yazıda MySQL’in başlamama sorunlarını sistemli bir şekilde nasıl analiz edeceğinizi, hata loglarını nasıl okuyacağınızı ve en sık karşılaşılan senaryolarda ne yapmanız gerektiğini ele alacağız.
İlk Adım: Servisin Gerçekten Çalışmadığını Doğrulayın
Paniklemeden önce durumu netleştirin. Servis gerçekten mi duruyor, yoksa sadece yavaş mı çalışıyor?
# Systemd tabanlı sistemler (Ubuntu 16+, CentOS 7+, Debian 9+)
systemctl status mysql
systemctl status mysqld
# Eski sistemler
service mysql status
# Process direkt kontrol
ps aux | grep mysqld | grep -v grep
# Port dinleniyor mu?
ss -tlnp | grep 3306
netstat -tlnp | grep 3306
systemctl status çıktısında Active: failed veya Active: inactive (dead) görüyorsanız, evet MySQL çalışmıyor. Şimdi asıl işe başlayabiliriz.
Hata Logunu Bulmak
MySQL’in neden başlamadığını öğrenmek için önce hata logunu bulmanız gerekiyor. Log dosyasının konumu sisteme ve kurulum yöntemine göre değişiyor.
# MySQL konfigürasyon dosyasından log konumunu bul
grep -i "log_error" /etc/mysql/mysql.conf.d/mysqld.cnf
grep -i "log_error" /etc/mysql/my.cnf
grep -i "log_error" /etc/my.cnf
# MySQL'e direkt sor (eğer başlatabiliyorsanız)
mysql -e "SHOW VARIABLES LIKE 'log_error';"
# Yaygın log konumları
ls -la /var/log/mysql/error.log
ls -la /var/log/mysqld.log
ls -la /var/lib/mysql/*.err
Eğer hiçbir şey bulamazsanız, systemd journal son çare olarak oldukça işlevsel:
journalctl -u mysql --since "1 hour ago" --no-pager
journalctl -u mysqld -n 100 --no-pager
Log Dosyasını Okumak: Temel Mantık
MySQL hata logu üç tip kayıt içerir: bilgi mesajları [Note], uyarılar [Warning] ve hatalar [ERROR]. Başlamama sorunlarında doğrudan [ERROR] satırlarına atlayın ama öncesindeki [Warning] satırlarını da göz ardı etmeyin, çünkü bazen asıl ipucu orada gizlidir.
# Sadece hata ve uyarıları filtrele
grep -E "[ERROR]|[Warning]" /var/log/mysql/error.log | tail -50
# Son başlatma girişiminin loglarını görmek için
# MySQL her başlatmada genellikle bir timestamp bırakır
tail -100 /var/log/mysql/error.log
# Belirli bir tarihten itibaren
grep "2024-01-15" /var/log/mysql/error.log | grep -E "ERROR|Warning"
Şimdi en sık karşılaşılan hata senaryolarına geçelim.
Senaryo 1: InnoDB Log Dosyası Boyutu Uyumsuzluğu
Bu hata, özellikle MySQL versiyonunu yükselttiğinizde veya innodb_log_file_size değerini değiştirdiğinizde karşınıza çıkar.
Logda şunu görürsünüz:
[ERROR] InnoDB: The innodb_system data file 'ibdata1' must be writable
[ERROR] InnoDB: Log file ./ib_logfile0 is of different size 0 5242880 bytes
than specified in the .cnf file 0 67108864 bytes!
Bu durumda çözüm log dosyalarını silip MySQL’in yeniden oluşturmasına izin vermektir. Ama dikkat, bu işlemi yapmadan önce yedeğinizin var olduğundan emin olun.
# MySQL'i durdur
systemctl stop mysql
# Mevcut log dosyalarını yedekle ve sil
cd /var/lib/mysql
mv ib_logfile0 ib_logfile0.bak
mv ib_logfile0 ib_logfile1.bak
# MySQL'i başlat, yeni log dosyalarını oluşturacak
systemctl start mysql
# Başarılı olursa eski log dosyalarını sil
rm /var/lib/mysql/ib_logfile*.bak
Senaryo 2: Disk Dolu Hatası
Klasiklerden. Disk dolduğunda MySQL yeni veri yazamaz, transaction log’ları güncelleyemez ve çöker.
# Disk durumunu kontrol et
df -h
# MySQL data dizininin boyutunu kontrol et
du -sh /var/lib/mysql/
du -sh /var/lib/mysql/* | sort -rh | head -20
# En çok yer kaplayan MySQL tablolarını bul
find /var/lib/mysql -name "*.ibd" -exec du -sh {} ; | sort -rh | head -10
Logda genellikle şunu görürsünüz:
[ERROR] InnoDB: Attempted to open a previously opened tablespace
[ERROR] InnoDB: Error number 28 means 'No space left on device'
[ERROR] InnoDB: Could not create the shared memory area
Disk dolduğunda hızlı aksiyon:
# Büyük log dosyalarını temizle (MySQL logları dahil)
find /var/log -name "*.gz" -mtime +7 -delete
find /var/log -name "*.log.*" -mtime +7 -delete
# MySQL binary loglarını temizle (dikkatli kullanın!)
ls -lh /var/lib/mysql/mysql-bin.*
# MySQL içinden:
# PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY);
# Geçici dosyaları temizle
rm -rf /tmp/*.tmp
Senaryo 3: İzin Sorunları (Permission Issues)
MySQL genellikle mysql kullanıcısı altında çalışır. Eğer data dizininin sahipliği veya izinleri bozulduysa MySQL başlamayı reddeder.
# Data dizini izinlerini kontrol et
ls -la /var/lib/mysql/
ls -la /var/run/mysqld/
ls -la /var/log/mysql/
# MySQL kullanıcısını kontrol et
id mysql
Logda şu tarz mesajlar görürsünüz:
[ERROR] Can't start server: Bind on TCP/IP port: Address already in use
[ERROR] mysqld: Can't create/write to file '/var/lib/mysql/mysql.pid'
[ERROR] Fatal error: Can't open and lock privilege tables:
Table 'mysql.user' doesn't exist
İzin sorunlarını düzeltmek için:
# Sahiplik düzelt
chown -R mysql:mysql /var/lib/mysql
chown -R mysql:mysql /var/log/mysql
chown -R mysql:mysql /var/run/mysqld
# İzinleri düzelt
chmod 750 /var/lib/mysql
chmod 755 /var/log/mysql
chmod 755 /var/run/mysqld
# Eğer /var/run/mysqld dizini yoksa oluştur
mkdir -p /var/run/mysqld
chown mysql:mysql /var/run/mysqld
chmod 755 /var/run/mysqld
Senaryo 4: Port Çakışması (Address Already in Use)
Bazen MySQL process’i zombie olarak bellekte kalır ve port’u meşgul tutar. Ya da başka bir uygulama 3306 portunu kullanıyordur.
# 3306 portunu kim kullanıyor?
ss -tlnp | grep 3306
lsof -i :3306
# Eski MySQL process var mı?
ps aux | grep mysqld | grep -v grep
pgrep -a mysqld
# PID dosyasını kontrol et
cat /var/run/mysqld/mysqld.pid
cat /var/lib/mysql/*.pid
Eğer eski bir MySQL process takılı kalmışsa:
# Process'i bul ve öldür
MYSQL_PID=$(cat /var/run/mysqld/mysqld.pid 2>/dev/null)
if [ ! -z "$MYSQL_PID" ]; then
kill -9 $MYSQL_PID
fi
# PID dosyasını temizle
rm -f /var/run/mysqld/mysqld.pid
rm -f /var/lib/mysql/*.pid
# Servis tekrar başlat
systemctl start mysql
Senaryo 5: InnoDB Kurtarma Modu
Bu senaryo en zorlusudur. Beklenmedik sistem kapanması, güç kesintisi veya donanım hatası sonrasında InnoDB tablespace’i bozulabilir.
Logda şunları görürsünüz:
[ERROR] InnoDB: Page log sequence number 123456 is in the future!
[ERROR] InnoDB: Database page corruption on disk or a failed file read
[ERROR] InnoDB: space id and page id should be 0 1234,
but found 0 and 0. Recovery failed!
Bu durumda innodb_force_recovery parametresini kullanarak MySQL’i kurtarma modunda başlatmanız gerekir. 1’den 6’ya kadar giden bir ölçek var ve her seviye öncekinden daha agresif:
# /etc/mysql/mysql.conf.d/mysqld.cnf veya /etc/my.cnf dosyasını düzenle
# [mysqld] bölümüne ekle:
# Önce en düşük seviyeyle dene
innodb_force_recovery = 1
# MySQL'i başlat
systemctl start mysql
# Başladıysa hemen veri dışa aktar
mysqldump --all-databases > /backup/emergency_dump_$(date +%Y%m%d_%H%M%S).sql
# Eğer 1 çalışmadıysa sırayla 2, 3, 4, 5, 6 dene
# Her seviyede mysqldump almayı dene
Uyarı: Kurtarma modu 4, 5 ve 6’da veri kaybı yaşanabilir. Bu seviyelerde MySQL’i sadece veri kurtarmak için başlatın, asla üretim ortamında bu şekilde bırakmayın.
Verileri dışa aktardıktan sonra temiz bir kurulum yapın:
# Kurtarma satırını my.cnf'den sil veya yorum satırına al
# sed -i 's/innodb_force_recovery/#innodb_force_recovery/' /etc/mysql/mysql.conf.d/mysqld.cnf
# Eski InnoDB dosyalarını yedekle
mkdir /backup/innodb_old_$(date +%Y%m%d)
mv /var/lib/mysql/ibdata1 /backup/innodb_old_$(date +%Y%m%d)/
mv /var/lib/mysql/ib_logfile* /backup/innodb_old_$(date +%Y%m%d)/
# MySQL'i başlat (yeni InnoDB dosyaları oluşacak)
systemctl start mysql
# Verileri geri yükle
mysql < /backup/emergency_dump_*.sql
Senaryo 6: my.cnf Sözdizimi Hatası
Bazen sorun çok daha basittir. Konfigürasyon dosyasında yapılan yanlış bir değişiklik MySQL’in başlamasını engeller.
# Konfigürasyonu test et
mysqld --verbose --help 2>&1 | head -20
# Daha spesifik syntax kontrolü
mysqld --validate-config
# Hangi konfigürasyon dosyaları kullanılıyor?
mysql --help | grep -A 1 "Default options"
mysqld --help --verbose 2>/dev/null | grep "Default options" -A 3
Logda şunları görürsünüz:
[ERROR] unknown variable 'innodb-buffer-pool-size=4G'
[ERROR] Fatal error in defaults handling.
Program aborted!
Bu durumda en son değişikliğinizi geri alın. Eğer dosyayı versiyonlamıyorsanız (ki her zaman yapmalısınız), şu yaklaşımı deneyin:
# Konfigürasyon dosyasını yedekle
cp /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf.broken
# Minimal bir konfigürasyonla test et
cat > /tmp/minimal-my.cnf << 'EOF'
[mysqld]
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
EOF
mysqld --defaults-file=/tmp/minimal-my.cnf &
Senaryo 7: MySQL Upgrade Sonrası Tablo Uyumsuzluğu
MySQL’i version 5.7’den 8.0’a yükselttiğinizde sistem tablolarının güncellenmesi gerekir.
# Logda bu tarz bir şey görürsünüz:
# [ERROR] Column count of mysql.user is wrong. Expected 51, found 45.
# [ERROR] Fatal error: Can't open and lock privilege tables
# Upgrade sonrası çalıştırılması gereken komut
mysql_upgrade -u root -p
# MySQL 8.0'da bu otomatik yapılıyor ama manuel tetiklemek için:
mysqld --upgrade=FORCE
Sistematik Hata Ayıklama Akışı
Yukarıdaki senaryoları tek tek deneme yanılmayla değil, sistematik bir akışla ilerlemek çok daha verimli. Şu sırayı takip edin:
#!/bin/bash
# mysql-debug.sh - MySQL başlamama sorunu ilk müdahale scripti
echo "=== Disk Durumu ==="
df -h /var/lib/mysql
echo "=== MySQL Data Dizin İzinleri ==="
ls -la /var/lib/mysql/ | head -20
echo "=== Son 50 Log Satırı ==="
if [ -f /var/log/mysql/error.log ]; then
tail -50 /var/log/mysql/error.log
elif [ -f /var/log/mysqld.log ]; then
tail -50 /var/log/mysqld.log
else
journalctl -u mysql -n 50 --no-pager
fi
echo "=== 3306 Port Durumu ==="
ss -tlnp | grep 3306 || echo "Port kullanımda değil"
echo "=== MySQL Process Durumu ==="
ps aux | grep mysqld | grep -v grep || echo "MySQL process yok"
echo "=== Konfigürasyon Testi ==="
mysqld --validate-config 2>&1 || echo "Konfigürasyon hatası var!"
Önleyici Tedbirler
Yangın çıktıktan sonra söndürmek yerine, önceden hazırlıklı olmak çok daha akıllıca.
Monitoring kurulumu: MySQL’in çalışıp çalışmadığını her 60 saniyede bir kontrol eden basit bir script bile sizi saatlerce zaman kaybından kurtarabilir. Prometheus + MySQL Exporter, Zabbix veya sadece basit bir cron job yeterli olabilir.
Log rotasyonu: MySQL log dosyaları hızla büyüyebilir. Logrotate konfigürasyonunuzun düzgün çalıştığından emin olun:
# /etc/logrotate.d/mysql-server dosyasını kontrol et
cat /etc/logrotate.d/mysql-server
# Manuel test
logrotate -d /etc/logrotate.d/mysql-server
Düzenli yedekleme: Kurtarma senaryolarında en büyük güvenceniz yedeğinizdir. Günlük tam yedek ve binary log’larla point-in-time recovery yapabilirsiniz:
# Otomatik yedek için basit bir script
#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
mysqldump
--user=backup_user
--password=backup_pass
--all-databases
--single-transaction
--routines
--triggers
--events
--flush-logs
| gzip > $BACKUP_DIR/full_backup_$DATE.sql.gz
# 7 günden eski yedekleri sil
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
InnoDB konfigürasyonu: Düzgün ayarlanmış bir InnoDB konfigürasyonu hem performansı artırır hem de çökme sonrası kurtarma süresini kısaltır:
# my.cnf için önerilen temel InnoDB ayarları
# innodb_buffer_pool_size = RAM'in %70-80'i
# innodb_log_file_size = 512M (büyük veritabanları için)
# innodb_flush_log_at_trx_commit = 1 (güvenilir ama yavaş)
# innodb_flush_method = O_DIRECT
Logları Gerçek Zamanlı Takip Etmek
MySQL’i manuel başlatmaya çalışırken logları eş zamanlı takip etmek çok işe yarar:
# Bir terminal penceresi aç ve logları takip et
tail -f /var/log/mysql/error.log
# Diğer terminal penceresinde başlatmayı dene
systemctl start mysql
# Veya MySQL'i ön planda başlat (debug için)
mysqld --user=mysql --console 2>&1 | tee /tmp/mysql-debug.log
Sonuç
MySQL’in başlamama sorunu, ilk bakışta çok korkutucu görünse de mantıklı bir yaklaşımla genellikle hızlıca çözülebilir. Önemli olan paniklemeden önce hata loguna bakmak ve logların söylediklerini doğru okumaktır.
Karşılaştığım sorunların büyük çoğunluğu şu dört kategoride toplanıyor: disk dolması, izin sorunları, konfigürasyon hatası ve InnoDB bozulması. Bu dördünü nasıl çözeceğinizi biliyorsanız, üretim ortamındaki MySQL sorunlarının yüzde seksenini halledebilirsiniz.
Son olarak şunu vurgulamak isterim: her acil müdahalenin ardından o soruna karşı önleyici tedbir alın. Disk mi doldu? Disk kullanım alarmı kurun. İzin mi bozuldu? Deployment script’lerinizi gözden geçirin. Konfigürasyon mı bozuldu? my.cnf dosyalarını git’e alın. Her sorun, sisteminizi daha sağlam yapma fırsatıdır.
Bir dahaki “hocam site açılmıyor” telefonu geldiğinde, bu yazı açık olsun. İyi şanslar.
