绝大多数情况下grant后无需flush privileges,因其自动刷新权限;仅在直接修改mysql系统表后才需执行;全局权限变更须新建连接生效,而库表级权限对当前连接后续查询即时生效。

GRANT 之后到底要不要执行 FLUSH PRIVILEGES?
绝大多数情况下,GRANT(或 REVOKE)语句本身就会立即生效,不需要手动 FLUSH PRIVILEGES。MySQL 在执行权限变更语句时,会自动重载权限表并刷新内存中的权限缓存。
只有当你绕过 GRANT,直接用 INSERT/UPDATE/DELETE 修改 mysql.user、mysql.db 等系统表后,才必须执行 FLUSH PRIVILEGES —— 因为此时 MySQL 不知道你动了底层数据。
- 用
GRANT SELECT ON mydb.* TO 'u1'@'localhost'→ 权限立刻可用,新连接和已有连接(对后续查询)都受新权限约束 - 用
UPDATE mysql.user SET Select_priv='Y' WHERE User='u1'→ 必须跟FLUSH PRIVILEGES,否则无效果 -
FLUSH PRIVILEGES会强制重读所有权限表,代价略高,频繁调用可能短暂阻塞其他权限相关操作
哪些权限变更需要新连接才能体现?
部分权限(尤其是全局级权限)只在用户建立连接时检查一次,因此修改后,已存在的连接不会“降权”或“升权”,必须新建连接才能应用新权限。
典型例子:SUPER、PROCESS、REPLICATION CLIENT、CREATE USER 等全局权限,以及影响连接行为的设置(如 max_connections 相关限制)。
- 当前连接执行
GRANT SUPER ON *.* TO 'admin'@'%'→ 该连接仍无法使用KILL或SET GLOBAL,除非断开重连 - 数据库/表级权限(如
SELECT ON mydb.t1)通常对当前连接后续查询即时生效(只要没在事务中缓存旧权限状态) - 如果用
SET ROLE切换角色,角色权限可即时切换,不依赖重连
FLUSH PRIVILEGES 执行失败的常见原因
FLUSH PRIVILEGES 报错,往往不是语法问题,而是权限或状态异常导致。
- 执行者没有
RELOAD权限 → 报错ERROR 1227 (42000): Access denied; you need (at least one of) the RELOAD privilege(s) for this operation - MySQL 正在以
--skip-grant-tables启动 → 此时权限系统被禁用,FLUSH PRIVILEGES无意义且可能报错 - 系统表损坏(如
mysql.user表结构与当前版本不兼容)→ 可能触发Table 'mysql.user' doesn't exist或内部断言错误 - 在 Group Replication 或 InnoDB Cluster 中,该命令不能在非 primary 节点执行
生产环境权限变更的推荐流程
避免临时拼接 SQL、跳过审计、直改系统表。应把权限变更当作配置变更来管理。
- 始终优先用
GRANT/REVOKE,而非UPDATE mysql.*;它们自带校验、记录 binlog(如果开启)、兼容性更好 - 批量变更建议写成单个事务化的脚本,例如:先
REVOKE再GRANT,避免中间态权限缺口 - 若需确认权限是否生效,用
SHOW GRANTS FOR 'u'@'h'查看结果,而不是依赖SELECT * FROM mysql.user—— 后者展示的是原始数据,不反映实际生效逻辑(比如列值为 'Y' 但 host 匹配失败就无效) - 自动化平台中,禁止无条件插入
FLUSH PRIVILEGES;应根据操作方式(是 GRANT 还是 DML)动态决定是否执行
最常被忽略的一点:权限生效 ≠ 功能可用。比如授予 SELECT 权限后,还可能因 SQL mode、字符集、存储引擎限制或行级安全策略(如 MySQL 8.0 的 CREATE POLICY)而实际查不到数据。











