MySQL Hatası: Sunucu PID Dosyasını Güncellemeden Kapandı — Eksiksiz Tanılama ve Düzeltme Kılavuzu
The "The server quit without updating PID file" hatası, MySQL’in yapılandırılmış `.pid` dosyasına işlem tanımlayıcısını yazamadan sonlandığı anlamına gelir — bu, daemon’ın bağlantıları kabul etmesini engelleyen tam bir duruştur. Bu hata neredeyse her zaman daha derin bir sorunun belirtisidir: `my.cnf` içindeki yanlış bir yapılandırma, veri dizinindeki izin uyuşmazlığı, dolu disk bölümü, tablo düzeyinde bozulma veya ikinci bir MySQL ya da MariaDB örneğiyle port çakışması.
Bu kılavuz, tüm doğrulanmış kök nedenleri ele alır, her birini teşhis etmek ve onarmak için tam kabuk komutları sağlar ve genel eğitimlerin rutin olarak atladığı uç durumları kapsar.
PID Dosyasının Gerçekte Ne İşe Yaradığı ve Yokluğunun Neden Önemli Olduğu
MySQL, daemon başlatıldıktan hemen sonra işlem kimliğini (PID) küçük bir düz metin dosyasına yazar — genellikle `/var/run/mysqld/mysqld.pid`. Init sistemleri, servis yöneticileri (systemd, SysVinit) ve izleme araçları, doğru işleme sinyal göndermek için bu dosyayı okur. MySQL çöker, anormal şekilde çıkar veya başlatma sırasında ölümcül bir hatayla karşılaşırsa, o dosyayı yazma noktasına hiç ulaşamaz. Servis yöneticisi daha sonra "quit without updating PID file" mesajını bildirir.
Bu sırayı anlamak kritik öneme sahiptir: PID dosyası hatası bir *sonuçtur*, kök neden değildir. Önce hata günlüğünü okumadan PID dosyasının peşine düşmek, yöneticilerin yaptığı en yaygın tek hatadır.
Yaygın Kök Nedenlere Genel Bakış
| Kök Neden | Hata Günlüğündeki Tipik Belirti | Etkilenen Sistemler |
|---|---|---|
| — | — | — |
| `my.cnf` içinde yanlış `pid-file` yolu | `Can't start server: can't create PID file` | Tüm dağıtımlar |
| `/var/run/mysqld` üzerinde yanlış sahiplik | PID dizininde `Permission denied` | Yükseltmeler sonrası Debian/Ubuntu |
| Dolu disk veya inode tükenmesi | `No space left on device` | Küçük `/var` olan herhangi bir sunucu |
| Bozulmuş `ibdata1` veya InnoDB yineleme günlükleri | `InnoDB: Corruption detected` | MySQL 5.7, 8.0, MariaDB |
| Önceki bir çökmeden kalan eski `.pid` dosyası | `A mysqld process already exists` | Zorla yeniden başlatma sonrası herhangi bir sistem |
| 3306 portu zaten kullanımda | `Can't start server: Bind on TCP/IP port` | Çoklu örnek kurulumları |
| AppArmor veya SELinux politika reddi | syslog’da `apparmor="DENIED"` | Ubuntu, RHEL/CentOS |
| Paket yükseltmesi sonrası uyumsuz `datadir` | `[ERROR] Fatal error: Can't open and lock privilege tables` | Ana sürüm yükseltmeleri |
Adım 1 — Önce MySQL Hata Günlüğünü Okuyun
Diğer tüm adımlar hata günlüğünün ne söylediğine bağlıdır. Bu adımı atlamayın.
“`bash
Debian/Ubuntu default path
sudo tail -100 /var/log/mysql/error.log
RHEL/CentOS/AlmaLinux default path
sudo tail -100 /var/log/mysqld.log
If you are unsure of the path, query the running config
mysqld –verbose –help 2>/dev/null | grep "log-error"
“`
`[ERROR]`, `[FATAL]`, `Aborting` veya `InnoDB` içeren satırları arayın. Başlatma sırasındaki ilk `[ERROR]` girişi neredeyse her zaman gerçek nedendir.
Adım 2 — PID Dosyası Dizinini Doğrulayın ve Düzeltin
PID dizini, modern Linux dağıtımlarında `/var/run` bir `tmpfs` bağlama noktası olduğundan sistem yeniden başlatıldıktan sonra genellikle `root` sahipliğiyle yeniden oluşturulur. Bu, Ubuntu 20.04+ ve Debian 11+’da en sık gözden kaçırılan nedenlerden biridir.
“`bash
Check current ownership
ls -ld /var/run/mysqld
Recreate the directory with correct ownership
sudo mkdir -p /var/run/mysqld
sudo chown mysql:mysql /var/run/mysqld
sudo chmod 755 /var/run/mysqld
“`
Bunu systemd sistemlerinde yeniden başlatmalar arasında kalıcı hale getirmek için bir `tmpfiles.d` kuralı oluşturun:
“`bash
echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf
“`
`my.cnf` içinde yapılandırılan PID yolunun az önce oluşturduğunuz dizinle eşleştiğini doğrulayın:
“`bash
sudo grep -i "pid" /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/*.cnf 2>/dev/null
“`
Adım 3 — Veri Dizini Sahipliğini ve İzinlerini Denetleyin
MySQL’in veri dizini tamamen `mysql` sistem kullanıcısına ait olmalıdır. Paket yükseltmeleri, manuel dosya kopyaları veya yedekten geri yüklemeler bunu sıklıkla bozar.
“`bash
Correct ownership recursively
sudo chown -R mysql:mysql /var/lib/mysql
Correct permissions — directories 750, files 640 is more secure than 755/644
sudo find /var/lib/mysql -type d -exec chmod 750 {} ;
sudo find /var/lib/mysql -type f -exec chmod 640 {} ;
“`
Önemli uç durum: `root` olarak `rsync` veya `cp` kullanarak bir yedek geri yüklediyseniz, `/var/lib/mysql/mysql.sock` soket dosyası da root sahipliğinde olabilir. Onu kaldırın — MySQL başlatma sırasında yeniden oluşturacaktır:
“`bash
sudo rm -f /var/lib/mysql/mysql.sock
sudo rm -f /var/run/mysqld/mysqld.sock
“`
Adım 4 — Disk Alanını ve Inode Kullanılabilirliğini Kontrol Edin
Dolu bir disk, MySQL’in PID dosyası ve ikili günlükler dahil herhangi bir dosya yazmasını sessizce engeller.
“`bash
Check disk space
df -h
Check inode usage — often overlooked
df -i
Find the largest directories consuming space
sudo du -sh /var/lib/mysql/* | sort -rh | head -20
“`
Bölüm doluysa, yaygın suçlular ikili günlükler (`mysql-bin.000*`), yanlışlıkla etkin bırakılan genel sorgu günlükleri veya çekirdek döküm dosyalarıdır. MySQL içinden eski ikili günlükleri güvenle temizlemek için:
“`bash
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
“`
Adım 5 — Eski PID Dosyalarını ve Çakışan İşlemleri Ortadan Kaldırın
Bir çekirdek paniği, güç kesintisi veya `kill -9` sonrasında, eski bir PID dosyası diskte kalabilir. MySQL bir tane bulursa başlamayı reddeder.
“`bash
Check for a stale PID file
cat /var/run/mysqld/mysqld.pid
Verify whether that PID is actually running
ps aux | grep mysqld
If the process is not running but the file exists, remove it
sudo rm -f /var/run/mysqld/mysqld.pid
“`
Başka bir MySQL veya MariaDB örneği gerçekten çalışıyor ve 3306 portunu işgal ediyorsa:
“`bash
sudo ss -tlnp | grep 3306
sudo systemctl stop mariadb
sudo systemctl stop mysql
sudo killall -9 mysqld mysqld_safe
“`
Çekirdek soket TIME_WAIT durumlarının temizlenmesine izin vermek için işlemleri öldürdükten sonra yeniden başlatmayı denemeden önce üç saniye bekleyin.
Adım 6 — AppArmor ve SELinux Politikalarını Kontrol Edin
Bu neden temel eğitimlerde neredeyse hiç bahsedilmez, ancak Ubuntu ve RHEL ailesi sistemlerde PID dosyası hatalarının önemli bir yüzdesinden sorumludur.
Ubuntu / AppArmor:
“`bash
sudo dmesg | grep -i apparmor | grep -i mysql
sudo grep -i "DENIED" /var/log/syslog | grep mysql
“`
AppArmor MySQL’i engelliyorsa, profili güncelleyin veya teşhis için geçici olarak şikayet moduna alın:
“`bash
sudo aa-complain /usr/sbin/mysqld
“`
RHEL / CentOS / AlmaLinux — SELinux:
“`bash
sudo ausearch -c 'mysqld' –raw | audit2why
sudo sealert -a /var/log/audit/audit.log | grep mysqld
“`
Veri dizinini taşıdıktan sonra SELinux bağlam sorunları için yaygın bir düzeltme:
“`bash
sudo semanage fcontext -a -t mysqld_db_t "/new/datadir(/.*)?"
sudo restorecon -Rv /new/datadir
“`
Adım 7 — InnoDB Bozulmasını Teşhis Edin ve Onarın
Hata günlüğü `InnoDB: Corruption detected`, `[ERROR] InnoDB: Unable to lock ./ibdata1` gibi mesajlar veya yineleme günlüğü tutarsızlıklarına atıflar içeriyorsa, InnoDB tablo alanının kendisi zarar görmüştür.
MyISAM tabloları için `mysqlcheck` kullanın:
“`bash
sudo mysqlcheck –all-databases –repair –user=root –password
“`
InnoDB bozulması için `mysqlcheck` yetersizdir. Doğru yaklaşım, `my.cnf` içinde InnoDB zorla kurtarma modunu etkinleştirmektir:
“`ini
[mysqld]
innodb_force_recovery = 1
“`
MySQL’i bu ayarla başlatın, hemen tüm veritabanlarını dökün, ardından yeniden oluşturun:
“`bash
mysqldump –all-databases –single-transaction -u root -p > full_backup.sql
“`
`innodb_force_recovery`’ı yalnızca daha düşük değerler sunucuyu başlatmakta başarısız olursa 1’den 6’ya kadar artırın. 4 ve üzeri seviyelerde veri kaybı mümkündür — örneği salt okunur olarak değerlendirin ve hemen dışa aktarın.
Başarılı bir döküm sonrasında:
“`bash
sudo systemctl stop mysql
sudo rm -rf /var/lib/mysql/ib_logfile* # Remove corrupt redo logs
Remove innodb_force_recovery from my.cnf
sudo systemctl start mysql
mysql -u root -p < full_backup.sql
“`
Adım 8 — my.cnf İçindeki Yapılandırma Hatalarını Yalıtın
`my.cnf` içindeki tek bir yazım hatası veya geçersiz bir yönerge, PID dosyası yazılmadan önce başlatmayı iptal edecektir. MySQL 8.0+, bilinmeyen seçenekler konusunda 5.7’den daha katıdır.
“`bash
Validate configuration without starting the server
mysqld –validate-config
Or test with verbose output
mysqld –verbose –help > /dev/null
“`
Yapılandırmayı yedekleyin ve varsayılanlara indirgeyin:
“`bash
sudo cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak.$(date +%F)
“`
Ana sürüm yükseltmelerinden sonra sorun çıkaran yaygın yönergeler arasında MySQL 8.0’da kaldırılan `query_cache_size`, `query_cache_type`, `innodb_file_format` ve `innodb_large_prefix` gibi kullanımdan kaldırılmış seçenekler bulunur.
Adım 9 — MySQL’i Yeniden Başlatın ve Doğrulayın
“`bash
sudo systemctl restart mysql
Check service status
sudo systemctl status mysql
Confirm the PID file was written
cat /var/run/mysqld/mysqld.pid
Confirm MySQL is accepting connections
mysqladmin -u root -p status
“`
Adım 10 — MySQL’i Yeniden Yükleme (Veri Korumayla Son Çare)
Yeniden yükleme yalnızca yukarıdaki her teşhis adımını tükettikten sonra yapılmalıdır. Devam etmeden önce tüm verileri yedekleyin:
“`bash
If MySQL can start in recovery mode, dump first
mysqldump –all-databases -u root -p > /backup/full_$(date +%F).sql
Copy raw data directory as a secondary backup
sudo rsync -av /var/lib/mysql/ /backup/mysql_datadir_$(date +%F)/
“`
Ardından kaldırın ve yeniden yükleyin:
“`bash
sudo systemctl stop mysql
sudo apt-get remove –purge mysql-server mysql-client mysql-common
sudo apt-get autoremove && sudo apt-get autoclean
sudo rm -rf /var/lib/mysql /etc/mysql
sudo apt-get install mysql-server
sudo mysql_secure_installation
“`
Döküm dosyasından geri yükleyin:
“`bash
mysql -u root -p < /backup/full_$(date +%F).sql
“`
Yinelemeyi Önlemek İçin Doğru Barındırma Ortamını Seçme
Bu hataların çoğu — disk tükenmesi, yeniden başlatmalar sonrası izin sıfırlamaları, birlikte barındırılan hizmetlerden kaynaklanan kaynak çekişmesi — MySQL sorunları olduğu kadar altyapı sorunlarıdır. Üretim veritabanını ayrılmış kaynaklara sahip düzgün sağlanmış bir sunucuda çalıştırmak, bu hataların tüm kategorilerini ortadan kaldırır.
MySQL destekli bir uygulama yönetiyorsanız, VPS Hosting ortamı size tam root erişimi, yalıtılmış kaynaklar ve kısıtlama olmaksızın `tmpfiles.d`, AppArmor profilleri ve systemd birim geçersiz kılmalarını yapılandırma imkânı sunar. Garantili IOPS ve RAM gerektiren yüksek trafikli veritabanları için Dedicated Servers tüm kaynak paylaşımı endişelerini tamamen ortadan kaldırır.
Doğrudan CLI yönetimi yerine yönetilen bir kontrol paneli tercih eden ekipler için VPS with cPanel, sunucu düzeyinde erişimin yanı sıra MySQL yönetim arayüzleri sağlar. Yığınınız ayrıca domain ve DNS yapılandırması gerektiriyorsa, Domain Registration ve SSL Certificates aynı sağlayıcıdan yönetilerek operasyonel yükü azaltabilir.
Karar Matrisi: Hangi Düzeltmeyi Önce Uygulamalı
| Hata Günlüğündeki Belirti | İlk Eylem | Tahmini Çözüm Süresi |
|---|---|---|
| — | — | — |
| PID veya veri dizininde `Permission denied` | `chown mysql:mysql` ile sahipliği düzeltin | 2 dakika |
| `No space left on device` | İkili günlükleri temizleyin, diski genişletin | 5–30 dakika |
| `A mysqld process already exists` | Eski PID dosyasını kaldırın, yetim işlemi sonlandırın | 2 dakika |
| `Bind on TCP/IP port: Address already in use` | Çakışan örneği durdurun, `ss -tlnp` kontrol edin | 5 dakika |
| `InnoDB: Corruption detected` | `innodb_force_recovery` etkinleştirin, dökün, yeniden oluşturun | 30 dakika ile birkaç saat |
| syslog’da `apparmor="DENIED"` | AppArmor profilini güncelleyin veya şikayet modunu ayarlayın | 10 dakika |
| Günlükte `unknown variable` | `mysqld –validate-config` çalıştırın, `my.cnf` düzeltin | 5 dakika |
| Belirli hata yok, diğer her şey başarısız | MySQL’i yeniden yükleyin, yedekten geri yükleyin | 1–2 saat |
Teknik Temel Çıkarımlar Kontrol Listesi
- Herhangi bir dosyaya dokunmadan önce her zaman `/var/log/mysql/error.log` veya `/var/log/mysqld.log` okuyun — ilk `[ERROR]` satırı gerçek nedeni tanımlar.
- `/var/run` üzerinde `tmpfs` olan systemd sistemlerinde, her yeniden başlatmada izin sıfırlamalarını önlemek için kalıcı bir `/etc/tmpfiles.d/mysqld.conf` kuralı oluşturun.
- Herhangi bir `rsync` veya manuel yedek geri yüklemesinin ardından MySQL’i başlatmayı denemeden önce `chown -R mysql:mysql /var/lib/mysql` çalıştırın.
- `df -i` (inode kullanımı) ile birlikte `df -h`’i (disk alanı) kontrol edin — dolu bir inode tablosu, dolu bir diskle aynı belirtileri üretir.
- InnoDB bozulması için `innodb_force_recovery`’ı 1’den yukarıya doğru artımlı olarak kullanın; doğrudan 6. seviyeye atlamayın.
- Başarısız bir başlatma girişimi olmadan yazım hatalarını yakalamak için yeniden başlatmadan önce `mysqld –validate-config` ile `my.cnf` sözdizimini doğrulayın.
- MySQL 8.0’a yükseltmeden önce kullanımdan kaldırılmış MySQL 5.7 yönergelerini (`query_cache_*`, `innodb_file_format`) kaldırın.
- Ubuntu’da `/var/log/syslog` içindeki AppArmor redlerini kontrol edin; RHEL/AlmaLinux’ta `ausearch -c mysqld` ile SELinux’u kontrol edin.
Sıkça Sorulan Sorular
MySQL’in neden başlatılamadığını bulmanın en hızlı yolu nedir?
`sudo tail -50 /var/log/mysql/error.log` çalıştırın ve `[ERROR]` veya `[FATAL]` içeren ilk satırı arayın. Bu tek satır, vakaların büyük çoğunluğunda kök nedeni tanımlar ve hangi düzeltmenin uygulanacağını belirler.
PID dizini neden yeniden başlatma sonrasında izinlerini kaybeder?
`/var/run` için `tmpfs` kullanan Linux dağıtımlarında (Ubuntu 18.04+ ve Debian 10+ dahil), tüm `/var/run` ağacı önyükleme sırasında bellekte yeniden oluşturulur. `/etc/tmpfiles.d/` içinde tanımlanmayan herhangi bir dizin `root:root` olarak yeniden oluşturulur. Düzeltme, bir `tmpfiles.d` kuralı eklemektir: `echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf`.
InnoDB bozulması nedeniyle MySQL hiç başlamıyorsa verileri kurtarabilir miyim?
Evet, çoğu durumda. `my.cnf` içinde `innodb_force_recovery = 1` ayarlayın, MySQL’i başlatın ve hemen `mysqldump –all-databases` çalıştırın. 1. seviye sunucuyu başlatmazsa 2’ye, ardından 3’e ve böyle devam edin. 4–6. seviyelerde bazı veriler kurtarılamaz olabilir, ancak tabloların büyük çoğunluğu genellikle sağlamdır.
MySQL’i tekrar çökertmemesi için "no space left on device" hatasını nasıl önlerim?
İkili günlük süresinin dolmasını etkinleştirin: `my.cnf` içinde `binlog_expire_logs_seconds = 604800` (7 gün) ayarlayın. Ayrıca üretimde genel sorgu günlüğünü devre dışı bırakın (`general_log = 0`) ve izleme sisteminiz aracılığıyla %80 kapasitede bir disk kullanım uyarısı kurun.
Bu hata MariaDB’de de oluşur mu ve düzeltme aynı mıdır?
Evet. MariaDB, MySQL ile aynı PID dosyası mekanizmasını ve aynı veri dizini yapısını kullanır. Bu kılavuzdaki tüm teşhis adımları doğrudan MariaDB için de geçerlidir; tek fark, `systemctl` komutlarında servis adının `mysql` yerine `mariadb` olması ve dağıtıma bağlı olarak hata günlüğünün `/var/log/mariadb/mariadb.log` konumunda bulunabilmesidir.
