grant/alter user在mysql 8.0.16+中自动同步磁盘与内存权限,无需flush privileges;该命令仅在直接update mysql.user等系统表时必需,且不影响已存在连接,新权限需重连生效。

GRANT/ALTER USER 自动同步内存与磁盘权限
MySQL 8.0.16 起,所有标准权限语句(GRANT、REVOKE、CREATE USER、ALTER USER、SET PASSWORD)在执行成功后,会原子性地完成两件事:写入 mysql.user 等系统表(磁盘持久化),同时更新内存中的 ACL 结构(如 acl_users 数组)。这意味着你敲完 ALTER USER 'u'@'%' IDENTIFIED BY 'p'; 并收到 Query OK,权限就已对新连接生效——FLUSH PRIVILEGES 完全不参与这个流程。
FLUSH PRIVILEGES 只响应“绕过 SQL 接口”的操作
它不是权限生效的开关,而是强制重载信号:清空内存中全部权限缓存,再从磁盘完整读取 mysql.user、mysql.db、mysql.tables_priv 等 6 张表重建 ACL。这个机制只在以下场景真正必要:
- 用
UPDATE mysql.user SET authentication_string = '$A$...'手动改哈希值 - 用
INSERT INTO mysql.db直接插入库级权限记录 - 用
mysqldump --no-create-info mysql user db导入权限表后未走GRANT流程
这些操作 MySQL 完全不感知,内存缓存仍是旧的,不 FLUSH PRIVILEGES 就永远不生效。但这类操作本身就不该出现在生产环境。
执行了 FLUSH PRIVILEGES 却仍不生效?真因不在“刷没刷”
常见误判是把现象归咎于刷新动作,实际卡点往往更底层:
- 当前连接仍持有旧权限快照,必须
QUIT后重连,FLUSH PRIVILEGES不影响已存在会话 -
'u'@'localhost'和'u'@'127.0.0.1'是两个独立账号,改了一个,另一个完全不受影响 - MySQL 8.0 默认
caching_sha2_password插件,老客户端(如旧版 JDBC)可能静默降级失败,表现为“能连但权限不对” - 执行
FLUSH PRIVILEGES需要RELOAD权限,普通用户直接报ERROR 1227 (42501): Access denied
验证权限是否真正生效,别信命令返回,要看实际行为
最可靠的方式永远是实操验证:
- 用
CURRENT_USER()确认当前会话匹配的是哪条user@host记录 - 新开终端,用新密码尝试登录:
mysql -u u -p,而不是复用旧连接 - 执行一条受控语句测试,比如
SELECT * FROM db.t(表级权限)、USE db(库级权限)或SHOW DATABASES(全局权限)
复杂点在于:权限生效不是全局实时的,而是按粒度分层加载;最容易被忽略的,永远是你以为连的是目标实例,其实连的是 Docker 容器里那个、Homebrew 装的那个、或者系统自带的老版本 MySQL。











