“Access denied”不是密码错误,而是MySQL未校验密码即拒绝连接,根本原因是'user'@'host'组合不匹配,需严格比对错误信息中的具体组合与mysql.user表记录,注意localhost与127.0.0.1不等价、通配符不匹配IPv6、bind-address限制及认证插件兼容性。

不是密码错了,是 MySQL 根本没走到校验密码那步——它直接拒绝了 'user'@'host' 这个组合的连接请求。
查清楚你连的到底是哪个 'user'@'host'
错误信息里写的 'root'@'192.168.1.100' 或 'app'@'localhost' 就是 MySQL 实际比对的目标,不是“你以为的”。
-
localhost和127.0.0.1完全不同:前者走 Unix socket,后者走 TCP;只存在'root'@'localhost',就无法用mysql -h 127.0.0.1 -u root登录 -
'user'@'%'能匹配 IPv4,但不匹配 IPv6 的::1;'user'@'192.168.1.%'也不会匹配10.0.0.5 - 执行
SELECT User, Host FROM mysql.user;,逐行比对输出是否和你连接命令中声明的 user + host 字符串完全一致(注意大小写、空格、点号)
GRANT 之后权限没生效?先看是不是绕过了权限系统
很多操作看似成功,其实权限根本没加载进内存。
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
- 直接
UPDATE mysql.user SET Host = '%'后,必须手动执行FLUSH PRIVILEGES; - 用
ALTER USER ... IDENTIFIED WITH mysql_native_password切换认证插件后,同样要FLUSH PRIVILEGES; - 验证是否真生效:
SHOW GRANTS FOR 'dev'@'%';—— 如果返回空,说明这个账号压根没被 MySQL 认出来 - 新建用户时用
CREATE USER+GRANT是自动生效的,不需要FLUSH;但直接改表或改插件就必须刷
端口通了,还是 Access denied?检查 bind_address 和 require_secure_transport
哪怕用户、密码、host 全对,只要下面任一条件成立,MySQL 就会静默拒绝,而不是报 Connection refused。
-
bind_address = 127.0.0.1没改 → 远程 TCP 请求被内核丢弃,MySQL 压根不参与鉴权 -
require_secure_transport = ON开启时,非 SSL 连接会被拒绝,客户端可能只显示超时或模糊错误 - 云服务器安全组未放行 3306 入方向 → 请求到不了 mysqld 进程,自然不会触发用户校验
- 验证监听状态:
ss -tlnp | grep :3306,输出中必须含*:3306或具体外网 IP,不能只有127.0.0.1:3306
老客户端连不上 MySQL 8.0+?大概率是 caching_sha2_password 插件不兼容
Navicat、旧版 PHP、某些 Docker 镜像默认不支持 MySQL 8.0+ 的默认认证方式,握手失败就表现为 Access denied,和密码无关。
- 查当前插件:
SELECT host, user, plugin FROM mysql.user WHERE user = 'root'; - 临时切回兼容插件:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_pwd'; - 切完别忘了
FLUSH PRIVILEGES; - 注意:
'root'@'localhost'和'root'@'%'的插件可以不同,得分别改
真正容易被忽略的是 host 字段的字面精确匹配——MySQL 不做通配展开,也不自动归一化 IP 或域名。别靠猜,查表、试连、看日志(/var/log/mysql/error.log 或 journalctl -u mysql)才是唯一靠谱路径。

















