权限修改后需执行flush privileges才能生效,因mysql不会自动重载权限表;直接update系统表后必须刷新,grant在8.0+通常自动刷新但例外情况仍需手动执行。

权限改了但不生效,先确认是不是忘了刷新
MySQL 的权限变更不会自动实时生效,必须显式执行 FLUSH PRIVILEGES 才会让服务重新加载 mysql.user 等系统表。很多人改完 GRANT 或直接 UPDATE 了权限表,就去连数据库,结果还是被拒绝——根本原因就是卡在这一步。
常见错误现象:Access denied for user 'xxx'@'%' (using password: YES),而你明明刚执行过 GRANT SELECT ON db.* TO 'xxx'@'%'。
-
FLUSH PRIVILEGES是唯一强制重载权限的方式,重启 mysqld 也能生效,但没必要 - 只对当前 MySQL 实例生效,不影响其他节点(主从、集群需各自执行)
- 如果用的是 MySQL 8.0+ 并通过
CREATE USER/GRANT操作,部分场景下可跳过该命令(因为语句本身会触发内部刷新),但直接 UPDATEmysql.user后必须刷
直接 UPDATE 权限表后不刷新,大概率立刻失效
绕过 GRANT 语句、手动 UPDATE mysql.user 或 mysql.db 表是高危操作,MySQL 不会监听这些表变化,也不会自动同步到内存权限缓存中。
使用场景:批量修复用户 host 错误、紧急禁用某类账号、迁移旧版本权限数据。
- UPDATE 后必须跟
FLUSH PRIVILEGES,否则新值只是躺在磁盘上,连接时仍按旧缓存判断 - UPDATE 前建议先
SELECT确认目标行,避免误改authentication_string或account_locked字段导致锁死 - MySQL 8.0+ 中
password_expired、password_last_changed等字段受内部逻辑保护,单纯 UPDATE 可能被忽略,优先用ALTER USER
GRANT 之后还要不要 FLUSH PRIVILEGES?看 MySQL 版本和操作方式
不是所有 GRANT 都需要手动刷新。MySQL 5.7 及以前,GRANT 语句本身会写权限表并通知缓存更新;MySQL 8.0+ 使用数据字典存储权限,GRANT 已内置刷新逻辑。
但以下情况仍要主动执行:INSERT INTO mysql.user ...、UPDATE mysql.user SET ...、用工具导出导入权限表后。
- 安全起见,只要动过
mysql库里的表,统一执行一次FLUSH PRIVILEGES,没坏处 -
GRANT失败报错(如语法错、用户不存在)时,别以为“没成功就不影响”,失败前可能已部分写入,此时也建议刷一下清状态 - 注意权限作用域:改了
user表的全局权限,但用户当前连接仍用旧权限,新连接才生效;已有连接需KILL或等其断开
FLUSH PRIVILEGES 执行失败或没反应?检查权限和上下文
FLUSH PRIVILEGES 是特权语句,要求执行者拥有 RELOAD 权限。普通应用账号通常没有,容易在自动化脚本里静默失败。
常见错误现象:ERROR 1227 (42501): Access denied; you need (at least one of) the RELOAD privilege(s) for this operation。
- 用 root 或具备
RELOAD权限的账号执行,比如创建时加WITH GRANT OPTION的管理账号 - 在 MySQL 8.0+ 中,
RELOAD已拆分为更细粒度权限(如RELOAD控制FLUSH类命令,SYSTEM_VARIABLES_ADMIN控制变量刷新),确保权限完整 - 某些托管 MySQL(如阿里云 RDS、AWS RDS)禁用了
FLUSH PRIVILEGES,改权限只能走控制台或白名单 API,这时候报错是正常的
权限这事,写进去是一回事,加载进内存是另一回事。缓存不刷,再准的 SQL 也白搭。尤其跨版本迁移或混用 GRANT 和直接 UPDATE 时,多敲一行 FLUSH PRIVILEGES 花不了两秒,省得查半小时连不上到底谁背锅。











