Сторінка порожня. Або ще гірше: вона завантажується миттєво і показує той рядок, який змушує кожного інженера на виклику зітхнути — «Помилка встановлення з’єднання з базою даних.» Ваш CEO оновлює сторінку. Маркетинг «просто щось перевіряє». Моніторинг кричить, як чайник.
Ця помилка — не діагноз. Це WordPress каже: «Я запитав базу даних — і отримав тишу». Ваше завдання — з’ясувати, чи та тиша означає, що база даних упала, неправильна адреса, проблема з обліковими даними, перевантаження сервера або підсистема збереження даних тихо руйнується.
Що насправді означає помилка (і чого вона не означає)
WordPress відображає «Помилка встановлення з’єднання з базою даних», коли не може завершити початкове встановлення з’єднання з MySQL/MariaDB (або іншим сервером, сумісним з MySQL). Збій відбувається до того, як WordPress встигне виконати запити за опціями, користувачами чи постами, тому ви не бачите тему, вміст — лише повідомлення.
Технічно WordPress робить приблизно таке:
- Зчитує налаштування БД з
wp-config.php(DB_NAME, DB_USER, DB_PASSWORD, DB_HOST). - Ініціалізує драйвер клієнта бази даних (mysqli).
- Відкриває TCP-з’єднання (зазвичай порт 3306) або локальний сокет.
- Аутентифікується.
- Вибирає схему бази даних.
Якщо будь-який з цих кроків не вдається, вихід виглядає однаково. Саме тому найшвидше відновлення починається зі звуження області збоїв: мережа vs процес vs облікові дані vs насичення vs збереження.
Чого це не означає: зазвичай це не «баг WordPress». WordPress лише доставник повідомлення. Іноді доставник дратує, але повідомлення потрібно почути.
Два поширені сценарії:
- Повний крах: сервіс бази даних зупинився, аварійно завершив роботу або недоступний. Виправлення — оперативне.
- М’який крах: база даних жива, але відмовляється приймати з’єднання (занадто багато клієнтів, повільне сховище, блокування, проблема DNS, автентифікація). Виправлення часто пов’язане з пропускною здатністю або конфігурацією.
Цитата, яку варто прикріпити до вашого інцидент-процесу:
«Надія — це не стратегія.» — Генерал Гордон Р. Салліван
Швидкий план діагностики (першочергово/далі/після цього)
Коли сайт впав, «бути ретельним» — це спосіб пропустити SLA. Будьте швидкими, потім ретельними. Ось порядок дій, що рятує в продакшні.
Спочатку: підтвердіть, що саме пошкоджено з зовні
- Відкрийте сайт із чистого мережевого шляху (не ваш офісний VPN) і переконайтеся, що це не кешуючий шар, який віддає застарілі сторінки з помилкою.
- Перевірте, чи
/wp-admin/показує ту саму помилку. Якщо так — це не рендеринг теми; збій відбувається на ранній стадії ініціалізації БД. - Перевірте дашборди здоров’я серверів (CPU, load, пам’ять, затримки диска). Якщо затримки диска стрибають — підозрюйте БД, поки не доведено протилежне.
По-друге: ізолюйте мережу від сервісу
- Якщо БД віддалена: перевірте TCP-доступність до порту 3306 з веб-хосту.
- Якщо БД локальна: перевірте наявність Unix-сокета і що MySQL слухає.
- Перевірте резолюцію DNS для DB_HOST, якщо це ім’я хоста, а не IP.
По-третє: облікові дані та ємність
- Перевірте, що
wp-config.phpвідповідає реальним обліковим даним і хосту БД. - Перевірте MySQL на предмет «Too many connections», повільних запитів або відновлення InnoDB.
- Перевірте логи: PHP-FPM, Nginx/Apache, MySQL error log і системний журнал.
Правило великого пальця: якщо ви можете підключитися тими ж обліковими даними з веб-сервера — WordPress теж зможе. Якщо не можете — припиніть правити WordPress і виправляйте платформу.
Жарт №1: База даних не «відпочиває» — вона просто взяла вихідний день одразу після того, як ви почали свій.
Практичні завдання відновлення (команди, результати, рішення)
Нижче — практичні завдання, які ви можете виконати під час інциденту. Кожне містить: команду, що означає її вивід, і рішення, яке потрібно прийняти далі. Це те, що ви робите о 02:17.
Завдання 1: Підтвердити статус служби MySQL/MariaDB
cr0x@server:~$ sudo systemctl status mariadb --no-pager
● mariadb.service - MariaDB 10.11.6 database server
Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-12-26 01:58:12 UTC; 15min ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Main PID: 2143 (mariadbd)
Status: "Taking your SQL requests now..."
Tasks: 37 (limit: 18956)
Memory: 1.2G
CPU: 2min 41.121s
CGroup: /system.slice/mariadb.service
└─2143 /usr/sbin/mariadbd
Значення: Якщо він active (running), демон БД існує. Це не означає, що він приймає з’єднання, але він запущений.
Рішення: Якщо inactive, failed або демон перезапускається — переходьте до логів (Завдання 4) та перевірок збереження (Завдання 11/12) перед тим, як сліпо робити рестарт.
Завдання 2: Перевірити, чи MySQL слухає очікуваний інтерфейс/порт
cr0x@server:~$ sudo ss -lntp | grep -E ':(3306|33060)\b'
LISTEN 0 151 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=2143,fd=22))
Значення: Ця БД слухає лише localhost. Якщо ваш WordPress на іншому хості — він буде завжди падати.
Рішення: Якщо WordPress віддалений — виправте bind-address або використайте приватний мережевий інтерфейс. Якщо локальний — переконайтеся, що DB_HOST вказує на 127.0.0.1 або на сокет правильно.
Завдання 3: Перевірити резолюцію DNS для DB_HOST
cr0x@server:~$ getent hosts db.internal
10.10.2.15 db.internal
Значення: Ім’я резолюється. Якщо команда зависає або нічого не повертає — у вас проблема з DNS або резольвером (поширене під час мережевих інцидентів).
Рішення: Якщо пошкоджено — тимчасово зафіксуйте запис у /etc/hosts під час пом’якшення інциденту, а потім виправте DNS правильно.
Завдання 4: Перевірити лог помилок бази даних на предмет відновлення після збою, корупції або проблем з диском
cr0x@server:~$ sudo tail -n 60 /var/log/mysql/error.log
2025-12-26 02:10:44 0 [Note] InnoDB: Starting crash recovery.
2025-12-26 02:10:44 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
2025-12-26 02:10:47 0 [Note] InnoDB: Crash recovery finished.
2025-12-26 02:10:47 0 [Warning] Aborted connection 431 to db: 'wpdb' user: 'wpuser' host: '10.10.3.21' (Got timeout reading communication packets)
Значення: Відбулося відновлення після збою (тому стався crash або неакуратне завершення). Перервані з’єднання натякають на таймаути або мережеві затримки.
Рішення: Якщо відновлення повторюється в циклі або показує помилки вводу/виводу — припиніть звинувачувати WordPress. Перевірте затримки диска і стан файлової системи (Завдання 11–12).
Завдання 5: Перевірити підключення з веб-сервера тими ж обліковими даними, що й WordPress
cr0x@server:~$ grep -E "DB_(NAME|USER|PASSWORD|HOST)" /var/www/html/wp-config.php
define('DB_NAME', 'wpdb');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'correcthorsebatterystaple');
define('DB_HOST', 'db.internal');
cr0x@server:~$ mysql -h db.internal -u wpuser -p -e "SELECT 1;"
Enter password:
1
1
Значення: Якщо це вдається — мережа й облікові дані в порядку. WordPress теж повинен підключитися, тож проблема, ймовірно, у PHP-рантаймі, невідповідності сокетів або транзиторному насиченні.
Рішення: Якщо команда не вдається — повідомлення від mysql безцінне; дійте згідно з ним. «Access denied» означає проблеми з авторизацією/грантами. «Can’t connect» — мережа/слушатель/блокування портів. «Unknown MySQL server host» — DNS.
Завдання 6: Перевірити, чи MySQL відмовляє через max_connections
cr0x@server:~$ mysql -h db.internal -u root -p -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';"
Enter password:
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 498 |
+-------------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 500 |
+-----------------+-------+
Значення: Ви на краю прірви. Нові з’єднання буде відмовлено; WordPress викине загальну помилку.
Рішення: Негайне пом’якшення: зупиніть шторм з’єднань (кеш, обмеження швидкості, убийте зловмисних клієнтів, акуратно перезапустіть PHP-FPM). Потім виправте корінну причину: стратегія постійних з’єднань, продуктивність запитів, кількість процесів PHP-FPM і пулінг з’єднань (де це доречно).
Завдання 7: Виявити основні джерела з’єднань і що вони роблять
cr0x@server:~$ mysql -h db.internal -u root -p -e "SHOW FULL PROCESSLIST\G" | sed -n '1,80p'
Enter password:
*************************** 1. row ***************************
Id: 91231
User: wpuser
Host: 10.10.3.21:51344
db: wpdb
Command: Query
Time: 24
State: Sending data
Info: SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'
*************************** 2. row ***************************
Id: 91244
User: wpuser
Host: 10.10.3.21:51362
db: wpdb
Command: Query
Time: 29
State: Copying to tmp table
Info: SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts ...
Значення: Довготривалі запити, тимчасові таблиці та стан «Sending data» можуть вказувати на відсутність індексів, величезні набори результатів або повільне збереження.
Рішення: Якщо ви бачите повторюваний дорогий запит, тимчасово завершіть найгірших виконавців, щоб відновити сервіс, а потім додайте індекси або виправте плагін/тему, що його породжує.
Завдання 8: Убити вийшовший з-під контролю запит (хірургічно, не агресивно)
cr0x@server:~$ mysql -h db.internal -u root -p -e "KILL 91244;"
Enter password:
Значення: Потік завершено. Якщо він миттєво відроджується — щось б’є по базі (cron, трафік, бот, плагін).
Рішення: Якщо вбивство допомогло ненадовго — введіть контролі на трафік (правила WAF, кеш, адміністративне блокування) і шукайте джерело.
Завдання 9: Перевірити стан PHP-FPM і чергу (веб-рівень може бути винуватцем)
cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-12-26 01:55:02 UTC; 18min ago
Main PID: 1887 (php-fpm8.2)
Status: "Processes active: 52, idle: 1, Requests: 10432, slow: 219, Traffic: 0.6req/sec"
Значення: Якщо у вас багато активних воркерів, мало простих і зростають повільні запити — PHP насичений. Насичений PHP часто створює більше навантаження на БД через повторні запити, таймаути і «стади» повторних запитів.
Рішення: Якщо PHP-FPM завантажений — зменшіть конкурентність або додайте потужності. Не збільшуйте її сліпо; ви перетворите відмови БД на крах всього сервера.
Завдання 10: Перевірити відповідність сокета DB_HOST vs TCP
cr0x@server:~$ sudo ls -l /var/run/mysqld/
total 4
srwxrwxrwx 1 mysql mysql 0 Dec 26 01:58 mysqld.sock
-rw-r--r-- 1 mysql mysql 5 Dec 26 01:58 mysqld.pid
cr0x@server:~$ php -r 'echo ini_get("mysqli.default_socket"), PHP_EOL;'
/var/run/mysqld/mysqld.sock
Значення: Сокет існує і PHP очікує той самий шлях сокета. Якщо PHP очікує інший сокет — локальні підключення можуть падати, навіть коли БД запущена.
Рішення: Якщо невідповідність — встановіть DB_HOST на 127.0.0.1, щоб примусово використовувати TCP (швидка міра), або виправте налаштування сокета в конфігурації PHP (правильне рішення).
Завдання 11: Перевірити вільне місце на диску та вичерпання inode (класичний «БД помер»)
cr0x@server:~$ df -h /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 100G 99G 1.0G 99% /var
cr0x@server:~$ df -i /var/lib/mysql
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda2 6553600 6553200 400 100% /var
Значення: У вас вичерпані іноди. MySQL може «працювати», але не створювати тимчасові таблиці, файли redo або нові файли. WordPress бачить збої підключень або таймаути.
Рішення: Негайно звільніть місце/іноди (логи, кеші, старі бекапи), потім заплануйте правильне розподілення розділів/сховище. Вичерпання інодів — структурна проблема, а не тимчасовий настрій.
Завдання 12: Шукати I/O-«зависання», що робить БД брехливою (вона каже «запущена», але фактично застрягла)
cr0x@server:~$ iostat -xz 1 3
Linux 6.1.0 (server) 12/26/2025 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
10.21 0.00 5.02 42.11 0.00 42.66
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 8.00 120.00 256.0 6144.0 98.0 12.4 102.5 15.2 108.4 2.10 96.0
Значення: Високий %iowait і великий await з майже 100% завантаженням: ваш диск — вузьке місце. MySQL-запити зависатимуть; клієнти таймаутитимуть; WordPress повідомлятиме «не вдається підключитися».
Рішення: Зменшіть навантаження на запис (зупиніть «шумні» задачі, знизьте обсяг логування), перемістіть БД на швидше сховище або збільшіть вертикально ресурси. Якщо це спільний диск у віртуалці — можливо, ви стали жертвою «шумних сусідів».
Завдання 13: Перевірити помилки файлової системи або перемонтування в режим лише для читання
cr0x@server:~$ mount | grep ' /var '
/dev/sda2 on /var type ext4 (ro,relatime,errors=remount-ro)
cr0x@server:~$ sudo dmesg | tail -n 20
[12345.678901] EXT4-fs error (device sda2): ext4_journal_check_start:83: Detected aborted journal
[12345.678905] EXT4-fs (sda2): Remounting filesystem read-only
Значення: Файлова система перемонтована в режимі лише для читання через помилки. MySQL може продовжувати працювати, але не може писати — і тоді все розвалюється.
Рішення: Розглядайте це як інцидент збереження. Якщо можливо, коректно зупиніть MySQL, заплануйте fsck і відновлення з бекапів при необхідності. Не робіть героїчних дій на пошкодженій ФС — можна погіршити корупцію.
Завдання 14: Підтвердити, що WordPress не вказує на неправильний хост БД після міграції
cr0x@server:~$ sudo -u www-data php -r "require '/var/www/html/wp-config.php'; echo DB_HOST, PHP_EOL;"
db.internal
cr0x@server:~$ ping -c 1 db.internal
PING db.internal (10.10.2.15) 56(84) bytes of data.
64 bytes from 10.10.2.15: icmp_seq=1 ttl=63 time=0.493 ms
Значення: Конфігурація WordPress резолюється і хост доступний на рівні ICMP. (ICMP не доводить доступність TCP-сервісу, але це швидка перевірка здоров’я.)
Рішення: Якщо ping працює, але MySQL — ні, зосередьтеся на фаєрволі та слухачі БД. Якщо обидва не працюють — у вас проблеми з маршрутизацією або DNS.
Завдання 15: Перевірити гранти користувача з боку БД (несумісність віддаленого хоста — класика)
cr0x@server:~$ mysql -u root -p -e "SHOW GRANTS FOR 'wpuser'@'10.10.3.%';"
Enter password:
+--------------------------------------------------------------------------------------------------+
| Grants for wpuser@10.10.3.% |
+--------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `wpdb`.* TO `wpuser`@`10.10.3.%` |
+--------------------------------------------------------------------------------------------------+
Значення: Користувачу дозволено підключення з тієї підмережі. Якщо у вас лише 'wpuser'@'localhost', віддалені підключення будуть падати з «Access denied».
Рішення: Виправте гранти відповідно до реальності. Після міграцій припущення про «localhost» — тихі вбивці.
Завдання 16: Виявити пошкоджену таблицю і виконати відносно безпечний ремонт (MyISAM) або обережну перевірку (InnoDB)
cr0x@server:~$ mysql -h db.internal -u root -p -e "CHECK TABLE wpdb.wp_options;"
Enter password:
+------------------+-------+----------+--------------------------------+
| Table | Op | Msg_type | Msg_text |
+------------------+-------+----------+--------------------------------+
| wpdb.wp_options | check | status | OK |
+------------------+-------+----------+--------------------------------+
Значення: Базова перевірка цілісності відповідає OK. Якщо ви бачите «corrupt» для MyISAM-таблиць — REPAIR TABLE може допомогти. Для InnoDB корупція — значно серйозніша історія.
Рішення: Якщо виявлено корупцію і ви використовуєте InnoDB: пріоритет — відновлення з бекапів або обережні режими відновлення InnoDB. «Repair» не є чарівною паличкою для InnoDB.
Типові помилки: симптом → корінна причина → виправлення
Цей розділ навмисно конкретний. Загальні поради — це те, як відмови стають повторюваними подіями у календарі.
1) Симптом: помилка з’являється після зміни DNS або міграції
- Корінна причина:
DB_HOSTвказує на старе ім’я/IP, або TTL DNS + кешування продовжують спрямовувати деякі сервери до старої БД. - Виправлення: Підтвердіть
DB_HOSTна кожному веб-вузлі; очистьте локальні DNS-кеші там, де потрібно; тримайте кінцеву точку БД стабільною (VIP/CNAME) і мігруйте за її зачином.
2) Симптом: періодичні помилки під час піків трафіку, при низькому трафіку все в порядку
- Корінна причина: MySQL досягає
max_connections, PHP-FPM має забагато воркерів або у вас «стадо» на некешованих сторінках. - Виправлення: Додайте кешування для навантажених маршрутів, обмежте конкурентність PHP-FPM, збільште потужності БД і припиніть ілюзії «масштабування тільки вебу», якщо БД — вузьке місце.
3) Симптом: сервіс БД «працює», але з’єднання таймаутяться
- Корінна причина: I/O-«зависання», файлову систему перемонтовано в режим лише для читання, або InnoDB застряг у режимі відновлення/очікуванні скидання.
- Виправлення: Виміряйте затримку диска, перевірте
dmesgі прапори монтовання, зменшіть навантаження на запис і перемістіть БД на правильне сховище при потребі.
4) Симптом: «Access denied for user» після зміни пароля
- Корінна причина: WordPress використовує старі облікові дані; конфіг-менеджмент не пропагував зміни; або гранти користувача залежать від конкретного хоста й ідентичність хоста змінилась.
- Виправлення: Оновіть
wp-config.phpпослідовно, перевірте гранти для підключаючого хоста і оберніть секрети через контрольований процес (не вставляйте паролі в Slack і не сподівайтеся на щастя).
5) Симптом: помилка з’являється тільки на деяких сторінках (адмін працює, публічний сайт ні)
- Корінна причина: кеш/CDN віддає застарілі сторінки з помилкою; або плагін викликає важкі запити лише на певних маршрутах.
- Виправлення: Очищуйте кеші, відключіть CDN для діагностики, потім профілюйте повільні запити, прив’язані до тих маршрутів.
6) Симптом: помилка з’явилася відразу після увімкнення «плагіна для прискорення»
- Корінна причина: об’єктний кеш неправильно налаштовано (невірна точка Redis), агресивний cron/heartbeat або плагін штормить БД некешованими запитами.
- Виправлення: Вимкніть плагін, щоб відновити сервіс, потім повертайте його поступово з навантажувальним тестуванням. Роби «оптимізацію» без метрик — це рукоділля.
7) Симптом: «MySQL server has gone away», а потім WordPress показує помилку підключення
- Корінна причина: max_allowed_packet занадто малий для великих запитів, таймаути для неактивних з’єднань, перезапуск БД або обриви мережі.
- Виправлення: Перевірте логи БД на предмет рестартів, налаштуйте таймаути та
max_allowed_packetза потреби, і забезпечте надійність мережевого шляху між шарами.
Сторона збереження: режими відмов файлової системи, що маскуються під «БД недоступна»
Непопулярна правда інженера збереження: багато інцидентів «підключення до бази даних» — це інциденти зі сховищем, які носять фальшиві вуса.
Затримка диска — проблема з підключенням у маскуванні
Якщо InnoDB не може зробити flush, він застосує зворотний тиск. Запити ставляться в чергу. Потоки накопичуються. З’єднання таймаутяться. З точки зору WordPress, база даних може так само добре бути відключеною.
Слід слідкувати за:
- Високий тиск fsync: flush-і логів redo затримуються на повільних дисках.
- «Шторми» свопінгу: тиск пам’яті БД виштовхує сторінки; затримки зростають експоненціально.
- Підсилення записів: тимчасові таблиці на диску, великі сортування, стани
Copying to tmp table.
Вичерпання інодів: дурний шлях до падіння
Бази даних створюють файли, тимчасові таблиці, binlog і redo-логи. Якщо інодів не вистачає, ОС ввічливо відмовить у створенні файлів. MySQL менш ввічливий. WordPress покаже ту саму загальну помилку, бо інакше й бути не може.
Перемонтування в режим тільки для читання: тиха катастрофа
Ext4 з errors=remount-ro робить вам послугу: він не дозволяє погіршити корупцію. Але це перетворює кожну операцію запису на помилку, а бази даних — переважно операції запису під прикриттям читання.
Мережеве сховище і «сьогодні БД повільна»
Якщо ваша база даних на мережевому сховищі, перевантажений масив може призвести до секундних латентностей на блоці. MySQL буде терпляче чекати. Клієнти — ні. Якщо ви в хмарі на спільних томах, вас також можуть «тротлити». ОС рідко оголошує це з фанфарами; вона просто стає повільною.
Запобігання, яке дійсно працює (без абстракцій)
Запобігання — це не «додайте CPU». Для надійності БД WordPress запобігання — це контроль конкурентності, стабілізація латентності сховища і видимість збоїв до того, як вони стануть повідомленням на головній сторінці.
1) Розмістіть базу даних на сховищі, що поводиться під навантаженням
- Використовуйте SSD/NVMe-клас сховище для директорії даних MySQL і redo-логів.
- Надавайте перевагу локальному NVMe замість «магічних IOPS» мережевих томів для сайтів з великим трафіком.
- Моніторьте затримку диска (
await,%util) так само, як моніторите CPU.
2) Обмежуйте конкурентність на веб-рівні
Якщо PHP-FPM дозволено запустити маленьку армію — він це зробить. Кожен воркер відкриває з’єднання з БД, і ваша база перетворюється на найсумнішого «швейцара у нічному клубі».
- Встановіть розумне
pm.max_childrenвиходячи з CPU, пам’яті і можливостей БД. - Використовуйте кешування для анонімного трафіку. Більшість сторінок WordPress не повинні звертатись до БД при кожному запиті.
- Обмежте доступ до точок входу входу й XML-RPC, якщо вони не потрібні.
3) Робіть «підключення до БД» моніторинговим SLO, а не забобоном
Моніторте:
- TCP-час підключення з веб-вузлів до БД (синтетичні перевірки).
- MySQL
Threads_connected,Threads_runningі кількість перерваних з’єднань. - Затримки диска і лічильники помилок файлової системи.
- Сплески обсягу логів повільних запитів.
4) Резервні копії, які відновлюються, а не просто існують
Бекап, який не відновлювався — це казка на добраніч. Працюйте відновлення регулярно, включно з:
- Логічними дампами для портативності (
mysqldumpабо еквівалент). - Фізичними бекапами для швидкості (снапшоти на рівні файлів або спеціальні інструменти резервного копіювання).
- Відновленням до точки часу, якщо у вас є binlog і план.
5) Уникайте одноточкових відмов, якщо це важливо
Не кожен сайт на WordPress потребує HA, але якщо ваш бізнес залежить — побудуйте:
- Primary/replica зі автоматичним фейловером (ретельно протестованим).
- Окремі веб- та БД-шари, щоб масштабування одного не дестабілізувало іншого.
- Health checks, що перевіряють «БД приймає з’єднання і може виконувати запит», а не лише «порт відкритий».
6) Тримайте WordPress в розумі: зменшуйте навантаження запитів і неприємні сюрпризи
- Аудитуйте плагіни. Кожен плагін — потенційний DBA, якого ви не наймали.
- Правильно використовуйте об’єктний кеш (і моніторьте його).
- Підтримуйте WordPress core і PHP в актуальному стані для поліпшень продуктивності й стабільності.
Жарт №2: Плагін обіцяв «оптимізацію в один клік», що було правдою — один клік достатній, щоб оптимізувати ваш сайт до відмови.
Чеклісти / покроковий план
Під час інциденту: чекліст стабілізації за 15 хвилин
- Підтвердьте вплив: це всі сторінки чи підмножина? Чи кешує CDN помилку?
- Перевірте здоров’я БД: статус служби, слухач, логи.
- Перевірте з веб-хоста: підключіться за допомогою
mysqlз обліковими даними WordPress. - Перевірте насичення: з’єднання, виконувані потоки, повільні запити.
- Перевірте збереження: диск заповнений, inode вичерпано, I/O wait, режим read-only.
- М’яке пом’якшення: зменшіть конкурентність (тимчасово), вбийте довгі запити, відключіть проблемний плагін за необхідності.
- Комунікація: встановіть чіткий графік оновлень про те, що відомо і що робиться далі.
Після стабілізації: чекліст встановлення кореневої причини (той самий день)
- Витягніть вікна помилок з MySQL, PHP-FPM і веб-серверів.
- Зкорелюйте з метриками: з’єднання, затримка диска, CPU, пам’ять, помилки мережі.
- Визначте тригер: пік трафіку, деплой, зміни плагінів, подія збереження, зміна DNS.
- Запишіть точний режим відмови (наприклад, досягнуто
max_connections, вичерпано inode, read-only remount). - Впровадьте зміну для запобігання з планом відкотування.
- Додайте/підкоригуйте моніторинг так, щоб наступного разу це сталося раніше (або ніколи).
Чекліст посилення (щотижня/щомісяця)
- Періодично тестуйте відновлення з бекапів.
- Переглядайте список плагінів і видаляйте зайві.
- Переглядайте повільні запити і можливості для індексів.
- Слідкуйте за тенденціями зростання диска і використання інодів.
- Патчуйте OS, БД, PHP контрольовано.
- Переглядайте співвідношення capacity: кількість воркерів PHP-FPM vs max_connections БД vs апаратні можливості.
Три корпоративні міні-історії з практики
Міні-історія 1: Інцидент, спричинений хибним припущенням
Компанія мала «просту» архітектуру: кілька веб-вузлів і керована служба бази даних. Команда мігрувала WordPress на нові веб-сервери для отримання новішого PHP і кращого CPU. Усе виглядало добре в стадії. Продакшн-міграція була запланована на тиху ранкову годину.
Після переключення DNS і приходу трафіку через кілька хвилин з’явилося: Помилка встановлення з’єднання з базою даних. Метрики бази даних виглядали нормально. БД «вгору». Веб-вузли були здорові. Природно, усі дивилися на WordPress, ніби він їх підвів особисто.
Хибне припущення ховалося в одному рядку: DB_HOST був встановлений в localhost на старих серверах, бо раніше БД стояла на тому ж хості багато років тому. Під час попередніх міграцій хтось «тимчасово» використав SSH-тунель і ніколи не прибрав логіку конфігурації. На нових серверах локального MySQL не було. WordPress намагався підключитися до самого себе. Він прогнозовано падав.
Виправлення було тривіальним: вказати DB_HOST на керований кінцевий пункт БД, задеплоїти — і все. Тривалий урок був не в «оновіть DB_HOST». Він полягав у тому, щоб не дозволяти дрейф інфраструктури жити всередині конфігів застосунку без тестів, які підтверджують топологію. Команда додала preflight-перевірку для валідації підключення БД з кожного веб-вузла перед будь-яким DNS-flip.
Міні-історія 2: Оптимізація, що зіграла проти
В іншій організації була вимога покращити продуктивність. Сторінки були повільні, і хтось запропонував: «збільшимо воркерів PHP-FPM, щоб запити не ставали в чергу». Звучало розумно. Веб-сервери мали вільний CPU. Зміна була розгорнута вдень, бо ризик «здавався малим».
Результат був миттєвим: WordPress почав інтермітентно викидати помилки підключення до БД. Не повний крах — але достатньо, щоб зіпсувати конверсії і змусити службу підтримки відчувати себе переслідуваною. MySQL досягав ліміту з’єднань, і латентність запитів злетіла. БД не була розрахована на таку одночасну кількість. Більше воркерів PHP означало більше одночасних з’єднань БД, більше кеш-місій і більше тиску на InnoDB flush.
Команда зробила те інстинктивне: підняла max_connections. Це купило кілька хвилин, потім сервер втратив пам’ять і почав свопитись. Тепер усе було повільним: БД, веб-вузли, навіть SSH-підключення. Це вже був каскад виснаження ресурсів.
Відкат це виправив. Довгострокове рішення було нудним: додати кеш для анонімного трафіку, встановити розумні ліміти для PHP-FPM, додати індекси для найгірших запитів і масштабувати сховище/IOPS для БД. Найбільша «оптимізація» була просто не генерувати непотрібну роботу.
Міні-історія 3: Нудна але правильна практика, що врятувала день
Медіакомпанія запускала WordPress як частину більшої платформи. БД була одна primary з warm replica. Нічого складного. Вражала їхня дисципліна: регулярні тести відновлення і задокументований runbook фейловера в тому ж репозиторії, що і інфраструктурний код.
Одного дня primary DB-хост зазнав помилок файлової системи після оновлення ядра і перезавантаження. Він повернувся, але том даних перемонтувався в режим лише для читання. MySQL стартував, а потім поступово виходив з ладу, намагаючись писати. WordPress показав помилку підключення. У них було близько п’яти хвилин плутанини, потім on-call розпізнав паттерн: «запущений, але не може писати».
Вони не намагались робити геройські дії на пошкодженій файловій системі. Виконали runbook: підняли репліку, оновили кінцеву точку БД і перезапустили веб-вузли, щоб очистити застарілі з’єднання. Трафік швидко відновився. Пізніше primary відремонтували офлайн і знову посіяли коректно.
Врятувала не магічна автоматизація, а відрепетировані, нудні компетенції: бекапи перевірені, кроки фейловера відомі, і команда, яка не вірить у безсмертя файлових систем.
Цікаві факти та контекст (коротко й конкретно)
- Факт 1: WordPress почався в 2003 році, і залежність від MySQL була з самого початку; помилка «підключення до БД» переслідує адміністраторів уже два десятиліття.
- Факт 2: Багато років стандартним драйвером бази даних у WordPress був старий розширення
mysql; сучасні інсталяції використовуютьmysqli, що змінює поведінку сокетів і таймаутів. - Факт 3: Поведінка MySQL при «Too many connections» відома своєю різкістю: щойно досягнуто ліміт, нові сесії відкидаються негайно, навіть якщо сервер загалом здоровий.
- Факт 4: InnoDB став дефолтним рушієм у MySQL 5.5; раніше MyISAM був поширений, і «ремонт таблиці» був частішою практикою.
- Факт 5: TTL DNS може утримувати старі кінцеві точки БД в кешах клієнтів значно довше, ніж очікується, особливо через контейнерні резольвери та локальні демон-кешери.
- Факт 6: Плутанина Unix-сокета vs TCP старша за WordPress: клієнти можуть підміняти сокети для «localhost» і TCP для «127.0.0.1», що може змінювати шляхи автентифікації і дозволи.
- Факт 7: Багато плагінів WordPress реалізують власні кеші погано; неправильно налаштований об’єктний кеш може збільшити навантаження на БД замість його зменшення.
- Факт 8: Час відновлення InnoDB пропорційний розміру redo-логу і робочому навантаженню; після збою «БД вгору» може означати «БД зайнята відновленням».
- Факт 9: Файлові системи перемонтовані в режим read-only при помилках — це функція безпеки, а не баг — бази даних її дуже не люблять.
Питання й відповіді (FAQ)
1) Чому WordPress показує ту саму помилку для різних відмов?
Тому що збій відбувається на етапі підключення, до того, як WordPress зможе завантажити опції або виконати вагомі запити. Він не може розрізнити «неправильний пароль» від «хост БД горить» без розкриття деталей. Потрібні перевірки на рівні платформи.
2) Чи варто негайно перезапускати MySQL?
Тільки після перевірки логів і симптомів сховища. Перезапуск може допомогти, якщо демон завис, але також може погіршити відновлення після збою або сховати реальну проблему. Якщо бачите помилки диска або перемонтування в read-only — рестарт це культ.
3) Як зрозуміти, що це облікові дані, а не підключення?
Запустіть mysql -h ... -u ... -p -e "SELECT 1;" з веб-сервера, використовуючи облікові дані з wp-config.php. «Access denied» — питання auth/grants. «Can’t connect» — мережа/слухач/фаєрвол. Таймаути часто означають насичення або I/O-зависання.
4) Чому це трапляється лише під час піків трафіку?
Тому що конкурентність множить усе. Більше запитів → більше PHP-воркерів → більше з’єднань до БД → більше блокувань і тиску на flush. Якщо ви поруч з лімітом — пік перекидає вас у відмову та таймаути.
5) Чи добрий варіант збільшити max_connections?
Іноді це тимчасовий пластир. У довгостроковій перспективі це може спричинити зворотний ефект через збільшення використання пам’яті і контекстних перемикань. Виправляйте сторону попиту (кеш, оптимізація запитів, обмеження швидкості) і сторону пропозиції (ресурси БД) разом.
6) Чи може повний диск спричинити помилку підключення до бази даних?
Так. Заповнений диск або відсутність інодів може завадити MySQL створювати тимчасові таблиці або писати логи, що призводить до зависань і збоїв, які на рівні застосунку виглядають як проблеми підключення.
7) Яке найшвидше безпечне пом’якшення, якщо БД перевантажена?
Спочатку зменшіть навантаження: увімкніть/перевірте кеш сторінок для анонімного трафіку, обмежте зловмисні кінцеві точки і капніть воркери PHP-FPM. Вбивство найгірших запитів може купити час, але це не стратегія сама по собі.
8) Як запобігти меланню БД, спричинену плагінами?
Проводьте зміни плагінів як деплои: поетапний реліз, порівняння метрик і план відкату. Аудит плагінів щоквартально. Менше коду — менше хаосу.
9) Чому перемикання DB_HOST з localhost на 127.0.0.1 інколи «виправляє» проблему?
Тому що це примушує використовувати TCP замість Unix-сокета. Якщо шлях сокета неправильний або права доступу дивні — TCP може обійти проблему. Це валідна міра, але справжнє виправлення — узгодити конфігурацію сокета.
10) Якщо база віддалена, що найчастіше ховається за проблемою?
Найпоширеніший прихований винуватець — надійність мережевого шляху і резолюція імен. «Маленька» зміна DNS, правило фаєрволу або проблема маршрутизації може виглядати точно як відмова БД для WordPress.
Висновок: кроки, які можна зробити сьогодні
Ця помилка WordPress — симптом, а не причина. Ставтесь до неї як до продакшн-інциденту: швидко ізолюйте домен збоїв, застосуйте хірургічні пом’якшення, а потім виправте базову проблему ємності/конфігурації/сховища, щоб вона не повторювалася.
- Напишіть свій швидкий діагностичний рукопис з використанням описаних завдань, підлаштуйте під своє середовище (локальна БД vs керована, сокет vs TCP).
- Додайте два монітори сьогодні: синтетичний запит з вебу до БД і моніторинг латентності диска на хості/томі БД.
- Обмежте конкурентність (PHP-FPM і веб-сервер) на основі можливостей БД, а не бажань.
- Відновіть тестові бекапи цього тижня. Не «перевірте, що вони є» — відновіть їх.
- Аудитуйте плагіни і видаліть усе, що не підтримується, надмірне або «тимчасово встановлене» з 2019 року.