Błąd nawiązywania połączenia z bazą danych. Ścieżka diagnostyczna
Wpisujesz adres swojej strony, a zamiast niej dostajesz jedno zdanie na białym tle: Error establishing a database connection. Żadnego menu, żadnych stylów, żadnej podpowiedzi. Kokpit też nie działa, więc nawet nie masz gdzie zajrzeć.
Zacznę od dobrej wiadomości, bo to zwykle pierwsze pytanie, które słyszę przez telefon: prawie na pewno nic nie zginęło. Wpisy, produkty, zamówienia i konta klientów siedzą w bazie dokładnie tam, gdzie były. Ten komunikat nie mówi „baza zniknęła”, tylko „nie udało mi się do niej dostać”. To dwie zupełnie różne rzeczy.
Poniżej znajdziesz kolejność, w jakiej sam podchodzę do takiej awarii. Od rzeczy najczęstszych do najrzadszych, tak żeby nie tracić czasu na egzotykę, zanim sprawdzisz oczywistości.
Co ten komunikat naprawdę oznacza
WordPress przy każdym wejściu na stronę musi połączyć się z bazą danych MySQL lub MariaDB. Dane potrzebne do tego połączenia trzyma w jednym pliku, wp-config.php, w czterech stałych: nazwa bazy, nazwa użytkownika, hasło i adres serwera bazy. Jeśli którakolwiek z nich jest zła albo serwer bazy nie odpowiada, WordPress przerywa ładowanie i wyświetla ten komunikat.
Warto od razu odróżnić trzy różne ekrany, bo prowadzą w trzy różne strony:
- Error establishing a database connection na całej stronie. Połączenie w ogóle nie dochodzi do skutku. To temat tego wpisu.
- One or more database tables are unavailable w kokpicie. Połączenie działa, ale konkretne tabele są uszkodzone albo niedostępne.
- Ekran instalacji WordPressa, ten z wyborem języka. Połączenie działa, baza istnieje, tylko WordPress nie widzi w niej swoich tabel. Najczęściej wina leży w złym prefiksie tabel albo w niekompletnym imporcie po migracji.
Jeśli widzisz ekran instalacji, przerwij i nie klikaj dalej. Kliknięcie „Zainstaluj” w takiej sytuacji potrafi nadpisać dane, które jeszcze dało się uratować.
Zanim zaczniesz: trzy pytania, które skracają szukanie o połowę
- Co zmieniło się w ciągu ostatniej doby? Migracja na nowy serwer, zmiana hasła do bazy w panelu hostingu, aktualizacja PHP, zmiana pakietu, nieopłacona faktura, ktoś nowy dostał dostęp do FTP. Jeśli coś się zmieniło, tam zwykle jest przyczyna.
- Błąd jest wszędzie, czy tylko w jednym miejscu? Sprawdź stronę główną i osobno adres
/wp-admin/. Bywa, że front pokazuje jeszcze stronę z cache, a dopiero panel się wysypuje. - Czy na tym samym koncie hostingowym masz inne strony? Jeśli tak i one też leżą, to nie jest problem WordPressa.
Krok 1. Ustal, po czyjej stronie jest problem
Zaloguj się do panelu hostingu i spróbuj wejść do phpMyAdmin (albo Adminera, zależnie od firmy). To najszybszy test, jaki znam, bo omija WordPressa całkowicie.
- phpMyAdmin się nie otwiera albo zgłasza własny błąd połączenia: serwer bazy leży. Twoje pliki nie mają z tym nic wspólnego. Zgłoś awarię do hostingu i sprawdź jego stronę statusu.
- phpMyAdmin się otwiera, ale nie widzisz na liście swojej bazy: baza została usunięta, przeniesiona albo Twój użytkownik stracił do niej dostęp.
- phpMyAdmin działa i baza jest na miejscu, z tabelami w środku: serwer bazy żyje, więc problem leży w danych dostępowych albo w uprawnieniach. Przechodzisz do kroku drugiego.
Przy okazji sprawdź, czy konto nie zostało zawieszone. Brzmi banalnie, ale kilka razy w roku trafiam na sytuację, w której cała diagnostyka kończy się na niezapłaconej fakturze albo na przekroczonym limicie transferu.
Krok 2. wp-config.php, czyli miejsce, w którym kończy się większość przypadków
Plik wp-config.php leży w głównym katalogu instalacji, obok folderów wp-admin i wp-content. Dostaniesz się do niego przez FTP albo przez menedżer plików w panelu hostingu.
Zanim cokolwiek zmienisz, zrób kopię tego pliku. Wystarczy pobrać go na dysk albo skopiować na serwerze pod nazwą wp-config-kopia.txt. Uwaga na rozszerzenie: kopia z rozszerzeniem .php.bak albo .txt nie zostanie wykonana przez serwer, a wp-config.php.old w niektórych konfiguracjach da się pobrać z przeglądarki razem z hasłem w środku. Najbezpieczniej trzymać kopię poza katalogiem publicznym albo po prostu na własnym komputerze.
Interesują Cię cztery linie:
define( 'DB_NAME', 'nazwa_bazy' );
define( 'DB_USER', 'uzytkownik_bazy' );
define( 'DB_PASSWORD', 'haslo' );
define( 'DB_HOST', 'localhost' );
Otwórz teraz w drugiej karcie panel hostingu, sekcję z bazami danych, i porównaj wartość po wartości. Nie „na oko”, tylko znak po znaku.
DB_NAME i DB_USER
Na hostingach współdzielonych nazwa bazy i użytkownika prawie zawsze ma przedrostek konta, coś w rodzaju k12345_sklep. Przy przenosinach ze starego serwera na nowy ten przedrostek się zmienia, a stary plik konfiguracyjny zostaje. To najczęstsza przyczyna błędu, jaką widuję zaraz po migracji.
Drugi klasyk to pierwsza konfiguracja na własną rękę. Ktoś tworzy bazę o nazwie sklep, panel zapisuje ją jako k12345_sklep, a w konfiguracji zostaje sama końcówka.
DB_PASSWORD
Tutaj kryje się kilka pułapek naraz.
Hasła nie da się nigdzie podejrzeć, więc jedyny pewny ruch to ustawić je na nowo w panelu hostingu i od razu wkleić w tej samej postaci do pliku. Przy kopiowaniu pilnuj, żeby nie złapać spacji na końcu, bo to jeden z tych błędów, które człowiek przegapia dziesięć razy z rzędu.
Zwróć uwagę na cudzysłowy. W PHP hasło w apostrofach jest brane dosłownie, a w cudzysłowach podwójnych znak dolara zaczyna być traktowany jak zmienna. Jeśli więc masz hasło Xk$3rf i zapiszesz je tak:
define( "DB_PASSWORD", "Xk$3rf" );
to PHP wyśle do bazy coś zupełnie innego. Poprawnie:
define( 'DB_PASSWORD', 'Xk$3rf' );
Jeśli w haśle znajdzie się apostrof albo ukośnik wsteczny, trzeba go poprzedzić ukośnikiem. W praktyce prościej jest wygenerować w panelu hasło bez znaków, które wymagają uciekania: długie, ale złożone tylko z liter i cyfr.
DB_HOST
Domyślne localhost działa na większości serwerów współdzielonych, ale nie na wszystkich. Część hostingów trzyma bazy na osobnych maszynach i wymaga adresu w rodzaju mysql.twojadomena.pl, sql123.serwer.pl albo po prostu adresu IP. Właściwą wartość znajdziesz w panelu przy szczegółach bazy, zwykle jako „host” albo „serwer bazy danych”.
Jeśli baza działa na niestandardowym porcie, dopisujesz go po dwukropku:
define( 'DB_HOST', '127.0.0.1:3307' );
Drobiazg, który potrafi zaoszczędzić godzinę: localhost i 127.0.0.1 to na Linuksie nie to samo. Pierwsze łączy się przez gniazdo systemowe, drugie przez sieć. Bywa, że jedno działa, a drugie nie, więc jeśli utknąłeś, po prostu spróbuj obu.
Pułapki samego pliku
- Brak średnika lub nawiasu po ręcznej edycji. Wtedy zwykle zamiast komunikatu o bazie dostaniesz białą stronę albo błąd krytyczny.
- Podwójna definicja tej samej stałej. Jeśli ktoś dokleił nowe dane na końcu pliku, PHP i tak użyje pierwszej definicji, a nie ostatniej.
- Plik zapisany w Wordzie albo w Notatniku z BOM. Niewidoczne znaki na początku pliku psują nagłówki. Edytuj wyłącznie w edytorze kodu, na przykład Notepad++ albo VS Code, z kodowaniem UTF-8 bez BOM.
- Uprawnienia pliku. Po niefortunnym transferze FTP plik potrafi mieć uprawnienia, których serwer nie akceptuje. Bezpieczna wartość to 644, w niektórych konfiguracjach 640.
Krok 3. Przetestuj połączenie poza WordPressem
To mój ulubiony moment całej diagnostyki, bo tutaj zgadywanie się kończy. Wgrywasz do głównego katalogu strony mały plik, na przykład test-bazy.php, i wpisujesz w niego dokładnie te same dane, które masz w konfiguracji:
<?php
$host = 'localhost';
$user = 'uzytkownik_bazy';
$pass = 'haslo';
$db = 'nazwa_bazy';
$link = @mysqli_connect( $host, $user, $pass, $db );
if ( ! $link ) {
echo 'Blad ' . mysqli_connect_errno() . ': ' . mysqli_connect_error();
} else {
echo 'Polaczenie OK, wersja serwera: ' . mysqli_get_server_info( $link );
}
Wchodzisz na https://twojadomena.pl/test-bazy.php i czytasz, co serwer bazy naprawdę odpowiada. To zupełnie inna jakość informacji niż ogólnikowy komunikat WordPressa. Najczęstsze odpowiedzi i ich znaczenie:
- Access denied for user: hasło albo nazwa użytkownika się nie zgadza, ewentualnie użytkownik nie ma prawa łączyć się z tego hosta. Wracasz do kroku drugiego.
- Unknown database: dane logowania są dobre, ale baza o takiej nazwie nie istnieje. Sprawdź nazwę w panelu, zwykle chodzi o przedrostek.
- Can’t connect to MySQL server lub Connection refused: zły adres w DB_HOST albo serwer bazy nie działa.
- Too many connections: serwer żyje, ale wyczerpał limit jednoczesnych połączeń. O tym za chwilę.
- Połączenie OK: i to jest ciekawy przypadek. Skoro zwykły skrypt się łączy, a WordPress nie, to znaczy, że WordPress czyta inne dane, niż myślisz. Sprawdź, czy nie edytujesz pliku w złym katalogu (częste przy wielu instalacjach na jednym koncie) i czy dane nie są nadpisywane niżej w pliku.
Po zakończeniu testu skasuj ten plik. Zostawiony na serwerze wystawia hasło do bazy każdemu, kto zgadnie nazwę.
Krok 4. Uprawnienia użytkownika bazy
Zdarza się, że użytkownik istnieje, hasło jest dobre, a mimo to dostajesz odmowę. Wtedy zwykle brakuje mu przypisania do konkretnej bazy. W panelu hostingu odszukaj sekcję z użytkownikami MySQL i sprawdź, czy Twój użytkownik faktycznie jest podpięty pod tę bazę i czy ma pełen zestaw uprawnień. WordPress potrzebuje między innymi SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER i INDEX. Na typowym hostingu współdzielonym przypisanie robi się jednym kliknięciem, przy „wszystkie uprawnienia”.
Krok 5. Limity połączeń i limity pakietu
Jeśli błąd pojawia się nieregularnie, znika po odświeżeniu i wraca w godzinach największego ruchu, to prawie na pewno nie chodzi o hasło. Chodzi o limity.
Na hostingach współdzielonych obowiązuje maksymalna liczba jednoczesnych połączeń do bazy oraz limit procesów. Kiedy sklep dostanie falę ruchu, albo kiedy jedna ciężka wtyczka zacznie odpytywać bazę w kółko, limit się kończy i część odwiedzających widzi błąd, a część nie. Typowe źródła obciążenia:
- boty skanujące sklep, zwłaszcza po filtrach i wariantach produktów,
- wtyczki statystyk zapisujące każde wejście do bazy,
- rozbudowane wyszukiwanie i filtrowanie na dużym katalogu,
- brak jakiegokolwiek cache, przez co każde wejście generuje pełny zestaw zapytań,
- ataki na
xmlrpc.phpiwp-login.php.
Doraźnie pomaga włączenie cache i ograniczenie botów. Docelowo trzeba znaleźć zapytania, które ciągną serwer w dół. Rozpisałem to szerzej we wpisie o tym, dlaczego sklep WooCommerce działa wolno.
Krok 6. Miejsce na dysku
Prosty i zaskakująco częsty scenariusz: kończy się limit powierzchni na koncie. MySQL nie ma gdzie zapisać plików tymczasowych, więc przestaje odpowiadać. Strona pada, a komunikat sugeruje problem z połączeniem.
Sprawdź w panelu wykorzystanie miejsca. Jeśli jesteś blisko limitu, najszybciej odzyskasz przestrzeń, kasując stare kopie zapasowe leżące na serwerze, logi błędów, które urosły do gigabajtów, i pliki po nieudanych aktualizacjach. Bywa też, że winna jest tabela z transientami albo tabela logów jednej wtyczki, która puchnie od miesięcy.
Krok 7. Uszkodzone tabele
Ten punkt jest na końcu nie bez powodu. Uszkodzenie tabel zdarza się rzadziej, niż sugerują poradniki, ale zdarza się: po nagłym restarcie serwera, po przerwanym imporcie, po zapełnieniu dysku.
Rozpoznasz je zwykle po tym, że front pokazuje błąd połączenia, a kokpit wyświetla komunikat o niedostępnych tabelach. WordPress ma wbudowane narzędzie naprawcze. Dodaj do wp-config.php, powyżej linii z komentarzem „That’s all, stop editing”, następujący wpis:
define( 'WP_ALLOW_REPAIR', true );
Następnie wejdź na adres https://twojadomena.pl/wp-admin/maint/repair.php i wybierz naprawę bazy. Po zakończeniu koniecznie usuń tę linię z pliku. Strona naprawy nie wymaga logowania, więc pozostawiona włączona jest otwartą furtką dla każdego.
Jedno zastrzeżenie, o którym rzadko się wspomina: to narzędzie realnie naprawia tabele w silniku MyISAM. Współczesny WordPress używa InnoDB, gdzie taka naprawa najczęściej nic nie da. Przy InnoDB pewniejszą drogą jest przywrócenie bazy z kopii zapasowej albo pomoc administratora serwera.
Jeśli masz dostęp do konsoli i WP-CLI, ten sam test zrobisz szybciej:
wp db check
wp db repair
Kiedy błąd pojawia się i znika sam
Osobna kategoria, warta wyodrębnienia, bo prowadzi się ją inaczej. Jeśli strona działa, potem na dwie minuty pada, potem wraca, to nie szukaj literówki w konfiguracji. Szukaj przeciążenia.
Zacznij od ustalenia, o jakich porach to się dzieje. Poproś hosting o wykres zużycia zasobów albo zajrzyj do statystyk w panelu. Jeśli szczyty pokrywają się z Twoim ruchem, sprawa jest jasna. Jeśli pojawiają się o czwartej nad ranem, spójrz na zadania cron, kopie zapasowe i wtyczki importujące dane. A jeśli obciążenie generuje ruch, którego nie potrafisz wytłumaczyć, sprawdź logi dostępu pod kątem botów i rozważ, czy strona nie została naruszona. Opisałem to w tekście o tym, jak odwirusować stronę na WordPressie.
Czego nie robić
- Nie klikaj „Zainstaluj” na ekranie instalacji WordPressa. Jeśli go widzisz, połączenie działa, a problem leży gdzie indziej.
- Nie nadpisuj plików nową paczką WordPressa „na wszelki wypadek”. Przy tym błędzie to nic nie daje, a potrafi zamieszać.
- Nie zmieniaj prefiksu tabel w konfiguracji, licząc, że to pomoże. Zmiana
$table_prefixbez zmiany nazw tabel w bazie zamieni jeden problem na drugi. - Nie kasuj i nie twórz bazy od nowa, dopóki nie masz pewnej, sprawdzonej kopii. To jedyna czynność w całej tej liście, która potrafi naprawdę zniszczyć dane.
Gdy nic nie pomaga: co napisać hostingowi
Zgłoszenie w stylu „strona nie działa” zwykle wraca z prośbą o szczegóły i tracisz kolejne godziny. Napisz od razu wszystko, co ustaliłeś:
- adres strony i dokładny komunikat, który widzisz,
- od kiedy trwa problem i czy występuje stale, czy okresowo,
- co zmieniło się bezpośrednio wcześniej,
- że dane w
wp-config.phpzostały porównane z panelem i się zgadzają, - wynik testu połączenia z kroku trzeciego, najlepiej z dokładną treścią błędu MySQL,
- pytanie wprost: czy serwer bazy działa, czy konto nie przekroczyło limitu połączeń i czy nie ma zdarzeń w logach z tej godziny.
Zgłoszenie w takiej formie zwykle trafia od razu do kogoś, kto potrafi je rozwiązać, zamiast krążyć po pierwszej linii wsparcia.
Jak zmniejszyć ryzyko na przyszłość
Ten błąd rzadko przychodzi bez zapowiedzi. Zwykle poprzedza go coś, co dało się zauważyć wcześniej.
- Kopia zapasowa poza serwerem. Backup leżący na tym samym koncie nie pomoże, kiedy problemem jest zapełniony dysk. Raz na jakiś czas sprawdź, czy kopię da się faktycznie odtworzyć, bo backup, którego nikt nie testował, jest tylko obietnicą.
- Monitoring dostępności. Prosta usługa sprawdzająca stronę co pięć minut da Ci znać, zanim zrobi to klient.
- Cache. Zmniejsza liczbę zapytań do bazy o rząd wielkości i realnie chroni przed wyczerpaniem limitu połączeń.
- Porządek w bazie. Stare wersje wpisów, wygasłe transienty i tabele po odinstalowanych wtyczkach potrafią rozdąć bazę do rozmiarów, które zaczynają przeszkadzać.
- Zapisane dane dostępowe. Trzymaj gdzieś bezpiecznie komplet danych do bazy i do panelu. W trakcie awarii to nie jest dobry moment na przypominanie sobie, gdzie one były.
Najczęstsze pytania
Czy straciłem dane?
Prawie na pewno nie. Ten komunikat mówi o nieudanym połączeniu, a nie o utracie danych. Jedyne sytuacje, w których dane faktycznie znikają, to skasowana baza albo nadpisana instalacja, czyli rzeczy, które trzeba zrobić samemu.
Dlaczego strona działała jeszcze wczoraj?
Najczęściej dlatego, że coś zmieniło się po stronie serwera: hasło do bazy, adres serwera bazy, wersja PHP albo limity pakietu. Część hostingów robi takie zmiany w ramach migracji technicznych i informuje o nich mailem, którego łatwo przegapić.
Czy mogę to naprawić bez dostępu do FTP?
Tak, jeśli masz panel hostingu. Menedżer plików w panelu w zupełności wystarczy do edycji wp-config.php, a phpMyAdmin do sprawdzenia bazy.
Błąd zniknął sam. Trzeba jeszcze coś robić?
Tak. Jeśli problem ustąpił bez Twojej interwencji, to znaczy, że przyczyną było chwilowe przeciążenie albo krótka awaria po stronie serwera. Bez ustalenia, co dokładnie się stało, wróci przy następnym większym ruchu. Zajrzyj do kroku piątego.
Czy to może być skutek włamania?
Bezpośrednio rzadko, ale pośrednio owszem. Zainfekowana strona potrafi generować taki ruch i tyle zapytań, że wyczerpuje limity konta. Jeśli poza błędem widzisz dziwne przekierowania, nieznane konta administratorów albo skoki transferu, potraktuj to poważnie.
Podsumowanie
Kolejność, która sprawdza się w praktyce: najpierw phpMyAdmin, żeby wiedzieć, czy serwer bazy w ogóle żyje. Potem cztery linie w wp-config.php porównane z panelem hostingu znak po znaku. Potem samodzielny test połączenia, który powie Ci, co dokładnie odpowiada MySQL. Dopiero na końcu limity, miejsce na dysku i naprawa tabel.
Jeśli chcesz zobaczyć, jak wyglądają inne ścieżki tego typu, opisałem osobno błąd krytyczny WordPressa oraz białą stronę śmierci. To trzy różne objawy, które bardzo często mają wspólne korzenie.
A jeśli utknąłeś w połowie tej listy albo po prostu nie chcesz grzebać w plikach na produkcyjnym sklepie, napisz do mnie. Zajmuję się takimi awariami na co dzień i zwykle wystarczy dostęp do panelu, żeby powiedzieć Ci, co się stało.
Nie chcesz robić tego samodzielnie?
Zajmę się tym za Ciebie. Napisz krótko, co się dzieje - odpowiem tego samego dnia roboczego.