FLUSH PRIVILEGES仅重载磁盘权限表至内存,不校验合法性、不修复插件冲突、不影响已存在连接;权限生效需匹配User@Host、通过认证插件、并重新登录。

FLUSH PRIVILEGES 本身没“失效”,而是它根本没解决你遇到的问题
执行 FLUSH PRIVILEGES 后权限仍不生效,几乎从不因为命令执行失败(比如报错),而总是因为:你误以为它该管的事,其实它不管。这个命令只做一件事——从磁盘的 mysql.user、mysql.db 等表里全量重载权限数据到内存。它不校验字段合法性,不修复认证插件冲突,也不影响已有连接。
- 如果用
GRANT或ALTER USER修改权限,FLUSH PRIVILEGES是冗余操作,加了也白加 - 如果直接
UPDATE mysql.user改了authentication_string却填了明文或错误哈希,FLUSH PRIVILEGES会把非法值加载进内存,账号反而彻底不可用 - 如果 MySQL 正在
--skip-grant-tables模式下运行,所有权限检查被跳过,FLUSH PRIVILEGES根本不触发任何缓存更新 - 托管服务(如阿里云 RDS)通常禁用该命令,直接返回
ERROR 1227 (42501)
新权限对当前连接完全无效,和 FLUSH 无关
MySQL 在连接建立那一刻就固化了该连接的权限快照。无论你执行多少次 FLUSH PRIVILEGES,已存在的连接看到的仍是初始授权状态。这不是 bug,是设计使然。
- 必须执行
QUIT;后重新登录,或用新客户端连接验证(例如mysql -u u -p -h 127.0.0.1) -
SELECT USER(), CURRENT_USER();能暴露真实匹配账号:前者是你“自称”的用户,后者才是 MySQL 实际查到并应用权限的那一行User@Host - 常见错配:
'u'@'localhost'(socket 连接)和'u'@'127.0.0.1'(TCP 连接)是两个独立账号,Navicat 默认走后者,但很多人只授了前者
Host 匹配失败比缓存没刷更常见
权限是否生效,第一步永远是“能不能匹配到那条 User@Host 记录”。FLUSH PRIVILEGES 刷得再勤,如果客户端解析出的 host 和你授权的 host 字符串不精确一致,权限就压根不会被加载。
- 检查实际匹配记录:
SELECT User, Host FROM mysql.user WHERE User = 'u';,确认存在'u'@'127.0.0.1'或'u'@'%'(注意:%不匹配::1) - Host 字段区分大小写、前后空格敏感;
'u '@'localhost'(末尾空格)和'u'@'localhost'完全是两回事 - IPv6 地址
::1必须单独授权,%不覆盖它 - Docker 或远程环境里,客户端看到的 host 往往是容器 IP 或 NAT 后的真实出口 IP,不是你本地写的
localhost
认证插件不兼容时,FLUSH PRIVILEGES 完全无能为力
当出现 Access denied 但用户名密码没错,或 Navicat 提示 “Client does not support authentication protocol”,问题发生在认证环节,还没走到权限校验阶段。此时刷新权限缓存毫无意义。
- 查当前插件:
SELECT Host, User, plugin FROM mysql.user WHERE User = 'u'; - 若为
caching_sha2_password且客户端老旧(如 MySQLdb、旧版 PHP mysqli),需切换回mysql_native_password:ALTER USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 改完插件后,
FLUSH PRIVILEGES在 MySQL 8.0.15 及更早版本中才需要(因部分旧版本不自动同步 plugin 字段),8.0.16+ 已自动处理 - 某些客户端(如老版 Workbench)会静默降级失败,表现为能连上但权限查不到、
SHOW GRANTS为空
真正容易被忽略的是:权限生效不是单点动作,而是“账号匹配 → 认证通过 → 权限加载”三步链。其中任意一环断开,FLUSH PRIVILEGES 都只是在给一个没通电的灯泡擦玻璃。











