FLUSH PRIVILEGES 仅在直接修改 mysql 系统表(如 UPDATE mysql.user)时必须执行;使用 GRANT/REVOKE/ALTER USER 等标准语句会自动刷新权限缓存,无需手动执行,且已存在连接须重连才生效。

绝大多数情况下,FLUSH PRIVILEGES 不是权限“不生效”的解药,而是掩盖真实问题的惯性操作。它只在你直接修改 mysql.user 等系统表时才真正必要;用 GRANT、REVOKE 或 ALTER USER 修改权限,MySQL 会自动同步内存缓存——加 FLUSH PRIVILEGES 不但多余,还可能让你忽略连接未重建、host 匹配失败等更关键的问题。
GRANT 后执行 FLUSH PRIVILEGES 是不是必须?
不是。MySQL ≥8.0.16 中,GRANT SELECT ON db.* TO 'u'@'h'; 会立即更新磁盘和内存权限缓存,新连接立刻可用。在 8.0.15 及更早版本中,虽存在极少数延迟场景,但官方推荐做法仍是重连验证,而非盲目刷新。
常见错误现象:
- 执行
GRANT后立刻用同一连接查SHOW GRANTS;,发现没变 → 这是正常的,当前连接权限快照已固化,与刷新无关 - 执行
FLUSH PRIVILEGES后仍连不上 → 很可能Host字段写错(如'u'@'localhost'vs'u'@'127.0.0.1'),或用户插件不兼容(如caching_sha2_password客户端不支持)
性能影响:每次 FLUSH PRIVILEGES 都会触发全局锁,短暂阻塞新连接认证和权限检查请求,高并发下可能引发瞬时雪崩。
什么时候真得执行 FLUSH PRIVILEGES?
仅当你绕过语义命令、直接 DML 操作权限表时才必须。它不是“让权限生效”,而是通知 MySQL:“磁盘上那几份权限表(mysql.user、mysql.db、mysql.tables_priv 等)已被手动改过,请全量重载进内存”。
必须刷新的典型场景:
UPDATE mysql.user SET authentication_string = SHA2('pwd', 256) WHERE User='u' AND Host='%';INSERT INTO mysql.db (Host, Db, User, Select_priv) VALUES ('%', 'testdb', 'u', 'Y');- 用脚本批量导入权限表后(如
mysql -u root mysql )
注意:FLUSH PRIVILEGES 不校验你写的 SQL 是否合法——如果误删了 authentication_string 或填错 Host,一刷就可能锁死 root 登录。
为什么刷了还是没权限?常见匹配陷阱
权限生效依赖精确的三元组匹配:User + Host + authentication_string 插件。刷完不生效,90% 是匹配环节出了问题,而不是缓存没刷干净。
排查要点:
- 确认登录时实际匹配的账户:
SELECT USER(), CURRENT_USER();—— 前者是“你怎么连的”,后者是“MySQL 认你是谁”,二者常不同 - 检查 host 是否通配正确:
'u'@'%.example.com'不匹配u@example.com,'u'@'localhost'和'u'@'127.0.0.1'是两个独立账户 - 验证插件兼容性:
SELECT User, Host, plugin FROM mysql.user WHERE User='u';,若为caching_sha2_password但客户端太老,连都连不上,权限再对也白搭 - 主从环境慎刷:在从库上直接改
mysql表并FLUSH PRIVILEGES,会导致主从权限分裂,复制线程可能报错中断
已建立连接的权限永远刷不“活”
FLUSH PRIVILEGES 只影响后续新建连接。每个连接在登录瞬间就拷贝了一份权限快照,之后无论你刷多少次,该连接看到的权限都不会变。这是设计使然,不是 bug。
这意味着:
- 改完全局权限(
*.*)后,必须断开重连才能生效 - 改库级权限(
db.*)后,执行USE db;即可触发新权限检查(部分版本中甚至无需USE) - 改表/列级权限后,下次对该对象发起查询(如
SELECT * FROM t;)即生效,不依赖重连
最容易被忽略的一点:你以为在“测试新权限”,其实一直在用旧连接跑命令。关掉终端、换新 shell、或显式 EXIT; 再登录,比反复刷缓存管用得多。


















