必须用--skip-grant-tables启动才能进入修复:先停服并杀进程,再以--skip-grant-tables --skip-networking启动,直连后检查mysql.user是否为空,若无root@localhost则需insert补全基础记录及权限字段,再update authentication_string和plugin,最后flush privileges并正常重启。

mysql.user表被清空后连不上,必须用--skip-grant-tables启动才能进
权限表清空后,mysql -u root -p 会直接报 ERROR 1045 (28000): Access denied,不是密码错,是根本没匹配到任何用户记录。你没法登录,就无法执行任何修复语句——得先绕过权限加载流程。
关键动作是停掉当前服务并手动启动一个跳过权限校验的实例:
- 先彻底杀掉所有
mysqld进程:sudo killall mysqld(Linux)或任务管理器结束mysqld.exe(Windows) - 加
--skip-networking启动(防远程未授权访问):sudo mysqld --skip-grant-tables --skip-networking --datadir=/var/lib/mysql & - 另开终端,直接运行
mysql -u root(不加-p),此时能进,但所有权限检查失效
进去了却查不到root@localhost,说明记录真没了
执行 USE mysql; 后运行:SELECT User, Host, plugin FROM user;,如果返回空或只有 root@127.0.0.1、root@%,没有 root@localhost,那就要手动补一条——MySQL 8.0+ 默认不建 localhost 行,清空后它就彻底消失了。
补记录不能只插用户名,必须匹配认证插件和密码哈希格式:
- 先确认你要用哪种插件:
mysql_native_password(兼容旧客户端)还是caching_sha2_password(8.0+ 默认) - 插一条基础
root@localhost:INSERT INTO user (Host, User, plugin, authentication_string, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, Create_tmp_table_priv, Lock_tables_priv, Execute_priv, Repl_slave_priv, Repl_client_priv, Create_view_priv, Show_view_priv, Create_routine_priv, Alter_routine_priv, Create_user_priv, Event_priv, Trigger_priv, Create_tablespace_priv, ssl_type) VALUES ('localhost', 'root', 'mysql_native_password', '', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y'); - 注意:
authentication_string先留空,等下用ALTER USER安全设密
ALTER USER设密码失败?因为--skip-grant-tables下不走插件验证逻辑
在 --skip-grant-tables 模式下执行 ALTER USER 'root'@'localhost' IDENTIFIED BY 'xxx'; 会报错,提示“operation not allowed”,这是正常行为——该模式禁用了用户管理类 DDL 的权限校验路径,但允许直写系统表。
正确做法分两步:
- 先用
UPDATE写入哈希值(需另一台同版本正常 MySQL 生成):UPDATE user SET authentication_string = '$A$...' WHERE User = 'root' AND Host = 'localhost'; - 再改插件(如果当前是
auth_socket或unix_socket):UPDATE user SET plugin = 'mysql_native_password' WHERE User = 'root' AND Host = 'localhost'; - 最后强制刷新:
FLUSH PRIVILEGES;(这步在 skip 模式下依然生效,且必不可少)
重启失败提示Table 'mysql.user' doesn't exist?说明系统库结构已损坏
如果删掉配置里的 skip-grant-tables 后,systemctl start mysqld 报 Table 'mysql.user' doesn't exist 或字段缺失(如 password_last_changed),说明不只是数据丢了,连表结构都异常了——可能是误删整个 mysql 库,或混用了不同版本的初始化脚本。
这时不能再修,得重建系统库:
- 备份原
mysql目录:mv /var/lib/mysql/mysql /var/lib/mysql/mysql_bak_$(date +%Y%m%d) - 用同版本二进制初始化:
mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql - 启动后立即用空密码登录:
mysql -u root -p(回车),再执行:ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass'; -
--initialize-insecure不生成随机密码,但 root@localhost 默认空密码,务必第一时间改密
系统库重建后,业务数据库不会丢,但所有用户权限、存储过程、事件等都得重配——这就是为什么清空 mysql 库比清空业务表危险得多。











