MySQL 8.0+ 禁止直接修改 mysql.user 表,因启用 caching_sha2_password 插件且权限系统强制通过 CREATE USER/GRANT 等语句管理,否则变更重启后丢失;须最小化 root 权限、限制登录 host、启用 SSL/X509 并禁用全局高危权限。

为什么直接改 mysql.user 表会失效
MySQL 8.0+ 默认启用 caching_sha2_password 插件,且权限系统不再允许直接用 UPDATE 或 INSERT 操作 mysql.user 等系统表——哪怕你有 root 权限。执行后不会报错,但重启或刷新权限后变更就丢了。
- 这是 MySQL 的安全加固机制,不是 bug,也不是配置问题
-
FLUSH PRIVILEGES不会生效,因为权限已由服务端缓存并校验插件状态 - 旧版(5.7)虽能写入,但可能引发认证失败:比如改了
authentication_string却没同步更新plugin字段
该用 CREATE USER 和 GRANT 替代直接写表
所有权限变更必须走 SQL 权限语句,MySQL 会自动校验逻辑、更新缓存、写入数据字典。
- 新建受限账号:
CREATE USER 'app_rw'@'10.20.%.%' IDENTIFIED BY 'pwd123' REQUIRE SSL; - 精确授权:
GRANT SELECT, INSERT, UPDATE ON mydb.orders TO 'app_rw'@'10.20.%.%'; - 禁止全局权限:
REVOKE SUPER, FILE, SHUTDOWN ON *.* FROM 'app_rw'@'10.20.%.%'; - 删掉多余账号比改 root 更安全:
DROP USER 'root'@'%';(只留'root'@'localhost')
root@localhost 的权限其实可以更窄
默认 root@localhost 拥有 ALL PRIVILEGES,但多数运维操作(如备份、慢日志分析、连接排查)并不需要 FILE 或 PROCESS 权限。
- 最小化示例:
GRANT SELECT, RELOAD, SHOW DATABASES, LOCK TABLES, EXECUTE ON *.* TO 'root'@'localhost'; -
FILE权限一旦开启,攻击者可通过SELECT ... INTO OUTFILE写 shell;PROCESS可看到其他用户明文 SQL - 如果用
mysqldump备份,只需RELOAD+LOCK TABLES+ 对应库的SELECT,不需要ALL
限制 root 登录来源比改密码更重要
很多团队花时间设复杂密码,却放任 root@'%' 存在——等于把钥匙挂在防火墙上。
- 立刻执行:
DROP USER 'root'@'%';(MySQL 8.0+ 默认存在,5.7 需确认) - 如需远程管理,建专用账号:
CREATE USER 'dba_admin'@'192.168.10.0/24' IDENTIFIED BY 'xxx' REQUIRE X509; - 操作系统层配合:MySQL 配置
bind-address = 127.0.0.1,彻底阻断外网root@localhost的 TCP 连接(仅 socket 可用)
真正难的不是语法,是意识到:权限控制的本质不是“谁能做什么”,而是“谁在什么网络上下文里能做什么”。host 字段、SSL 要求、plugin 类型,这三个条件缺一不可,漏一个就等于没锁门。


















