直接改mysql.user表后权限不生效,是因为MySQL 8.0+权限缓存不自动更新且手动写入易破坏字段格式与认证逻辑;UPDATE后即使执行FLUSH PRIVILEGES仍可能因authentication_string哈希错误、plugin不匹配或host未精确匹配而失效。

直接改 mysql.user 表后权限不生效,是因为 MySQL 8.0+ 的权限缓存不会自动更新,且手动写入极易破坏字段格式或认证逻辑——这不是“没刷”,是根本没被系统认可。
为什么 UPDATE mysql.user 后执行 FLUSH PRIVILEGES 还是不行
MySQL 8.0 要求 authentication_string 字段必须是合法 SHA256 哈希值,并与 plugin 字段严格匹配(如 caching_sha2_password)。手动 UPDATE 很可能:
- 填错哈希格式(比如用了 MD5 或明文)
- 漏改
plugin字段,导致认证插件和密码格式不兼容 - 写错字段名(如仍用旧版的
Password字段) - 未同步更新
account_locked、password_last_changed等状态字段,触发静默拒绝
FLUSH PRIVILEGES 只负责重载数据,不校验合法性。一旦写入非法值,重载后反而让账号彻底不可用。
GRANT 和 ALTER USER 为什么比手改表可靠
这些语句由 MySQL 内核驱动,会自动处理:
- 生成符合当前
plugin的密码哈希(ALTER USER ... IDENTIFIED BY) - 设置配套字段(如
password_last_changed、password_lifetime) - 触发权限缓存同步,无需额外
FLUSH PRIVILEGES - 校验 host/user 匹配规则,避免空格、大小写、IP vs socket 等隐性错误
例如:ALTER USER 'u'@'localhost' IDENTIFIED BY 'pwd'; 比 UPDATE mysql.user SET authentication_string = 'xxx' WHERE User='u' 安全得多——后者漏掉 Host 条件就可能批量污染其他账号。
权限“看起来存在”但连不上,最常踩的三个坑
不是表没改对,而是连接根本没匹配到那行记录:
-
'u'@'localhost'和'u'@'127.0.0.1'是两个账号:前者走 socket,后者走 TCP;你授权的是前者,但客户端默认连后者 - 客户端解析出的实际 host 是
'u'@'192.168.1.100',而你只给了'u'@'%'——看似通配,但 MySQL 不会把 IP 反向解析成域名,%也不匹配 IPv6 的::1 - 执行
SELECT USER(), CURRENT_USER();发现两者不一致:前者是“你声明的身份”,后者才是 MySQL 实际查到的账号;权限只作用于CURRENT_USER()对应的那一行
真正危险的操作,不是忘了 FLUSH PRIVILEGES,而是以为改了磁盘就等于改了权限——MySQL 8.0 的权限系统早已不是“改表即生效”的简单模型,它依赖字段一致性、插件协同和连接时的精确匹配。任何绕过标准语句的修改,都得先问一句:这个值,MySQL 自己会不会生成?


















