Reset hasła root w MySQL i MariaDB

Opublikowano 13 min czytania

Zapomniane hasło root? Często wcale go nie potrzebujesz. A jeśli jednak, to tak otworzysz bazę na dokładnie jedną minutę, nie zostawiając jej przy okazji połowie internetu.

Hasło root do bazy danych to jedno z tych haseł, które ustawiasz raz przy instalacji i potem nigdy więcej go nie potrzebujesz, bo każda aplikacja pracuje na własnym koncie. Aż do dnia, w którym jednak musisz się do niej dostać. Wtedy widzisz to:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

Standardowa odpowiedź w sieci brzmi: zatrzymaj usługę, uruchom ją z --skip-grant-tables, ustaw hasło, gotowe. To prawda, ale tylko połowa prawdy. W tym poradniku znajdziesz też odpowiedź na to, dlaczego wszędzie kopiowane polecenie nie działa na Ubuntu z MySQL 8, dlaczego w wielu przypadkach hasło w ogóle nie jest potrzebne i co zrobić, gdy usługa po całej operacji przestaje się uruchamiać.

Najpierw sprawdź: prawdopodobnie hasło wcale nie jest potrzebne

Na Debianie i Ubuntu bazodanowy root od lat nie jest chroniony hasłem, tylko tożsamością użytkownika systemowego. MariaDB nazywa tę metodę unix_socket, MySQL nazywa ją auth_socket. Chodzi o to samo: kto łączy się przez lokalny socket i na poziomie systemu operacyjnego jest już użytkownikiem root, wchodzi bez hasła. Uzasadnienie jest proste: systemowy root i tak sięgnie do wszystkich plików z danymi oraz do pamięci procesu, więc dodatkowe hasło nie stanowi żadnej przeszkody.

Dlatego pierwsza próba powinna zawsze wyglądać tak:

sudo mariadb
sudo mysql

Zwróć uwagę: sudo mysql -u root -p nie zadziała, bo -p przełącza na uwierzytelnianie hasłem. Właśnie na tym potyka się większość osób. Bez -p i z sudo trafiasz z reguły prosto do znaku zachęty. Stamtąd ustawisz nowe hasło w dwie sekundy, w ogóle nie ruszając bazy danych.

Druga droga ratunku to konto serwisowe dystrybucji. Na Ubuntu z pakietem mysql-server nadal istnieje plik /etc/mysql/debian.cnf, który zawiera dane dostępowe do konta z pełnymi uprawnieniami, czytelny wyłącznie dla root:

sudo ls -l /etc/mysql/debian.cnf
sudo mysql --defaults-file=/etc/mysql/debian.cnf -e "SELECT current_user();"

Jeśli wróci tu jakiś wiersz, jesteś w środku i możesz od razu pracować dalej. Nie oczekuj przy tym root@localhost: zapytanie odpowiada debian-sys-maint@localhost. Tak ma być, bo to konto serwisowe ma ALL PRIVILEGES i w zupełności wystarcza do resetu, ale rootem przez to nie jesteś. Ta droga jest poza tym specyficzna wyłącznie dla Debiana i Ubuntu. Na AlmaLinux, Rocky Linux i Oracle Linux nie ma ani katalogu /etc/mysql/, ani tego konta, tam działa zamiast tego logowanie przez socket jako root z poprzedniej sekcji. W MariaDB od 10.4 konto to nie jest już zakładane na nowo (plik wskazuje tam zwykle po prostu na root przez socket), w istniejących instalacjach często jeszcze jest. Zerknięcie nic nie kosztuje, a w razie powodzenia oszczędza ci całą resztę tego poradnika.

Jaka baza danych tu właściwie działa?

To nie formalność, tylko rzecz decydująca o każdym kolejnym poleceniu. W Debianie od lat nie ma już pakietu mysql-server w oficjalnym archiwum, praktycznie zawsze działa tam MariaDB, nawet jeśli polecenie mysql istnieje. Jest ono bowiem tylko dowiązaniem symbolicznym do klienta MariaDB. Aktualnie w dystrybucjach znajdziesz:

Systemmysql-servermariadb-server
Debian 13brak11.8
Debian 12brak10.11
Ubuntu 24.048.010.11
Ubuntu 22.048.010.6

Zapytaj sam serwer, nie klienta:

systemctl list-units --type=service --all | grep -Ei 'mysql|mariadb'
mysqladmin --version
mariadbd --version

Przełącznik --all jest tu potrzebny, bo list-units pokazuje inaczej tylko wczytane, aktywne jednostki. Dokładnie w sytuacji, w której potrzebujesz tego polecenia, czyli przy usłudze, która nie działa, wynik pozostałby pusty. mysqladmin --version istnieje po obu stronach i nazywa silnik wprost, systemy z MariaDB odpowiadają ... Distrib 11.8.6-MariaDB .... Przy mariadbd --version komunikat command not found na czystym systemie z MySQL jest wynikiem oczekiwanym, a nie błędem; odwrotnie to samo dotyczy poleceń specyficznych dla mysqld na czystym systemie z MariaDB.

Jeśli jednostka nazywa się mariadb.service, pracujesz z MariaDB. Jeśli mysql.service, z MySQL. W systemach z MariaDB istnieje dodatkowo alias mysql.service, który wskazuje na mariadb.service, dlatego wynik systemctl list-units mówi więcej niż samo istnienie nazwy.

Same nazwy jednostek różnią się między rodzinami dystrybucji, a wszystkie kolejne wywołania systemctl w tym poradniku są napisane pod Debiana i Ubuntu. W rodzinie Red Hat nie ma w ogóle jednostki o nazwie mysql.service, tam systemctl status mysql odpowiada Unit mysql.service could not be found. W takim przypadku wstawiaj konsekwentnie nazwy z prawej kolumny, także w ścieżce katalogu drop-in:

CoDebian i UbuntuAlmaLinux, Rocky, RHEL
Jednostka MariaDBmariadb.servicemariadb.service
Jednostka MySQLmysql.servicemysqld.service
Katalog drop-in MySQL/etc/systemd/system/mysql.service.d//etc/systemd/system/mysqld.service.d/
Binarka serwera MySQL/usr/sbin/mysqld/usr/libexec/mysqld --basedir=/usr
Konfiguracja/etc/mysql//etc/my.cnf i /etc/my.cnf.d/

Najpierw odetnij dostęp: dlaczego ten krok nie jest opcjonalny

Przy --skip-grant-tables serwer nie wczytuje tabel uprawnień. To nie znaczy „root wchodzi bez hasła”, tylko „każdy może wszystko, bez hasła, jako dowolny użytkownik”. W tym stanie nie ma żadnego uwierzytelniania ani sprawdzania uprawnień, także dla baz twoich klientów.

MySQL 8 włącza w takim przypadku automatycznie skip_networking, czyli przestaje przyjmować połączenia TCP. Mimo to nie polegaj na tym, lecz zawsze dopisuj tę opcję samodzielnie. W MariaDB jest to i tak udokumentowane zalecenie, a kto opiekuje się obydwoma systemami, nie chce pamiętać, który z nich myśli za niego.

--skip-grant-tables --skip-networking

Dwie rzeczy, które łatwo tu przeoczyć. Po pierwsze: skip_networking zamyka tylko port sieciowy. Socket uniksowy w /run/mysqld/mysqld.sock pozostaje otwarty, a na wielu systemach jest dostępny dla wszystkich lokalnych użytkowników. Przejęty proces PHP działający jako www-data może w tym oknie odczytać każdą bazę na serwerze. Trzymaj więc to okno tak krótko, jak się da, i nie przeprowadzaj tej operacji, gdy działa serwer WWW z nieznanym kodem. Po drugie: zatrzymaj wcześniej wszystko, co łączy się automatycznie, czyli serwer WWW i usługi aplikacji. Ich próby połączenia nie tylko przeszkadzają, ale w tym stanie działają z pełnymi uprawnieniami.

Jeśli serwer jest osiągalny z zewnątrz, dociągnij dodatkowo firewalla. Jak ustawić to porządnie i na stałe, opisuje wpis Konfiguracja firewalla UFW.

sudo apt-get install -y ufw
sudo ufw deny 3306/tcp
sudo ss -ltnp | grep 3306

Pierwszy wiersz nie jest zbędny: w minimalnej instalacji Debiana ufw nie jest preinstalowany, polecenie kończy się inaczej komunikatem sudo: ufw: command not found. Na AlmaLinux, Rocky Linux i RHEL ufw w ogóle nie występuje, tam filtrowaniem pakietów zajmuje się firewalld:

sudo firewall-cmd --permanent --remove-service=mysql
sudo firewall-cmd --reload

We wszystkich sprawdzonych instalacjach Debiana i Ubuntu bind-address stoi i tak na 127.0.0.1, co potwierdza ss -ltnp. Serwer nie przyjmuje wtedy połączeń z zewnątrz, a reguła firewalla jest drugim zabezpieczeniem, nie właściwą ochroną.

MariaDB: reset hasła

Jednostka MariaDB uruchamia serwer wpisem ExecStart=/usr/sbin/mariadbd $MYSQLD_OPTS. Ta zmienna jest przewidziana dokładnie na takie sytuacje, nie musisz więc edytować żadnego pliku. Sprawdź to krótko, wtedy masz pewność, że opisana dalej droga zadziała na twoim systemie:

systemctl cat mariadb | grep ExecStart

Potem w tej kolejności:

sudo systemctl stop mariadb
sudo systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"
sudo systemctl start mariadb
sudo mariadb -u root

W znaku zachęty wykonaj najpierw FLUSH PRIVILEGES. Bez tego kroku serwer nie ma tabel uprawnień w pamięci i odrzuca każde zarządzanie kontami. Dopiero potem ustawiasz hasło:

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('TwojeNoweHaslo');

Ten nieco toporny zapis jest celowy i stanowi najważniejszy specyficzny dla MariaDB punkt całego poradnika. MariaDB potrafi od 10.4 prowadzić kilka metod uwierzytelniania na jedno konto i dokładnie tak skonfigurowany jest root po instalacji z pakietu: najpierw socket, zastępczo hasło. Jeśli użyjesz zamiast tego zwykłego ALTER USER 'root'@'localhost' IDENTIFIED BY '...', zastąpisz cały ten łańcuch samym uwierzytelnianiem hasłem. Zadziała, ale potem sudo mariadb bez hasła już nie przejdzie, a wewnętrzne skrypty serwisowe dystrybucji, które liczą na socket, trafią w próżnię. Problem zostanie wtedy tylko przesunięty o rok.

Na koniec posprzątaj stan wyjątkowy:

sudo systemctl stop mariadb
sudo systemctl unset-environment MYSQLD_OPTS
sudo systemctl start mariadb

Nie zapomnij o unset-environment. Zmienna wisi na menedżerze systemd, a nie na usłudze, i przeżywa każdy restart usługi. Jeśli w nocy aktualizacja pakietów zrestartuje MariaDB, twoja baza działa od tego momentu bez jakiegokolwiek sprawdzania uprawnień i nikt tego nie zauważy. Dopiero reboot serwera usuwa tę zmienną samoczynnie.

MySQL 8: polecenie z większości poradników nic tu nie robi

Dla MySQL krąży ten sam przepis z systemctl set-environment MYSQLD_OPTS=.... Pochodzi z dokumentacji Oracle i pasuje do ich własnych pakietów. Jednostka z archiwum Ubuntu wygląda jednak inaczej, stoi tam po prostu ExecStart=/usr/sbin/mysqld, bez zmiennej. Polecenie przechodzi, nie zgłasza błędu, a serwer i tak startuje całkiem normalnie z aktywnym sprawdzaniem uprawnień. Siedzisz wtedy przed Access denied i się dziwisz. Sprawdź sam:

systemctl cat mysql | grep ExecStart

Jeśli nie pojawia się tam $MYSQLD_OPTS, potrzebujesz drop-ina. A skoro i tak go zakładasz, wybierz od razu lepszą drogę: --init-file. Serwer startuje wtedy całkiem normalnie ze sprawdzaniem uprawnień i wykonuje przy starcie plik SQL z pełnymi uprawnieniami. Nie ma otwartego okna czasowego, w którym ktokolwiek wchodzi bez hasła. Oracle wyraźnie zaleca ten wariant przed --skip-grant-tables.

sudo systemctl stop mysql
printf "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'TwojeNoweHaslo';\n" | sudo tee /var/lib/mysql-files/kh-reset.sql
sudo chown mysql:mysql /var/lib/mysql-files/kh-reset.sql
sudo chmod 600 /var/lib/mysql-files/kh-reset.sql
sudo mkdir -p /etc/systemd/system/mysql.service.d

Fragment IDENTIFIED WITH caching_sha2_password jest tu decydujący i stanowi powód, dla którego niezliczone poradniki zawodzą w tym miejscu, nie pokazując żadnego błędu. Na Debianie i Ubuntu root@localhost także przy MySQL używa wtyczki auth_socket. Zwykłe IDENTIFIED BY 'passwort' ustawia wprawdzie skrót hasła, ale nie zmienia wtyczki. W mysql.user stoi potem nadal auth_socket, usługa startuje czysto, nie pojawia się ani jeden komunikat o błędzie, a mimo to każde logowanie hasłem kończy się na ERROR 1698 (28000): Access denied for user 'root'@'localhost'. Szczególnie zdradliwe: kto robi kontrolne sprawdzenie jako systemowy root, tego auth_socket przepuszcza bez hasła, więc uzna reset za udany. Testuj więc z innego konta albo przez TCP. Tylko przy bardzo starych klientach, które nie obsługują caching_sha2_password, wstawiasz zamiast tego mysql_native_password, z zastrzeżeniami z akapitu poniżej.

Katalog /var/lib/mysql-files jest wybrany świadomie: należy do użytkownika bazy danych i jest dopuszczony w profilu AppArmor dla mysqld. Jeśli położysz plik w /root albo /tmp, start może w pewnych okolicznościach polec na AppArmorze, a komunikat w logu jest mało pomocny. Teraz drop-in:

[Service]
ExecStart=
ExecStart=/usr/sbin/mysqld --init-file=/var/lib/mysql-files/kh-reset.sql

Pusty pierwszy wiersz ExecStart jest obowiązkowy, inaczej systemd dokleja twoje polecenie do istniejącego i odmawia uruchomienia usługi z błędem konfiguracji. Zapisz jako /etc/systemd/system/mysql.service.d/override.conf, następnie:

sudo systemctl daemon-reload
sudo systemctl start mysql
sudo mysql -u root -p

Jeśli logowanie działa, usuń jedno i drugie, plik SQL oraz drop-in:

sudo rm -f /var/lib/mysql-files/kh-reset.sql
sudo rm -f /etc/systemd/system/mysql.service.d/override.conf
sudo systemctl daemon-reload
sudo systemctl restart mysql

Jeśli mimo wszystko chcesz iść klasyczną drogą, zamień w drop-inie ten wiersz na ExecStart=/usr/sbin/mysqld --skip-grant-tables --skip-networking, połącz się przez sudo mysql i wykonaj tam najpierw FLUSH PRIVILEGES;, potem ALTER USER. Uwaga co do szyfrowania: MySQL 8 używa domyślnie caching_sha2_password. Jeśli bardzo stara aplikacja zgłosi się potem komunikatem „The server requested authentication method unknown to the client”, pomaga IDENTIFIED WITH mysql_native_password BY '...'. To jednak ślepa uliczka, bo ta metoda od 8.0.34 uchodzi za przestarzałą, a w MySQL 8.4 już jej nie ma. Lepiej zaktualizować klienta.

Komunikaty błędów w oryginalnym brzmieniu

ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement. Zapomniałeś o FLUSH PRIVILEGES;. Wykonaj to polecenie, wtedy ALTER USER zadziała.

ERROR 1288 (HY000): The target table user of the UPDATE is not updatable. Idziesz za starym poradnikiem, który proponuje UPDATE mysql.user SET password=.... Od MariaDB 10.4 uprawnienia leżą w mysql.global_priv, a mysql.user jest już tylko widokiem na tę tabelę. Użyj ALTER USER albo SET PASSWORD. Na marginesie: bezpośredni zapis do tabel uprawnień już dawniej był dobrą metodą na ostateczne rozłożenie konta.

ERROR 1698 (28000): Access denied for user 'root'@'localhost'. To nie błędne hasło, tylko odwrotność: konto oczekuje uwierzytelnienia przez socket, a ty nie działasz jako systemowy root albo podałeś -p. Spróbuj ponownie z sudo i bez -p.

ERROR 1524 (HY000): Plugin 'unix_socket' is not loaded. Konto wskazuje na wtyczkę, której działający serwer nie zna, typowo po przejściu z MariaDB na MySQL albo po skopiowaniu katalogu z danymi. Przestaw konto opisaną wyżej drogą na pasującą metodę.

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2). Serwer nie działa. Najpierw obejrzyj systemctl status i log, nie próbuj dalej po stronie klienta.

mysqld: Can't create directory '/run/mysqld/' (Errcode: 13 - Permission denied) albo start, który natychmiast się przerywa. Dzieje się tak, gdy serwer został uruchomiony ręcznie zamiast przez systemd, bo wtedy brakuje katalogu czasu wykonania. Naprawa:

sudo mkdir -p /run/mysqld
sudo chown mysql:mysql /run/mysqld

Job for mysql.service failed because the control process exited with error code. Ten komunikat sam w sobie nic nie mówi. Właściwa przyczyna stoi w dzienniku i w logu błędów:

sudo journalctl -u 'mysql*' -u 'mariadb*' -n 60 --no-pager

Wzorzec z obiema nazwami jednostek jest wybrany świadomie, bo nasuwające się zapytanie o jedną prowadzi w cichą pułapkę. Na Debianie z MariaDB mysql.service jest tylko aliasem na mariadb.service. systemctl rozwiązuje alias, ale dziennik indeksuje wpisy pod prawdziwą nazwą jednostki, dlatego journalctl -u mysql odpowiada -- No entries -- i kodem wyjścia 0, choć dziennik jest pełny. Odwrotnie, journalctl -u mariadb na systemie Ubuntu z MySQL zwraca również -- No entries --.

Podobnie jest z plikiem błędów. Wszędzie cytowany /var/log/mysql/error.log istnieje tylko na Ubuntu z MySQL. Na Debianie z MariaDB katalogu /var/log/mysql/ w ogóle nie ma, bo log_error jest w 50-server.cnf zakomentowany, a MariaDB pisze do dziennika. Pasujący wiersz zależnie od systemu:

System i serwerPolecenie
Debian lub Ubuntu, MariaDBsudo journalctl -u mariadb -n 60 --no-pager
Ubuntu, MySQLsudo tail -n 60 /var/log/mysql/error.log
AlmaLinux, Rocky, RHEL, MySQLsudo tail -n 60 /var/log/mysql/mysqld.log
AlmaLinux, Rocky, RHEL, MariaDBsudo tail -n 60 /var/log/mariadb/mariadb.log

Jeśli nie chcesz zgadywać ścieżki, zapytaj sam serwer: sudo mariadb -e "SHOW VARIABLES LIKE 'log_error';" względnie to samo z mysql.

Trzy najczęstsze przyczyny w tym miejscu: literówka w drop-inie (wtedy systemd wskazuje ten wiersz), pełny dysk (o tym wpis Pełny dysk w systemie Linux) albo drugi proces serwera, który wciąż działa i trzyma pliki z danymi zablokowane. To ostatnie sprawdzisz przez pgrep -a mariadbd względnie pgrep -a mysqld, zanim uruchomisz usługę ponownie.

Jeśli po resecie wchodzisz wprawdzie do bazy, ale twoje aplikacje nadal są odrzucane, problem leży gdzie indziej: aplikacje takie jak WordPress czy Nextcloud używają własnych użytkowników bazy danych, a nie konta root. Szczegóły w Naprawa błędu MySQL Access denied for user.

Po czym poznasz, że naprawdę się udało

Samo udane logowanie nie wystarcza za dowód, bo w stanie awaryjnym udaje się ono także bez jakiegokolwiek hasła. Sprawdź więc cztery rzeczy, gdy usługa znowu działa normalnie.

Po pierwsze: nie ma już żadnej konfiguracji specjalnej. Pierwszy wynik musi być pusty, drugi nie może pokazywać żadnych dodatkowych opcji.

systemctl show-environment | grep MYSQLD_OPTS
systemctl cat mariadb | grep ExecStart

Po drugie: sprawdzanie uprawnień znów działa. Logowanie z celowo błędnym hasłem musi się nie powieść. Jeśli przechodzi, serwer nadal stoi otworem.

Po trzecie: nowe hasło i oczekiwana metoda są zapisane w koncie. W MariaDB sprawdzisz to tak, przy MySQL bez kolumny JSON:

sudo mariadb -e "SELECT user, host, plugin FROM mysql.user WHERE user='root';"
sudo mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user='root';"

Po czwarte: port sieciowy zachowuje się znów tak jak wcześniej. Serwer bazy danych używany wyłącznie lokalnie powinien po sprzątaniu nasłuchiwać ponownie tylko na 127.0.0.1:

sudo ss -ltnp | grep 3306
grep -rs bind-address /etc/mysql/ /etc/my.cnf /etc/my.cnf.d/

Przełącznik -s oraz trzy ścieżki są celowe. Samo grep -r bind-address /etc/mysql/ przerywa w rodzinie Red Hat komunikatem No such file or directory, bo nie ma tam /etc/mysql/. Z -s grep pomija nieistniejące ścieżki po cichu, a wiersz pasuje do obu światów.

Sprzątanie, żeby nie zdarzyło się po raz drugi

Hasło stoi teraz być może w miejscach, o których nie myślisz. Polecenie z -e "ALTER USER ... IDENTIFIED BY '...'" ląduje w ~/.bash_history, komenda wpisana w znaku zachęty w pliku historii klienta bazy danych. Jedno i drugie trzeba wyczyścić:

history -c
rm -f ~/.mysql_history ~/.mariadb_history

Obie nazwy plików są potrzebne, bo klient zmienił nazwę. Do MariaDB 10.11, czyli włącznie z Debianem 12, pisze on do ~/.mysql_history. Od MariaDB 11, czyli od Debiana 13, pisze do ~/.mariadb_history. Kto usunie tam tylko stary plik, zostawia wpisane jawnym tekstem hasło na dysku i nawet tego nie zauważy. Jeszcze lepiej w ogóle nie dopuścić do powstania historii: export MYSQL_HISTFILE=/dev/null względnie export MARIADB_HISTFILE=/dev/null przed sesją, albo od razu droga przez --init-file z sekcji o MySQL, przy której hasło nigdy nie przechodzi przez sesję interaktywną.

Sensowniejsze niż hasło, które za rok znowu zapomnisz, jest ustawienie bez hasła w codziennej pracy. Na Debianie i Ubuntu znaczy to: root zostaje przy unix_socket względnie auth_socket, a do wszystkiego innego zakładasz zwykłych użytkowników z dokładnie tymi uprawnieniami, których dana aplikacja potrzebuje. Kto potrzebuje dostępu z innego komputera, tuneluje go przez SSH, zamiast otwierać port 3306, zobacz Połączenie z serwerem przez SSH.

Skoro i tak pracujesz właśnie przy bazie danych, weź od razu resztę: usuń anonimowych użytkowników, skasuj bazę testową, wyłącz zdalny dostęp dla root. Załatwia to mariadb-secure-installation względnie mysql_secure_installation w kilka minut, szczegółowo opisane w Zabezpieczanie MariaDB i MySQL. A ponieważ hasło rzadko bywa jedyną rzeczą leżącą odłogiem na świeżo przejętym serwerze, warto przejść przez listę kontrolną dla nowych serwerów root.

Ostatnia myśl o kolejności: zanim wprowadzisz działający serwer produkcyjny w stan bez uprawnień, zrób kopię zapasową katalogu z danymi albo snapshot. Sam reset jest niegroźny, ale usługa, która po literówce w jednostce już się nie uruchamia, o trzeciej nad ranem groźna jest jak najbardziej.

Najczęstsze pytania

Zapomniałem hasła root. Czy naprawdę muszę zatrzymywać MySQL?
Najczęściej nie. Na Debianie i Ubuntu bazodanowy root jest chroniony socketem uniksowym, a nie hasłem. Spróbuj najpierw sudo mariadb względnie sudo mysql, za każdym razem bez opcji -p. Jeśli to zadziała, ustawisz nowe hasło poleceniem ALTER USER przy działającej bazie. Dopiero gdy ta droga kończy się komunikatem Access denied, potrzebujesz restartu z pominiętym sprawdzaniem uprawnień.
Dlaczego dostaję ERROR 1290, mimo że uruchomiłem serwer z skip-grant-tables?
Bo serwer nie wczytał w tym stanie tabel uprawnień i dlatego nie może wykonać żadnej operacji na kontach. Wykonaj w znaku zachęty najpierw FLUSH PRIVILEGES, potem ALTER USER działa jak zwykle. Pełny komunikat brzmi: The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement.
Czy mój serwer jest w trakcie resetu podatny na atak?
Tak, i to całkowicie. Przy pominiętym sprawdzaniu uprawnień nie ma już żadnego uwierzytelniania, każda próba połączenia ma wszystkie prawa do wszystkich baz. MySQL 8 wyłącza przy tym automatycznie port sieciowy, MariaDB niekoniecznie. Dlatego zawsze dopisuj --skip-networking samodzielnie, zatrzymaj serwer WWW i usługi aplikacji, a całe okno ogranicz do kilku minut. Lokalny socket i tak pozostaje otwarty dla wszystkich użytkowników systemu.
Czym różni się reset hasła w MySQL 8 od MariaDB?
Trzema rzeczami. Po pierwsze jednostka systemd: przy MariaDB działa systemctl set-environment MYSQLD_OPTS, przy MySQL z archiwum Ubuntu już nie, tam potrzebujesz drop-ina z własnym wierszem ExecStart. Po drugie tabele uprawnień: od MariaDB 10.4 mysql.user jest już tylko widokiem na mysql.global_priv, bezpośrednie polecenia UPDATE kończą się błędem ERROR 1288. Po trzecie składnia konta: MariaDB potrafi prowadzić obie metody równocześnie przez IDENTIFIED VIA unix_socket OR mysql_native_password, a MySQL zna tylko jedną metodę na konto. Przy MySQL decydujące jest przy tym słowo WITH: ALTER USER ... IDENTIFIED BY ustawia wyłącznie skrót hasła i zostawia wtyczkę auth_socket, więc logowanie hasłem mimo wszystko kończy się błędem ERROR 1698. Poprawnie brzmi ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '...'.
Po resecie wchodzę jako root, ale moja strona nadal zgłasza Access denied. Dlaczego?
Bo aplikacje takie jak WordPress, Nextcloud czy systemy sklepowe nie pracują na koncie root, tylko na własnych użytkownikach bazy danych. Ich hasła stoją w pliku konfiguracyjnym danej aplikacji i reset konta root ich nie dotyczy. Sprawdź użytkownika zapisanego w aplikacji i w razie potrzeby ustaw jego hasło tak, żeby się zgadzało.
Co się stanie, jeśli zapomnę o systemctl unset-environment?
Zmienna wisi na menedżerze systemd i przeżywa każdy restart usługi. Jeśli w nocy aktualizacja pakietów zrestartuje bazę, od tego momentu działa ona trwale bez sprawdzania uprawnień, a nikt tego nie zauważa. Dopiero reboot całego serwera usuwa ją samoczynnie. Po zakończonej pracy sprawdź poleceniem systemctl show-environment, że MYSQLD_OPTS nie jest już ustawione.

MySQL MariaDB Hasło root Debian Ubuntu systemd Baza danych Zarządzanie serwerem unix_socket Rozwiązywanie problemów