ERROR 1045 根本原因非密码错误而是权限/插件/用户匹配失败;需先根据 using password: YES/NO 判断,再检查匿名用户、host 匹配、socket/TCP 差异及认证插件兼容性。

ERROR 1045:密码错还是权限锁?先分清根本原因
看到 Access denied for user 'root'@'localhost' (using password: YES),别急着重置密码——90% 的情况不是密码真错了,而是 MySQL 拒绝了你的登录请求。关键要看报错里 using password: YES 还是 NO:YES 表示你输对了密码格式、但权限/插件/用户匹配失败;NO 才大概率是密码根本没传或为空。
- 检查是否误用了匿名用户(
user为空):执行mysql -u "" -h localhost,如果能进,说明存在空用户名用户,它会优先匹配,挤掉root@localhost - 确认你连的是本地 socket 还是 TCP:macOS/Linux 下
mysql -u root -p默认走 socket;加-h 127.0.0.1强制走 TCP,这时匹配的是root@'127.0.0.1',而非root@'localhost',两者权限可能不同 - MySQL 8.0+ 默认用
caching_sha2_password插件,老客户端不兼容,会静默拒绝——用SHOW CREATE USER 'root'@'localhost';查看IDENTIFIED WITH后的插件名
跳过验证重置密码:Linux/macOS 实操要点
这是最常用也最容易翻车的一招。核心不是“跳过验证”,而是“让 mysqld 启动时不加载权限表”,所以必须确保旧服务已彻底停止,且新启动方式不被 systemd 或 launchd 拦截。
- 停止服务:
sudo systemctl stop mysql(Ubuntu/Debian)或sudo brew services stop mysql(macOS Homebrew) - 手动带参数启动:
sudo /usr/local/mysql/bin/mysqld_safe --skip-grant-tables &(路径以你实际安装为准);注意结尾的&不可省,否则终端会被占住 - 此时直接
mysql -u root即可登录(不加-p);但别急着改密码——先执行FLUSH PRIVILEGES;,否则后续ALTER USER会报错 - MySQL 8.0+ 必须用:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
;5.7 及以前用:
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('新密码');
账号异常:host 匹配冲突与插件不兼容
MySQL 认证时按 host 字段精确排序匹配,'root'@'%' 和 'root'@'localhost' 是两个完全独立的账号。如果你只给 'root'@'%' 设了密码,那从本机用 localhost 就永远登不上。
- 查所有 root 相关账号:
SELECT User, Host FROM mysql.user WHERE User = 'root';
- 若只有
'root'@'%',补一个本地账号:CREATE USER 'root'@'localhost' IDENTIFIED BY '密码'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
- 插件问题:如果客户端报错但无明确提示,试试切回传统认证:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';
-
配置文件里加
default_authentication_plugin=mysql_native_password只影响新建用户,不影响已有用户
临时密码失效?日志里找,别猜
MySQL 5.7+ 初始化后会在日志里生成临时密码,但很多人搜错路径或忽略大小写——它只出现在首次启动日志中,重启后不再输出。
- Linux 常见路径:
/var/log/mysqld.log或/var/log/mysql/error.log;macOS Homebrew 安装的通常在:/usr/local/var/mysql/*.err - 用命令快速提取:
sudo grep "temporary password" /var/log/mysqld.log
- 如果日志里找不到,说明服务已被启停多次,临时密码已失效,此时只能走
--skip-grant-tables流程 - 临时密码策略太严?登录后立刻执行:
SET GLOBAL validate_password.policy = 0; ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
真正卡住人的,往往不是哪步操作错了,而是以为自己在重置密码,其实是在跟 host 匹配规则、socket/TCP 差异、插件版本打架。动手前,先用 mysql -u root -h 127.0.0.1 -p 和 mysql -u root -S /tmp/mysql.sock -p 分别试一次,答案就出来了。
