mysql 5.7.6+ 中 password() 已弃用,authentication_string 需匹配认证插件格式;update 直接修改易失败,应使用 alter user 并确保 plugin、host、密码强度等配置正确。

UPDATE user SET authentication_string = PASSWORD('xxx') 为什么总失败
因为 PASSWORD() 函数在 MySQL 5.7.6+ 中已被弃用,返回值格式与认证插件不兼容;authentication_string 字段要求的是符合当前认证插件(如 mysql_native_password)的哈希串,不是旧式加密结果。直接塞进去,登录时插件直接拒绝校验。
-
PASSWORD()生成的是 16 字节旧哈希(如*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9这类 41 位字符串),而 5.7 默认插件期望的是更严格的格式,部分小版本虽能执行但后续登录必报Access denied - 没指定
host条件,比如只写WHERE user='root',可能同时匹配'root'@'localhost'、'root'@'127.0.0.1'、'root'@'%'多条,改的那条未必是你连上去用的那条 - UPDATE 后漏掉
FLUSH PRIVILEGES,内存权限缓存没刷新,新值压根不生效
user 表里根本找不到 password 字段,是删了吗
不是删了,是字段名彻底换了。MySQL 5.7 起,密码存储字段统一改为 authentication_string,password 字段已移除。你执行 DESC user 就能看到,authentication_string 是 TEXT 类型,而旧版的 password 是 CHAR(41)。
- 执行
SELECT User, Host, authentication_string, plugin FROM user WHERE User = 'root';,能清楚看到当前 root 账户实际用的认证插件和密码哈希值 - 如果
plugin为空或为auth_socket(常见于 Ubuntu 包安装),即使authentication_string改对了,登录也会被插件绕过或拒绝 - 必须同步更新
plugin字段:例如UPDATE user SET plugin = 'mysql_native_password' WHERE User = 'root' AND Host = 'localhost';
为什么 ALTER USER 能成功,UPDATE 却不行
ALTER USER 是 MySQL 官方在 5.7.6+ 明确推荐的密码修改方式,它内部自动处理三件事:调用正确的哈希函数、适配当前认证插件、隐式触发权限重载。而 UPDATE 是裸操作,全靠你自己对齐所有细节。
-
ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass';—— 简洁安全,无需关心authentication_string格式或plugin值 - 如果账户被标记为过期(常见于初始安装或强制改密后),
ALTER USER会直接报错ERROR 1820 (HY000),此时得先加PASSWORD EXPIRE NEVER或用SET PASSWORD过渡 -
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');在 5.7 中仍可用,但前提是CURRENT_USER()返回的正是该账户,且没开--super-read-only
skip-grant-tables 启动后 UPDATE 还是不生效的常见卡点
跳过权限表只是让你能连进去,不代表所有 SQL 都能绕过校验逻辑。很多“改完登不上”其实是启动态配置没对齐。
-
skip-grant-tables必须放在[mysqld]段下,若误贴到[client]或文件末尾,MySQL 完全忽略,服务照常校验密码 - 同时配置了
skip-networking,会导致本地 socket 连接也被禁,此时mysql -u root会失败,得显式指定 socket:mysql -S /var/lib/mysql/mysql.sock -u root - 改完后忘记重启服务(或没真正 reload 配置),或者改完没删/注释掉
skip-grant-tables就重启,服务会以无权限模式持续运行,外部连接全被拒
PASSWORD() 或 ALTER USER 执行时若新密码太短或太简单,语句看似成功,但实际没写入——查 authentication_string 仍是空或旧值,且不会报错。必须先看 SHOW VARIABLES LIKE 'validate_password%';,再决定是否临时调低策略。











