FLUSH PRIVILEGES仅在直接修改mysql系统表(如UPDATE mysql.user)时必需,因MySQL权限缓存启动时加载且不自动更新;GRANT/ALTER USER等标准操作会自动同步内存与磁盘,无需执行该命令。

因为 MySQL 不会自动重载内存中的权限缓存,改完权限后不执行 FLUSH PRIVILEGES,新权限对新连接完全无效。
MySQL 权限是缓存在内存里的
MySQL 启动时把 mysql.user、mysql.db 等权限表加载进内存,后续所有连接鉴权都查这份缓存,而不是实时读表。phpMyAdmin 的「执行」按钮只是向这些表写入数据(比如 UPDATE mysql.user SET Select_priv='Y' WHERE User='app'),但不会触发内存刷新。
常见表现包括:
- 新建用户连不上,报
Access denied for user - 明明勾了
SELECT却仍被拒绝查询 - 刷新 phpMyAdmin 页面后,刚设的权限又变回去了
GRANT/REVOKE 为什么有时不用 FLUSH PRIVILEGES
GRANT 和 REVOKE 是特权语句,MySQL 8.0+ 默认会在执行后自动重载权限缓存——但这只在语句成功执行的前提下成立。
立即学习“PHP免费学习笔记(深入)”;
容易出问题的情况:
- 当前账号没
GRANT OPTION,导致GRANT静默失败(界面显示“成功”,实际没写入) - 用了
caching_sha2_password插件,而 phpMyAdmin 5.2.3 之前版本不兼容,认证阶段就中断,GRANT根本没执行 - 目标用户不存在,
GRANT报错但 phpMyAdmin 没透出错误信息
所以不能依赖“用了 GRANT 就一定生效”,始终用 SHOW GRANTS FOR 'u'@'h'; 验证输出是否变化。
FLUSH PRIVILEGES 执行失败的三个真实原因
看到 ERROR 1227 (42000): Access denied; you need (at least one of) the RELOAD privilege(s),不是命令错了,而是:
- 当前登录账号没
RELOAD权限:必须换root或其他带该权限的用户重登 - 连的是只读副本(如阿里云 RDS 只读实例、ProxySQL 路由到从库):
FLUSH PRIVILEGES只能在主库执行,且不会同步 - MySQL 配置了
skip-grant-tables或启用了只读模式(read_only=ON),语句直接被拒绝
别在 Docker 或托管环境里盲目重试——先确认你连的是主库,再查 SELECT @@read_only; 和 SELECT @@skip_grant_tables;。
Host 字段不匹配是最隐蔽的坑
MySQL 把 'user'@'localhost' 和 'user'@'127.0.0.1' 当作两个完全不同的用户,权限互不影响。
你用 phpMyAdmin 修改的是前者,但应用连的是后者(比如 PHP mysqli_connect('127.0.0.1')),那无论怎么 FLUSH PRIVILEGES 都没用。
排查方法很简单:
- 看应用报错里的用户名和 host:比如
Access denied for user 'app'@'192.168.1.100' - 在 SQL 页运行
SELECT User, Host FROM mysql.user WHERE User = 'app';,确认是否存在对应记录 - 用
SHOW GRANTS FOR 'app'@'192.168.1.100';直接查该账号的实际权限
真正卡住的往往不是语法或权限名拼错,而是这一行里多了一个空格、少了一个反引号,或者大小写不一致——MySQL 对数据库名、表名、host 字符串都是严格匹配的。



















