根本原因是连接未匹配授权账号或未重连,而非缓存未刷新;'u'@'localhost'与'u'@'127.0.0.1'是两个独立账号,权限检查只在连接建立时生效,旧连接需QUIT后重新登录才应用新权限。
FLUSH PRIVILEGES执行成功但权限仍不生效,根本原因不是缓存没刷,而是你连的不是那个账号
命令返回 Query OK 只说明内存权限表重载了,不代表你当前连接用的就是刚授权的账号。最常见的情况是:'u'@'localhost' 和 'u'@'127.0.0.1' 在 MySQL 里是两个完全独立的账号,而 Navicat、PHP 或命令行默认走 TCP(即 127.0.0.1),你却只给 localhost 授权。
- 用
SELECT User, Host FROM mysql.user WHERE User = 'u';确认是否存在匹配你连接方式的记录 - 检查客户端实际连接串:如果填的是
127.0.0.1或留空 host,默认走 TCP;填localhost才可能走 socket(取决于 MySQL 配置) - Navicat 连接设置里显式勾选 “Use socket” 才会尝试走
localhost,否则一律按 IP 处理 - IPv6 环境下,
::1也需要单独授权,%不覆盖它
GRANT 后加 FLUSH PRIVILEGES 是冗余操作,还可能误导你忽略重连
MySQL 5.7+ 中,GRANT 和 REVOKE 语句本身就会同步磁盘与内存,FLUSH PRIVILEGES 加了也不报错,但纯属“做了没用的事”。如果你发现加了它才“好像生效”,大概率是因为你顺手退出重连了——真正起作用的是重连,不是刷新。
- 已有连接的权限在建立那一刻就固定了,不会随
FLUSH PRIVILEGES动态更新 - 必须执行
QUIT;后重新登录,或用新连接验证,比如mysql -u u -p -h 127.0.0.1 - 应用代码里不要写
FLUSH PRIVILEGES—— 它不该出现在业务逻辑中 - 脚本中若用
mysql -e "GRANT ...; FLUSH PRIVILEGES;",删掉后半句更安全
MySQL 8.0+ 认证插件不兼容,FLUSH PRIVILEGES 根本救不了
当你看到 Access denied 但用户名密码没错,或者 Navicat 提示 “Client does not support authentication protocol”,基本就是 caching_sha2_password 插件和老客户端不匹配。此时 FLUSH PRIVILEGES 刷一百遍也没用,因为问题出在认证环节,压根还没走到权限校验。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
- 查当前用户插件:
SELECT Host, User, plugin FROM mysql.user WHERE User = 'u'; - 若 plugin 是
caching_sha2_password且环境不支持,改用:ALTER USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 改完再执行
FLUSH PRIVILEGES;(仅在此类 ALTER USER 场景下有意义,因部分旧版本不自动刷新) - PHP 使用
mysqli或PDO时,确保驱动版本 ≥ 7.4 或启用MYSQLI_OPT_CONNECT_TIMEOUT兼容层
托管环境或 --skip-grant-tables 下,FLUSH PRIVILEGES 直接被禁用或无效
阿里云 RDS、腾讯云 CDB 等托管服务默认禁用 FLUSH PRIVILEGES,执行直接报 ERROR 1227 (42501): Access denied。另外,如果 MySQL 启动时加了 --skip-grant-tables,所有权限逻辑被跳过,GRANT 不写表、FLUSH 无意义、连 root 都无法被限制。
- 检查启动参数:
ps aux | grep mysqld,确认没有--skip-grant-tables - 托管环境应通过控制台或 API 修改权限,而非 SQL 命令
- 本地开发环境误启该模式后,需停服务、删掉配置文件中的 skip 参数、再重启
- docker run 启动时若加了
--skip-grant-tables,镜像内权限系统形同虚设
真正卡住的地方,往往不是命令敲错了,而是你正在连的实例、账号、协议、插件,四个维度里至少有一个没对上。验证前先问自己:我改的是哪个 'u'@'host'?我连的是同一个 host 吗?我用的是哪个认证插件?我是不是还在用旧连接?