答案是需用sudo mysql进入后执行alter user 'root'@'localhost' identified with mysql_native_password by '新密码'切换认证插件。ubuntu/debian默认将root@localhost设为auth_socket插件,不验证密码而依赖系统用户身份,导致mysql -u root -p报access denied;必须显式指定@'localhost'并用alter user修改,不可update表。

这个问题绝大多数情况下不是密码错了,而是 MySQL 根本没走密码验证流程——root@'localhost' 的认证插件被设成了 auth_socket 或 caching_sha2_password,而你用的客户端不支持。
检查 root@localhost 的 plugin 值是否为 auth_socket
Ubuntu/Debian 默认安装的 MySQL 5.7+ 会把 root@'localhost' 的 plugin 设为 auth_socket。它不认密码,只认系统用户身份,所以输对密码也报 Access denied。
先用系统权限连进去:
sudo mysql -u root
再查认证方式:
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
- 如果看到
plugin = 'auth_socket',就是它在作怪 - 别直接
UPDATE mysql.user SET plugin = 'mysql_native_password'—— MySQL 5.7.6+ 和 8.0 会拒绝这种写法,甚至让账号不可用 - 必须用
ALTER USER:执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的新密码'; - 注意必须显式写
'root'@'localhost',漏掉@'localhost'就会匹配到@'%',改错账号
确认 mysql.user 表里有没有 'root'@'localhost' 这一行
有些重置操作只改了 'root'@'127.0.0.1' 或 'root'@'%',但没补 'root'@'localhost'。而 mysql -u root -p 默认走 Unix socket,只匹配 localhost 这个 host。
连进 MySQL 后执行:
SELECT host, user FROM mysql.user WHERE user = 'root';
- 结果里没有
localhost?那就得手动创建:CREATE USER 'root'@'localhost' IDENTIFIED BY '密码'; - 再授权:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; - 最后
FLUSH PRIVILEGES;(MySQL 5.7.6+ 改认证插件不用这步,但新建用户必须) - 别用
INSERT INTO mysql.user直接写表——字段缺失或加密逻辑不对会导致账号异常
MySQL 8.0+ 用户遇到 caching_sha2_password 不兼容
MySQL 8.0 默认用 caching_sha2_password 插件,但老版本命令行、某些 Python 驱动(如旧版 PyMySQL)、Navicat 低版本默认不支持,连接时直接拒绝,哪怕密码正确。
查当前插件:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'root';
- 如果是
caching_sha2_password,且你不想升级客户端,就切回兼容模式:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码'; - 或者在客户端连接时加参数:
mysql -u root -p --default-auth=mysql_native_password - MySQL Workbench 要在连接设置里勾选 “Use Legacy Authentication Method”
- Python 里用
mysql-connector-python时需显式指定auth_plugin='mysql_native_password'
别忽略 socket 文件权限和 localhost 解析问题
mysql -u root -p 默认走 Unix socket(路径通常是 /var/run/mysqld/mysqld.sock),不是 TCP。如果这个文件权限不对,普通用户打不开,就会卡住或报 Can't connect to local MySQL server。
- 检查 socket 文件是否存在且可读:
ls -l /var/run/mysqld/mysqld.sock(路径可能因安装方式不同而异) - 若权限是
srw-rw---- 1 mysql mysql,普通用户确实进不去;临时修复:sudo chmod 777 /var/run/mysqld/mysqld.sock(仅调试用) - 测试是否真走 socket:
mysql -u root -p -S /var/run/mysqld/mysqld.sock - 强制走 TCP 测试:
mysql -u root -p -h 127.0.0.1,能进说明是 socket 层问题,不是认证问题
真正容易被忽略的是:localhost 和 127.0.0.1 在 MySQL 权限体系里是两个完全独立的账号,不能互相替代;而客户端行为又取决于你传的 -h 参数和底层协议选择——这点在排查时必须拆开验证,不能靠猜。











