90%的Access denied错误源于'user'@'host'不匹配、认证插件不兼容或未授权;需用SELECT User,Host FROM mysql.user确认账号存在,ALTER USER指定mysql_native_password插件,并GRANT显式赋权后FLUSH PRIVILEGES。

新建用户后立刻提示 Access denied,90% 不是密码输错了,而是账号没“对上号”——MySQL 把 'user'@'host' 当成一个完整身份,'test'@'localhost' 和 'test'@'127.0.0.1' 是两个完全独立的账号,哪怕密码一样也不互通。
确认你连的是哪个 'user'@'host' 组合
错误信息里写的 host 就是你必须匹配的目标。比如报错是 Access denied for user 'test'@'127.0.0.1',那你就得查 MySQL 里是否存在这一行记录,而不是只看有没有 'test'@'localhost'。
- 运行
SELECT User, Host FROM mysql.user WHERE User = 'test';,检查输出中是否有和错误信息里一模一样的Host值 - 用
mysql -u test -p能连,但mysql -h 127.0.0.1 -u test -p报错 → 说明只有'test'@'localhost',缺'test'@'127.0.0.1' -
SELECT USER(), CURRENT_USER();对比:前者是你声称的身份,后者才是 MySQL 实际认证通过、并用来查权限的真实账号
MySQL 5.7+ 必须显式指定认证插件
从 5.7 开始,默认插件是 caching_sha2_password,但很多客户端(老版 PHP、Python 的 MySQLdb、某些 Docker 镜像、旧版 Navicat)只认 mysql_native_password。密码正确、账号存在,握手仍会失败,表现就是 Access denied。
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
- 查当前插件:
SELECT plugin FROM mysql.user WHERE User = 'test' AND Host = 'localhost'; - 如果不是
mysql_native_password,强制改掉:ALTER USER 'test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 改完必须执行
FLUSH PRIVILEGES;,否则不生效 - 别用
UPDATE mysql.user SET authentication_string = ...—— 字段已废弃,且不会触发权限重载
新建用户没授权,等于白建
CREATE USER 只创建账号,不赋予任何权限。连上 MySQL 实例后,访问数据库、建表、查数据等操作都会被拦在第二道门——权限校验层。
- 执行
SHOW GRANTS FOR 'test'@'localhost';,如果只返回GRANT USAGE ON *.* TO 'test'@'localhost',说明啥权限都没有 - 至少要给库级权限,例如:
GRANT SELECT, INSERT ON mydb.* TO 'test'@'localhost'; - 如果是本地开发测试,常用:
GRANT ALL PRIVILEGES ON mydb.* TO 'test'@'localhost'; - 改完权限后,仍需
FLUSH PRIVILEGES;
最常被忽略的一点:CURRENT_USER() 返回的账号,才是 MySQL 真正用来查权限的依据;而你命令行里写的 -u 和 -h,只是“申报材料”。两者不一致时,报错永远指向后者,但问题根源往往藏在前者对应的那条权限记录里。

















