mysql权限被篡改后,必须先查mysql.user表确认空密码、匿名用户或'%'主机等风险,再以--skip-grant-tables安全模式启动修复,重置密码、解锁账户、补全权限位并执行flush privileges,同时确保datadir属主为mysql:mysql且权限为750,selinux环境下还需restorecon重置上下文。

权限被篡改后,MySQL不会报“权限错误”就完事——它可能让你连都连不上、查不到库、甚至悄悄放行高危操作。修复不是靠猜,而是先确认哪块坏了,再针对性动刀。
查 mysql.user 表里有没有空密码、匿名用户或 % 主机
这是最常被利用的入口。直接连上去(如果还能连)执行:
SELECT User, Host, authentication_string FROM mysql.user;
重点盯三类风险:
-
''@'localhost'这种空用户名,删掉:DROP USER ''@'localhost'; -
'root'@'%'或'admin'@'%'这类无限制远程账号,改成具体网段,比如'root'@'192.168.10.%' -
authentication_string为空或长度明显异常(如不是 40/64/72 字符),说明密码字段被清空或写错
用 SHOW GRANTS 检查是否过度授权
SHOW GRANTS FOR 'app_user'@'10.10.20.%'; 看到 GRANT OPTION、FILE、SUPER 就要警觉——普通业务账号不该有这些。
特别注意角色继承:MySQL 8.0+ 的 SHOW GRANTS 默认不显示角色带的权限。要查全,得用:
SELECT * FROM role_edges WHERE TO_USER = 'app_user' AND TO_HOST = '10.10.20.%';
然后顺着 FROM_ROLE 去查 role_table_privs,否则你以为删了权限,实际还挂在角色上。
修复前必须进 --skip-grant-tables 安全模式
权限表本身坏了,正常启动根本加载不了权限系统。停服务后手动启:
sudo mysqld --skip-grant-tables --skip-networking --datadir=/var/lib/mysql &
此时 mysql -u root 直连,不用密码,但所有权限检查失效——这正是修表的前提。
常见修法:
- 重置 root 密码(8.0+):
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'newpass'; - 解锁账户:
UPDATE mysql.user SET account_locked = 'N', password_expired = 'N' WHERE User = 'root'; - 补全权限位:
UPDATE mysql.user SET Grant_priv = 'Y', Super_priv = 'Y' WHERE User = 'root'; - 最后一定跑:
FLUSH PRIVILEGES;,否则内存缓存不更新
chmod 750 /var/lib/mysql 是硬性要求,不是建议
哪怕你把 mysql.user 表修好了,如果 /var/lib/mysql 目录权限是 777 或属主不是 mysql:mysql,MySQL 启动时会直接退出,并在错误日志里写 secure-file-priv 相关警告。
必须做两件事:
-
sudo chown -R mysql:mysql /var/lib/mysql(路径以mysqld --verbose --help | grep datadir查到的真实值为准) -
sudo chmod 750 /var/lib/mysql(子目录自动继承,别逐个 chmod) - SELinux 开着?补一句:
sudo restorecon -Rv /var/lib/mysql
修完别急着 systemctl start mysql,先用 sudo mysqld --user=mysql --datadir=/var/lib/mysql --skip-grant-tables 手动试启——看到 ready for connections 再正式启服务。最容易被忽略的是:安全模式下改完权限不 FLUSH PRIVILEGES,或者修完权限忘了关 --skip-grant-tables,结果所有人免密登录。











