Сброс пароля root в MySQL 8 и MariaDB

Прежде чем сбрасывать пароль root, проверьте, нужен ли он вообще. В Debian, Ubuntu и AlmaLinux пользователь root в MariaDB 10.4+ по умолчанию входит через сокет, без пароля: достаточно выполнить sudo mysql или sudo mariadb. В MySQL 8 из репозиториев Ubuntu root настроен так же, через плагин auth_socket. Если этот вход работает, пароль меняется одной командой ALTER USER, без остановки сервера.

Если сокетный вход отключён, а пароль потерян, используется классический способ. Сервер запускают с --skip-grant-tables --skip-networking, подключаются без пароля, выполняют FLUSH PRIVILEGES, затем ALTER USER, и возвращают обычный запуск. На системах с systemd опции передают через drop-in файл или переменную MYSQLD_OPTS, а не через mysqld_safe.

Старый рецепт UPDATE user SET password=PASSWORD(...) на MySQL 8 и MariaDB 10.4+ не работает. Ниже — порядок действий для MySQL 8.0/8.4 и MariaDB 10.11/11.x на Debian 12/13, Ubuntu 24.04 и AlmaLinux / Rocky Linux 9 и 10.

Шаг 0. Как у вас входит root

Попробуйте зайти от системного root:

sudo mysql        # MySQL или MariaDB
sudo mariadb      # MariaDB 10.11 и 11.x

Если появилось приглашение mysql> или MariaDB [(none)]>, сбрасывать ничего не нужно. Посмотрите, как настроен root:

-- MySQL 8
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';

-- MariaDB 10.4+
SHOW CREATE USER root@localhost;

Примерно так выглядит ответ в MariaDB на Debian:

CREATE USER `root`@`localhost` IDENTIFIED VIA mysql_native_password
  USING 'invalid' OR unix_socket

Это значит: пароль для root фактически не задан (invalid не совпадёт ни с одним хешем), а войти можно через сокет.

Система и СУБДКак root входит по умолчаниюКак попасть в базу
Debian 12/13, MariaDB 10.11 / 11.8unix_socketsudo mariadb
Ubuntu 24.04, MariaDB 10.11unix_socketsudo mariadb
Ubuntu 24.04, MySQL 8.0auth_socketsudo mysql
AlmaLinux / Rocky 9 и 10, MariaDBunix_socketsudo mysql
AlmaLinux / Rocky, MySQL из AppStreamпароль пустой, пока его не задалиmysql -u root
MySQL из репозитория Oracle (RPM)временный парольsudo grep 'temporary password' /var/log/mysqld.log

Почему root входит без пароля и это безопасно

Плагины unix_socket в MariaDB и auth_socket в MySQL проверяют не пароль, а того, кто подключился к сокету. Ядро сообщает серверу UID процесса на другом конце сокета. Если системный пользователь называется так же, как пользователь базы, вход разрешён. Подделать это из-под непривилегированного пользователя нельзя.

Получается, что доступ к root в базе есть только у того, кто уже root в системе. А тот, кто root в системе, и так может остановить сервер и прочитать файлы данных. Пароль здесь защиты не добавляет, зато появляется лишний секрет, который можно потерять или засветить в скрипте.

Отсюда практичная схема: root оставить на сокете, а для phpMyAdmin, бэкапов по сети и приложений создать отдельных пользователей с паролями и минимальными правами. Что ещё проверить после установки, описано в статье Настройка минимальной безопасности MySQL после установки.

В Ubuntu с MySQL есть ещё служебная учётка debian-sys-maint. Её пароль лежит в /etc/mysql/debian.cnf, файл читает только root. Если сокетный вход для root сломан, можно попробовать войти через неё:

sudo mysql --defaults-file=/etc/mysql/debian.cnf

Если у этой учётки есть права на управление пользователями, пароль root меняется без перезапуска сервера.

Смена пароля, когда доступ есть

Если вы вошли через сокет и всё-таки хотите задать root пароль, сохраните при этом сокетный вход.

MariaDB 10.4 и новее:

ALTER USER root@localhost
  IDENTIFIED VIA unix_socket
  OR mysql_native_password USING PASSWORD('Новый_Сложный_Пароль');

MySQL 8.0 и 8.4. Один пользователь в MySQL имеет один основной способ входа, поэтому при смене на пароль вход через сокет пропадёт: дальше только mysql -u root -p.

ALTER USER 'root'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'Новый_Сложный_Пароль';

Не используйте на MySQL 8.4 IDENTIFIED WITH mysql_native_password. В 8.4 этот плагин по умолчанию отключён, и вы получите ошибку о незагруженном плагине. caching_sha2_password — плагин по умолчанию в MySQL 8, его поддерживают актуальные клиенты и PHP-расширения mysqli и pdo_mysql.

FLUSH PRIVILEGES после ALTER USER не нужен. Эта команда нужна только после прямой правки системных таблиц через UPDATE или INSERT, а так делать не стоит.

Полный сброс через —skip-grant-tables

Этот способ нужен, если сокетный вход отключён, а пароль никто не помнит. Пока сервер работает в таком режиме, любой локальный пользователь может войти в базу с полными правами. Поэтому сеть отключаем, а сам режим держим минимальное время.

1. Узнайте имя службы и строку запуска

systemctl list-units --type=service | grep -Ei 'mysql|mariadb'
systemctl cat mariadb | grep ^ExecStart    # или mysql / mysqld

Имя службы: mariadb для MariaDB везде, mysql для MySQL в Debian и Ubuntu, mysqld для MySQL в AlmaLinux. Если в строке ExecStart есть $MYSQLD_OPTS, подойдёт вариант с переменной. Так устроена служба MariaDB и MySQL из пакетов Oracle. В Ubuntu строка MySQL выглядит просто как ExecStart=/usr/sbin/mysqld, переменную она не читает, и нужен drop-in файл.

2а. Вариант с MYSQLD_OPTS (MariaDB)

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

2б. Вариант с drop-in файлом (MySQL в Ubuntu и всё остальное)

sudo systemctl stop mysql
sudo systemctl edit mysql

В открывшемся редакторе впишите строки. Путь к бинарнику возьмите из вывода systemctl cat:

[Service]
ExecStart=
ExecStart=/usr/sbin/mysqld --skip-grant-tables --skip-networking

Пустая строка ExecStart= обязательна: она сбрасывает исходную команду, иначе systemd откажется запускать службу с двумя командами. Сохраните файл и запустите службу:

sudo systemctl start mysql
sudo systemctl status mysql --no-pager

systemctl edit сам выполнит daemon-reload. Если создаёте файл /etc/systemd/system/mysql.service.d/override.conf руками, выполните sudo systemctl daemon-reload перед запуском.

3. Подключитесь и задайте пароль

sudo mysql          # пароль не спросит

Порядок команд важен. В режиме --skip-grant-tables таблицы привилегий не загружены, и команды управления пользователями отключены. Если сразу выполнить ALTER USER, получите ошибку:

ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables
option so it cannot execute this statement

Сначала FLUSH PRIVILEGES загружает таблицы, затем ALTER USER работает:

FLUSH PRIVILEGES;

-- MySQL 8.0 / 8.4
ALTER USER 'root'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'Новый_Сложный_Пароль';

-- MariaDB 10.4+: пароль плюс сокет
ALTER USER root@localhost
  IDENTIFIED VIA unix_socket
  OR mysql_native_password USING PASSWORD('Новый_Сложный_Пароль');

Если пароль root вам не нужен, а нужно вернуть вход через сокет, хватит одной строки:

-- MariaDB
ALTER USER root@localhost IDENTIFIED VIA unix_socket;
-- MySQL в Ubuntu
ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket;

Если FLUSH PRIVILEGES падает с ошибкой Table 'mysql.servers' doesn't exist, повреждены системные таблицы. Это отдельная проблема, она разобрана в статье Ошибка ERROR 1146 (42S02): Table ‘mysql.servers’ doesn’t exist.

4. Верните обычный запуск

Для варианта с переменной:

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

Для drop-in файла:

sudo systemctl revert mysql
sudo systemctl restart mysql

systemctl revert удаляет все drop-in файлы службы в /etc/systemd/system. Если там были ваши собственные постоянные настройки, удалите только временный файл и выполните daemon-reload.

5. Проверьте

mysql -u root -p -e "SELECT CURRENT_USER(), @@skip_networking;"

Вход должен пройти с новым паролем, @@skip_networking — вернуться к прежнему значению. Обычно это 0; на серверах, где база слушает только сокет, — 1. Убедитесь, что без пароля посторонний пользователь не входит:

mysql -u root     # от обычного пользователя: должно быть Access denied

Почему старый способ не работает

В старых статьях, включая прежнюю версию этой, пароль меняли прямой правкой таблицы:

UPDATE mysql.user SET password = PASSWORD('...') WHERE user = 'root';
  • В MySQL 5.7 столбец password переименовали в authentication_string.
  • В MySQL 8.0 удалена функция PASSWORD(). Запрос даст синтаксическую ошибку.
  • В MariaDB 10.4+ mysql.user — представление (view) поверх таблицы mysql.global_priv. Менять пароль через UPDATE этой view нельзя.

Правильный инструмент во всех актуальных версиях — ALTER USER. Он сам выбирает плагин, считает хеш и обновляет привилегии в памяти.

Второй устаревший элемент — запуск mysqld_safe --skip-grant-tables вручную. На системах с systemd сервер управляется службой, а в пакетах MySQL для RPM-систем mysqld_safe вообще не входит. Ручной запуск в обход службы легко оставляет процесс от другого пользователя или без каталога для сокета /run/mysqld. Вариант через systemd надёжнее.

Безопасность

  • Сеть отключена. MySQL 8 сам включает skip_networking при --skip-grant-tables. Для MariaDB указывайте --skip-networking явно. Без этого любой, кто достучится до порта 3306, войдёт в базу без пароля.
  • Короткое окно. Режим без проверки прав держите несколько минут. Не уходите, не вернув обычный запуск.
  • Пароль не в командной строке. mysql -p'пароль' оставляет пароль в истории shell и в списке процессов. Используйте -p без значения: клиент спросит пароль сам.
  • История клиента. Клиент MySQL по умолчанию не пишет в ~/.mysql_history строки с IDENTIFIED и PASSWORD. Про клиент MariaDB этого не предполагайте: проверьте ~/.mysql_history и ~/.mariadb_history и удалите строку с паролем.
  • Файл с паролем. Если пароль нужен скриптам, храните его в ~/.my.cnf с правами 600, а не в cron-строке.
  • Root только локально. Учётки 'root'@'%' быть не должно. Для удалённого администрирования — отдельный пользователь, доступ через SSH-туннель или VPN.

Симптомы и решения

СимптомПричинаРешение
ERROR 1698 (28000): Access denied for user 'root'@'localhost'Root входит через сокет, а вы запускаете клиент не от rootsudo mysql; для приложений создать отдельного пользователя
ERROR 1045 (28000): Access denied ... (using password: YES)Неверный пароль или вход идёт под другим host (127.0.0.1 вместо localhost)Проверить SELECT user, host FROM mysql.user; при потере пароля — сброс
ERROR 1290 ... --skip-grant-tablesALTER USER до загрузки таблиц привилегийСначала FLUSH PRIVILEGES
Синтаксическая ошибка у PASSWORD('...')Функции нет в MySQL 8ALTER USER ... IDENTIFIED BY
Ошибка о незагруженном плагине mysql_native_passwordMySQL 8.4, плагин отключёнIDENTIFIED WITH caching_sha2_password
После правки службы пароль всё равно спрашиваютDrop-in не применилсяsystemctl daemon-reload, проверить пустую строку ExecStart=, systemctl cat
Служба не стартует после сбросаОстался drop-in с неверной строкой запускаsystemctl revert, journalctl -u mysql -n 50

Частые вопросы

Почему в Debian можно войти в MariaDB как root без пароля?

Root настроен на плагин unix_socket: сервер проверяет системного пользователя, подключившегося к сокету, а не пароль. Войти так может только тот, кто уже root в системе. Это не дыра, а штатная схема с MariaDB 10.4. Из обычной учётки или по сети такой вход не сработает.

Нужен ли FLUSH PRIVILEGES после ALTER USER?

В обычном режиме нет: ALTER USER, CREATE USER и GRANT сами обновляют привилегии в памяти. FLUSH PRIVILEGES нужен в двух случаях: в режиме --skip-grant-tables перед ALTER USER и после прямой правки системных таблиц.

phpMyAdmin не пускает под root, а в консоли sudo mysql работает. Что делать?

phpMyAdmin подключается с паролем, а root настроен на сокет. Не переводите root на пароль ради панели. Создайте отдельного пользователя с паролем и нужными правами, и используйте его.

Как сбросить пароль обычного пользователя базы?

Зайдите как root через sudo mysql и выполните ALTER USER 'user'@'localhost' IDENTIFIED BY 'новый_пароль';. Host должен совпадать с тем, что в mysql.user. Перезапуск и --skip-grant-tables не нужны.

Можно ли сбросить пароль без остановки сервера?

Да, если есть любой вход с правом управления пользователями: root через сокет, debian-sys-maint в Ubuntu или другой администратор. Без такого входа остаётся только перезапуск с --skip-grant-tables, а это несколько минут простоя.