Что было. Перенос MySQL/MariaDB на новый сервер. Данные приложений перенеслись дампом, а попытка выгрузить и загрузить системную базу mysql (где хранятся пользователи) закончилась Table 'user' already exists и несовместимостями.
Почему так. Системная база это внутренность конкретной версии сервера: набор таблиц, их структура и способ хранения паролей отличаются между MySQL 5.7, 8.0, MariaDB 10.x и 11.x. Импортировать её дампом с другой версии нельзя и не нужно. Участники предложили перенести пользователей как команды, а не как таблицы; автор подтвердил.
Способ. На старом сервере получить список пользователей и для каждого его права:
SELECT CONCAT("SHOW GRANTS FOR '", user, "'@'", host, "';") FROM mysql.user
WHERE user NOT IN ('root','mysql.sys','mysql.session','mysql.infoschema','mariadb.sys','debian-sys-maint');
Выполнить полученные SHOW GRANTS FOR …;: вывод это готовые SQL-команды GRANT …, которые копируются на новый сервер. Пароли: на MySQL 8 SHOW CREATE USER 'u'@'h'; даёт CREATE USER … IDENTIFIED WITH … AS '<хеш>', что переносит хеш без знания пароля; на MariaDB SHOW GRANTS включает IDENTIFIED BY PASSWORD '<хеш>'. Если переносится между разными СУБД (MySQL ↔ MariaDB) или между сильно разными версиями, хеши могут не подойти: задать пароли заново и сообщить владельцам приложений.
Скрипт целиком (от пользователя с правами чтения mysql.*):
mysql -N -e "SELECT CONCAT('SHOW CREATE USER \'',user,'\'@\'',host,'\';') FROM mysql.user WHERE user NOT LIKE 'mysql.%' AND user<>'root'" \
| mysql -N | sed 's/$/;/' > users.sql
mysql -N -e "SELECT CONCAT('SHOW GRANTS FOR \'',user,'\'@\'',host,'\';') FROM mysql.user WHERE user NOT LIKE 'mysql.%' AND user<>'root'" \
| mysql -N | sed 's/$/;/' > grants.sql
На новом сервере: mysql < users.sql && mysql < grants.sql && mysql -e 'FLUSH PRIVILEGES'. Утилита pt-show-grants из Percona Toolkit делает то же одной командой.
Порядок переезда, который не ломается.
- Новый сервер установлен, обновлён,
mysql_secure_installationпройден. - Пользователи и права (как выше). Плагины аутентификации согласованы с приложениями (старые клиенты не умеют
caching_sha2_password). - Данные:
mysqldump --single-transaction --routines --triggers --events --databases app1 app2(без--all-databases, чтобы не тащитьmysql), импорт. mysql_upgrade/mariadb-upgradeпри смене версии.- Проверка приложений на новом сервере до переключения; старый сервер остаётся в режиме только чтение до финального дампа.
Что не переносить файлами. Каталог данных целиком между версиями (отдельный разбор про несовместимые журналы), таблицы mysql.*, ib_logfile*.
Команда описана в документации MariaDB.