直接update mysql.user在mysql 5.7中几乎必然失败,因其表为只读视图,裸update会跳过字段校验与默认值填充,触发error 1364等错误导致登录失败;flush privileges无法修复已写入的非法记录,正确做法是用alter user严格匹配完整账号(如'app_user'@'localhost')安全修改主机限制。

直接 UPDATE mysql.user 在 MySQL 5.7 中几乎必然失败
不能安全地通过 UPDATE mysql.user SET host = '%' 修改主机限制。MySQL 5.7.6+ 的 mysql.user 表是只读视图,底层由数据字典驱动,字段如 authentication_string、password_expired、account_locked、ssl_cipher 等受服务端强校验约束。裸 UPDATE 会跳过认证插件逻辑和字段默认值填充,触发类似 ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value 的错误,导致用户无法登录或权限丢失。
为什么 FLUSH PRIVILEGES 也救不了 UPDATE 操作
FLUSH PRIVILEGES 只重新加载内存中的权限缓存,但它不修复已写入的非法记录。如果你强行执行了 UPDATE 并 FLUSH,MySQL 会在下次验证该用户时发现字段缺失或格式错误(比如 authentication_string 是空或旧式哈希),直接拒绝认证——不是“没生效”,而是“已损坏”。
- 即使语句显示
Query OK, 1 row affected,也不代表数据合法 -
SELECT host, user FROM mysql.user WHERE user = 'xxx'能查到结果,但登录时仍报Access denied - 部分字段(如
plugin)未同步更新,会导致认证插件找不到对应密码哈希路径
正确做法:用 ALTER USER 替代 UPDATE,并严格匹配账号全称
MySQL 5.7.6+ 要求用 ALTER USER 安全修改主机限制,它会自动处理插件适配、哈希生成与元数据一致性。关键点是:必须指定完整账号('user'@'host'),不能只写用户名。
- 把
'app_user'@'localhost'改成允许任意主机连接:ALTER USER 'app_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'newpass'; - 若不想改密码,先查当前插件和哈希:
SELECT plugin, authentication_string FROM mysql.user WHERE user = 'app_user' AND host = 'localhost';
再复用:ALTER USER 'app_user'@'localhost' IDENTIFIED WITH mysql_native_password AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'; - 批量操作不能写
ALTER USER ... , ...;需用SELECT CONCAT(...)生成单条语句,逐条执行并校验
MySQL 5.6 或更低版本怎么办
这些版本不支持 ALTER USER,但也**禁止直接 UPDATE user 表**。必须走授权路径:CREATE USER + GRANT + DROP USER,因为 GRANT 会自动补全所有必需字段(如 x509_issuer、ssl_type),而 DROP USER 才能彻底清理旧账号记录。
- 例如迁移
'dev'@'192.168.1.100'到'dev'@'10.0.0.5':CREATE USER 'dev'@'10.0.0.5' IDENTIFIED BY 'pwd';GRANT SELECT, INSERT ON mydb.* TO 'dev'@'10.0.0.5';DROP USER 'dev'@'192.168.1.100'; - 漏掉
DROP USER会导致同一用户名在多个 host 下共存,权限继承混乱
实际执行前务必确认 MySQL 版本(SELECT VERSION();),并备份 mysql.user 表(mysqldump mysql user > user_backup.sql)。任何绕过 ALTER USER 或 GRANT/DROP 流程的操作,在 5.7+ 上都属于高危误操作。











