mysql库未被真正删除,需先执行show databases和ls /var/lib/mysql/mysql/确认;若目录为空或不存在才属真删,且无备份无binlog时即使跳过权限启动也无法恢复。

确认是否真丢了 mysql 库
先别急着修,mysql 库不是“被删了就一定没了”。很多运维脚本会显式排除它:mysqldump --all-databases --ignore-database=mysql,或备份时用了 --skip-lock-tables 但没加 --single-transaction 导致 mysql 库没被一致读取。登录后执行:SHOW DATABASES;,如果列表里没有 mysql,再查磁盘:ls /var/lib/mysql/mysql/ —— 若目录为空或不存在,才是真删了。
没备份也没 binlog?跳过权限启动也救不回来
--skip-grant-tables 只让你进得去,不代表能修好。MySQL 8.0 的 user 表有 password_last_changed、account_locked、password_reuse_history 等强制非空字段,漏填一个,FLUSH PRIVILEGES 后账户照样拒绝登录。常见错误包括:
- 直接
INSERT INTO mysql.user填空值,结果 root 登录报错Access denied for user 'root'@'localhost' - 用 MySQL 5.7 的 dump 文件往 8.0 里还原,
user表结构不兼容(比如少了password_reuse_history字段) - 手动
UPDATE user SET Select_priv='Y',但忘了设authentication_string或设成空字符串,导致认证失败
有 ROW 格式 binlog 才能精准恢复用户行
必须满足三个条件:binlog 开启(SHOW VARIABLES LIKE 'log_bin'; 返回 ON)、格式为 ROW(SHOW VARIABLES LIKE 'binlog_format';)、且日志文件保留到了误删前。关键操作是:
- 定位删除语句:
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000012 | grep -A 15 -B 5 "DELETE FROM mysql\.user" - 往上翻,找到同一用户的最后一次
INSERT或UPDATE,提取整行原始值(含authentication_string和时间戳) - 在
--skip-grant-tables模式下,用完整字段值REPLACE INTO mysql.user VALUES (...)插入,不能漏字段
备份恢复是最稳妥路径,但要注意版本和参数
哪怕你有 mysqldump --all-databases 备份,也可能无效——如果备份命令里带了 --ignore-database=mysql,或者用的是物理拷贝(只拷了业务库目录),mysql 库根本不在里面。真正可用的备份需满足:
- 包含
mysql库(检查 dump 文件头是否有CREATE DATABASE `mysql`) - 备份时加了
--skip-lock-tables --single-transaction(InnoDB 场景) - 恢复目标 MySQL 版本与备份生成版本一致或兼容(例如 8.0.33 备份不能直接在 5.7 上还原)
最常被忽略的一点:恢复后必须执行 mysql_upgrade(MySQL 5.7)或 mysqld --upgrade(8.0+),否则权限表字段缺失会导致后续授权失败。











