Помилка MySQL: Сервер завершив роботу без оновлення PID-файлу — Повний посібник з діагностики та усунення несправностей
Помилка "The server quit without updating PID file" означає, що MySQL завершив роботу до того, як зміг записати свій ідентифікатор процесу до налаштованого файлу `.pid` — жорстка зупинка, яка перешкоджає демону приймати з’єднання. Ця помилка майже завжди є симптомом глибшої проблеми: неправильна конфігурація в `my.cnf`, невідповідність прав доступу до каталогу даних, переповнений дисковий розділ, пошкодження на рівні таблиць або конфлікт портів з другим екземпляром MySQL або MariaDB.
Цей посібник розглядає кожну підтверджену першопричину, надає точні команди оболонки для діагностики та усунення кожної з них, а також охоплює граничні випадки, які типові посібники зазвичай пропускають.
Що насправді робить PID-файл і чому його відсутність має значення
MySQL записує свій ідентифікатор процесу (PID) до невеликого текстового файлу — зазвичай `/var/run/mysqld/mysqld.pid` — одразу після ініціалізації демона. Init-системи, менеджери служб (systemd, SysVinit) та інструменти моніторингу зчитують цей файл, щоб надсилати сигнали до правильного процесу. Якщо MySQL аварійно завершує роботу, виходить ненормально або стикається з фатальною помилкою під час запуску, він ніколи не досягає точки запису цього файлу. Менеджер служб тоді повідомляє про помилку "quit without updating PID file".
Розуміння цієї послідовності є критично важливим: помилка PID-файлу є *наслідком*, а не першопричиною. Переслідування самого PID-файлу без попереднього читання журналу помилок — це найпоширеніша помилка, яку роблять адміністратори.
Поширені першопричини на перший погляд
| Першопричина | Типовий симптом у журналі помилок | Уражені системи |
|---|---|---|
| — | — | — |
| Неправильний шлях `pid-file` у `my.cnf` | `Can't start server: can't create PID file` | Усі дистрибутиви |
| Неправильний власник `/var/run/mysqld` | `Permission denied` на каталозі PID | Debian/Ubuntu після оновлень |
| Переповнений диск або вичерпання inode | `No space left on device` | Будь-який сервер з малим `/var` |
| Пошкоджений `ibdata1` або журнали повторного виконання InnoDB | `InnoDB: Corruption detected` | MySQL 5.7, 8.0, MariaDB |
| Застарілий файл `.pid` від попереднього збою | `A mysqld process already exists` | Будь-яка система після жорсткого перезавантаження |
| Порт 3306 вже використовується | `Can't start server: Bind on TCP/IP port` | Налаштування з кількома екземплярами |
| Відмова політики AppArmor або SELinux | `apparmor="DENIED"` у syslog | Ubuntu, RHEL/CentOS |
| Невідповідний `datadir` після оновлення пакету | `[ERROR] Fatal error: Can't open and lock privilege tables` | Оновлення основних версій |
Крок 1 — Спочатку прочитайте журнал помилок MySQL
Кожен наступний крок залежить від того, що говорить журнал помилок. Не пропускайте цей крок.
“`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` або `InnoDB`. Перший запис `[ERROR]` у послідовності запуску майже завжди є справжньою причиною.
Крок 2 — Перевірте та виправте каталог PID-файлу
Каталог PID часто відтворюється з власником `root` після перезавантаження системи, оскільки `/var/run` є монтуванням `tmpfs` у сучасних дистрибутивах Linux. Це одна з найчастіше overlooked причин на Ubuntu 20.04+ та Debian 11+.
“`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
“`
Щоб зробити це постійним після перезавантажень на системах systemd, створіть правило `tmpfiles.d`:
“`bash
echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf
“`
Переконайтеся, що шлях PID, налаштований у `my.cnf`, відповідає щойно створеному каталогу:
“`bash
sudo grep -i "pid" /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/*.cnf 2>/dev/null
“`
Крок 3 — Перевірте власника та права доступу до каталогу даних
Каталог даних MySQL повинен повністю належати системному користувачу `mysql`. Оновлення пакетів, ручне копіювання файлів або відновлення з резервної копії часто порушують це.
“`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 {} ;
“`
Важливий граничний випадок: Якщо ви відновили резервну копію за допомогою `rsync` або `cp` від імені `root`, файл сокета `/var/lib/mysql/mysql.sock` також може належати root. Видаліть його — MySQL відтворить його під час запуску:
“`bash
sudo rm -f /var/lib/mysql/mysql.sock
sudo rm -f /var/run/mysqld/mysqld.sock
“`
Крок 4 — Перевірте наявність вільного місця на диску та доступність inode
Переповнений диск непомітно перешкоджає MySQL записувати будь-який файл, включаючи PID-файл та бінарні журнали.
“`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
“`
Якщо розділ переповнений, типовими винуватцями є бінарні журнали (`mysql-bin.000*`), загальні журнали запитів, випадково залишені увімкненими, або файли core dump. Щоб безпечно очистити старі бінарні журнали зсередини MySQL:
“`bash
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
“`
Крок 5 — Усуньте застарілі PID-файли та конфліктуючі процеси
Після паніки ядра, відключення живлення або `kill -9`, застарілий PID-файл може залишитися на диску. MySQL відмовляється запускатися, якщо знаходить такий файл.
“`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
“`
Якщо інший екземпляр MySQL або MariaDB справді працює та займає порт 3306:
“`bash
sudo ss -tlnp | grep 3306
sudo systemctl stop mariadb
sudo systemctl stop mysql
sudo killall -9 mysqld mysqld_safe
“`
Зачекайте три секунди після завершення процесів перед спробою перезапуску, щоб дозволити станам TIME_WAIT сокетів ядра очиститися.
Крок 6 — Перевірте політики AppArmor та SELinux
Ця причина майже ніколи не згадується в базових посібниках, проте вона відповідає за значний відсоток помилок PID-файлу на Ubuntu та системах сімейства RHEL.
Ubuntu / AppArmor:
“`bash
sudo dmesg | grep -i apparmor | grep -i mysql
sudo grep -i "DENIED" /var/log/syslog | grep mysql
“`
Якщо AppArmor блокує MySQL, або оновіть профіль, або тимчасово встановіть режим скарг для діагностики:
“`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
“`
Поширене виправлення проблем контексту SELinux після переміщення каталогу даних:
“`bash
sudo semanage fcontext -a -t mysqld_db_t "/new/datadir(/.*)?"
sudo restorecon -Rv /new/datadir
“`
Крок 7 — Діагностика та відновлення після пошкодження InnoDB
Якщо журнал помилок містить повідомлення на кшталт `InnoDB: Corruption detected`, `[ERROR] InnoDB: Unable to lock ./ibdata1` або посилання на невідповідності журналу повторного виконання, табличний простір InnoDB пошкоджений.
Для таблиць MyISAM використовуйте `mysqlcheck`:
“`bash
sudo mysqlcheck –all-databases –repair –user=root –password
“`
При пошкодженні InnoDB `mysqlcheck` недостатньо. Правильний підхід — увімкнути режим примусового відновлення InnoDB у `my.cnf`:
“`ini
[mysqld]
innodb_force_recovery = 1
“`
Запустіть MySQL з цим налаштуванням, негайно зробіть дамп усіх баз даних, потім відновіть:
“`bash
mysqldump –all-databases –single-transaction -u root -p > full_backup.sql
“`
Збільшуйте `innodb_force_recovery` від 1 до 6 лише якщо нижчі значення не дозволяють запустити сервер. На рівні 4 і вище можлива втрата даних — ставтеся до екземпляра як до режиму лише для читання та негайно виконайте експорт.
Після успішного дампу:
“`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
“`
Крок 8 — Виявлення помилок конфігурації в my.cnf
Одна помилка друку або недійсна директива в `my.cnf` призведе до переривання запуску до запису PID-файлу. MySQL 8.0+ є суворішим щодо невідомих параметрів, ніж 5.7.
“`bash
Validate configuration without starting the server
mysqld –validate-config
Or test with verbose output
mysqld –verbose –help > /dev/null
“`
Зробіть резервну копію та скиньте конфігурацію до стандартних значень:
“`bash
sudo cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak.$(date +%F)
“`
Поширені проблемні директиви після оновлень основних версій включають застарілі параметри, такі як `query_cache_size`, `query_cache_type`, `innodb_file_format` та `innodb_large_prefix` — усі видалені в MySQL 8.0.
Крок 9 — Перезапустіть MySQL та перевірте
“`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
“`
Крок 10 — Перевстановлення MySQL (крайній захід зі збереженням даних)
Перевстановлення слід виконувати лише після вичерпання кожного діагностичного кроку вище. Перед продовженням зробіть резервну копію всіх даних:
“`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)/
“`
Потім видаліть та перевстановіть:
“`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
“`
Відновіть з дампу:
“`bash
mysql -u root -p < /backup/full_$(date +%F).sql
“`
Вибір правильного хостингового середовища для запобігання повторенню
Багато з цих збоїв — вичерпання диска, скидання прав доступу після перезавантажень, конкуренція ресурсів від спільно розміщених служб — є проблемами інфраструктури не менше, ніж проблемами MySQL. Запуск виробничої бази даних на належно підготовленому сервері з виділеними ресурсами усуває цілі категорії цих помилок.
Якщо ви керуєте додатком на основі MySQL, середовище VPS Хостинг надає вам повний root-доступ, ізольовані ресурси та можливість налаштовувати `tmpfiles.d`, профілі AppArmor та перевизначення одиниць systemd без обмежень. Для баз даних з високим трафіком, що потребують гарантованих IOPS та RAM, Виділені сервери повністю усувають будь-які проблеми спільного використання ресурсів.
Для команд, які надають перевагу керованій панелі управління, а не прямому адмініструванню через CLI, VPS з cPanel надає інтерфейси управління MySQL поряд з доступом на рівні сервера. Якщо ваш стек також потребує налаштування домену та DNS, Реєстрація доменів та SSL-сертифікати можна керувати від одного провайдера, зменшуючи операційні витрати.
Матриця рішень: яке виправлення застосувати першим
| Симптом у журналі помилок | Перша дія | Орієнтовний час вирішення |
|---|---|---|
| — | — | — |
| `Permission denied` на PID або каталозі даних | Виправте власника за допомогою `chown mysql:mysql` | 2 хвилини |
| `No space left on device` | Очистіть бінарні журнали, розширте диск | 5–30 хвилин |
| `A mysqld process already exists` | Видаліть застарілий PID-файл, завершіть осиротілий процес | 2 хвилини |
| `Bind on TCP/IP port: Address already in use` | Зупиніть конфліктуючий екземпляр, перевірте `ss -tlnp` | 5 хвилин |
| `InnoDB: Corruption detected` | Увімкніть `innodb_force_recovery`, зробіть дамп, відновіть | 30 хвилин — кілька годин |
| `apparmor="DENIED"` у syslog | Оновіть профіль AppArmor або встановіть режим скарг | 10 хвилин |
| `unknown variable` у журналі | Запустіть `mysqld –validate-config`, виправте `my.cnf` | 5 хвилин |
| Немає конкретної помилки, все інше не допомогло | Перевстановіть MySQL, відновіть з резервної копії | 1–2 години |
Технічний контрольний список ключових висновків
- Завжди читайте `/var/log/mysql/error.log` або `/var/log/mysqld.log` перед тим, як торкатися будь-якого файлу — перший рядок `[ERROR]` визначає справжню причину.
- На системах systemd з `tmpfs` на `/var/run`, створіть постійне правило `/etc/tmpfiles.d/mysqld.conf`, щоб запобігти скиданню прав доступу при кожному перезавантаженні.
- Після будь-якого `rsync` або ручного відновлення резервної копії запустіть `chown -R mysql:mysql /var/lib/mysql` перед спробою запустити MySQL.
- Перевіряйте `df -i` (використання inode) поряд з `df -h` (місце на диску) — повна таблиця inode дає ідентичні симптоми переповненому диску.
- При пошкодженні InnoDB використовуйте `innodb_force_recovery` поступово від 1 вгору; ніколи не переходьте одразу до рівня 6.
- Перевіряйте синтаксис `my.cnf` за допомогою `mysqld –validate-config` перед перезапуском — це виявляє помилки друку без невдалої спроби запуску.
- Видаліть застарілі директиви MySQL 5.7 (`query_cache_*`, `innodb_file_format`) перед оновленням до MySQL 8.0.
- На Ubuntu перевіряйте відмови AppArmor у `/var/log/syslog`; на RHEL/AlmaLinux перевіряйте SELinux за допомогою `ausearch -c mysqld`.
Часті запитання
Який найшвидший спосіб дізнатися, чому MySQL не запустився?
Запустіть `sudo tail -50 /var/log/mysql/error.log` та знайдіть перший рядок, що містить `[ERROR]` або `[FATAL]`. Цей єдиний рядок визначає першопричину у переважній більшості випадків та визначає, яке виправлення застосувати.
Чому каталог PID втрачає права доступу після перезавантаження?
У дистрибутивах Linux, що використовують `tmpfs` для `/var/run` (включаючи Ubuntu 18.04+ та Debian 10+), все дерево `/var/run` відтворюється в пам’яті під час завантаження. Будь-який каталог, не визначений у `/etc/tmpfiles.d/`, відтворюється з власником `root:root`. Виправлення полягає в додаванні правила `tmpfiles.d`: `echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf`.
Чи можна відновити дані, якщо MySQL взагалі не запускається через пошкодження InnoDB?
Так, у більшості випадків. Встановіть `innodb_force_recovery = 1` у `my.cnf`, запустіть MySQL та негайно виконайте `mysqldump –all-databases`. Якщо рівень 1 не запускає сервер, збільшіть до 2, потім до 3 і так далі. На рівнях 4–6 деякі дані можуть бути невідновлюваними, але більшість таблиць зазвичай залишається цілою.
Як запобігти тому, щоб помилка "no space left on device" знову не зупиняла MySQL?
Увімкніть термін дії бінарних журналів: встановіть `binlog_expire_logs_seconds = 604800` (7 днів) у `my.cnf`. Крім того, вимкніть загальний журнал запитів у виробництві (`general_log = 0`) та налаштуйте сповіщення про використання диска на рівні 80% через вашу систему моніторингу.
Чи виникає ця помилка також на MariaDB, і чи однакове виправлення?
Так. MariaDB використовує той самий механізм PID-файлу та ту саму структуру каталогу даних, що й MySQL. Усі діагностичні кроки в цьому посібнику безпосередньо застосовуються до MariaDB, з єдиною відмінністю: ім’я служби — `mariadb` замість `mysql` у командах `systemctl`, а журнал помилок може знаходитися за адресою `/var/log/mariadb/mariadb.log` залежно від дистрибутива.
