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

“Access denied”不是密码错了,而是 MySQL 根本没走到校验密码那步——它明确拒绝了 'user'@'host' 这个组合的连接请求。
确认你连的是哪个 'user'@'host' 组合
错误信息里写的 'root'@'192.168.1.100' 或 'app'@'localhost' 就是关键。MySQL 把它们当完全不同的账号处理:
-
'localhost'和'127.0.0.1'不等价:前者走 Unix socket,后者走 TCP;mysql -h 127.0.0.1 -u root需要单独存在'root'@'127.0.0.1' -
'user'@'%'能匹配 IPv4,但不匹配 IPv6 地址(如::1);'user'@'192.168.1.%'不会匹配10.0.0.5 - 执行
SELECT User, Host FROM mysql.user;,逐行比对输出是否和你连接时的User+Host完全一致
权限改了但没生效?查 FLUSH PRIVILEGES 和认证插件
用 GRANT 创建用户通常自动生效,但以下操作后必须手动刷新:
- 直接
UPDATE mysql.user SET Host='%' WHERE User='dev';→ 必须跟FLUSH PRIVILEGES; - 用
ALTER USER ... IDENTIFIED WITH mysql_native_password切换插件 → 也需FLUSH PRIVILEGES; - 验证是否生效:
SHOW GRANTS FOR 'dev'@'%';,如果返回空,说明权限根本没加载 - MySQL 8.0+ 默认用
caching_sha2_password,老版 PHP/Navicat 可能握手失败,临时切回:ALTER USER 'dev'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
端口通了,但还是 Access denied?检查 bind_address 和 require_secure_transport
哪怕用户、权限、防火墙全对,只要下面任一条件成立,最终仍报 Access denied(而非 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
真正容易被忽略的是 Host 字符串的**字面精确匹配**——MySQL 不做通配展开,也不自动归一化 IP 或域名。别靠猜,查表、试连、看日志(/var/log/mysql/error.log 或 journalctl -u mysqld -n 30),否则你会反复在“明明授权了却连不上”的循环里卡住。


















