直接改 mysql.user 表没生效,因 mysql 8.0+ 启用权限缓存且绕过校验逻辑,需用 alter user、grant 等标准语句触发自动刷新与一致性校验。

直接改 mysql.user 表为什么没生效
MySQL 8.0+ 默认启用缓存权限,UPDATE 或 INSERT 到 mysql.user 表后,内存里的权限结构不会自动刷新。你改了表,但连接时用的还是旧权限快照。
- MySQL 启动时加载一次权限表到内存,后续只响应
FLUSH PRIVILEGES或特定 DDL(如CREATE USER)触发重载 - 直接
UPDATE mysql.user属于底层数据操作,绕过了权限系统校验逻辑,甚至可能写入非法值(比如空密码哈希、错位的插件字段) - 5.7 及更早版本虽支持该方式,但必须配
FLUSH PRIVILEGES;8.0+ 中部分字段(如authentication_string格式)已变更,手动更新极易出错
FLUSH PRIVILEGES 还不生效?检查这几个点
执行了 FLUSH PRIVILEGES 却仍连不上、权限不对,大概率是权限作用域或认证机制没对上。
- 确认修改的是当前连接用户实际匹配的行:
Host和User必须完全匹配客户端来源(比如'user'@'192.168.1.%'不等价于'user'@'%') - MySQL 8.0+ 默认使用
caching_sha2_password插件,若手动更新plugin字段为mysql_native_password,但客户端不支持或未指定,会静默回退认证失败 -
FLUSH PRIVILEGES不影响已存在的连接,新权限只对后续新建连接生效;已有连接需重新登录 - 某些托管环境(如阿里云 RDS、腾讯云 CDB)禁用直接修改系统表,
FLUSH PRIVILEGES本身也会被拒绝
应该用什么方式安全改权限
走标准授权语句,让 MySQL 自己处理底层一致性与缓存刷新。
- 改密码:用
ALTER USER 'u'@'h' IDENTIFIED BY 'pwd'(8.0+)或SET PASSWORD FOR 'u'@'h' = 'pwd'(5.7) - 调权限:用
GRANT SELECT, INSERT ON db.* TO 'u'@'h',再加WITH GRANT OPTION如需转授 - 删用户:用
DROP USER 'u'@'h',别用DELETE FROM mysql.user—— 它不会清理mysql.db等关联表 - 新增用户且赋权:一步到位用
CREATE USER 'u'@'h' IDENTIFIED BY 'pwd'; GRANT ...,避免中间态权限不一致
哪些字段绝对不要手改 mysql.user
这些字段由 MySQL 内部管理,手动写入极易破坏认证流程或导致无法登录。
-
authentication_string:SHA256 哈希格式复杂,且依赖plugin字段;用ALTER USER自动生成最稳妥 -
password_last_changed、password_lifetime:涉及密码过期策略,手动设错会导致账户被锁 -
account_locked:虽然可设,但应优先用ALTER USER 'u'@'h' ACCOUNT LOCK,它会同步处理状态与日志 -
plugin:除非明确知道客户端兼容性,否则不要随意改;比如从caching_sha2_password改成mysql_native_password后,老客户端能连,但新客户端可能报Client does not support authentication protocol
真要 debug 权限问题,优先查 SELECT * FROM mysql.user WHERE User='xxx'\G 看原始值,但所有变更动作,都交给 CREATE/ALTER/DROP USER 和 GRANT/REVOKE 处理。系统表是结果,不是接口。











