mysql远程连接报“access denied”是因'user'@'host'组合不匹配,未走到密码校验阶段;需确认mysql.user表中存在对应客户端ip的记录,如'root'@'192.168.10.%',并确保bind-address配置正确、防火墙放行3306端口。

这个问题不是网络不通,也不是密码错了,而是 MySQL 在认证阶段就拒绝了连接请求——它压根没走到校验密码那步。
查 user@host 记录是否匹配客户端来源
MySQL 把 user@host 当作独立账户。你远程连时用的是 root@192.168.10.5 或 root@win-1b3uv78sfn3,但 mysql.user 表里可能只有 root@localhost 这一条记录。
先登录本地 MySQL,执行:
SELECT user, host FROM mysql.user WHERE user = 'root';
如果结果里没有 host 值能覆盖你的客户端 IP 或主机名,就必然报错。注意:
-
'%'匹配任意非 localhost 的 IPv4/IPv6 地址(不含localhost、127.0.0.1) -
'192.168.10.%'只匹配该 C 类网段,比'%'安全 - 空字符串或
'*'不合法,不会生效
用 GRANT 创建新授权,别直接 UPDATE user 表
MySQL 8.0+ 默认禁用直接改 mysql.user 表,UPDATE user SET host='%' WHERE user='root' 很可能报错 ERROR 1396 或被 silently 忽略。
正确做法是走标准授权流程:
- 创建新用户:
CREATE USER 'root'@'192.168.10.%' IDENTIFIED BY 'strong_password'; - 赋予权限:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.10.%' WITH GRANT OPTION; - 立即生效:
FLUSH PRIVILEGES;
这样会自动在底层表写入新记录,且兼容 caching_sha2_password 插件。如果已有 'root'@'%' 但密码不对,用 ALTER USER 'root'@'%' IDENTIFIED BY 'new_pass'; 更安全。
bind-address 和防火墙是两道独立关卡
即使权限开了,MySQL 自身不监听外部地址,或者系统/云平台拦了端口,照样连不上。
检查监听状态:
sudo ss -tlnp | grep :3306
如果只看到 127.0.0.1:3306,说明 MySQL 没对外暴露。编辑配置文件(如 /etc/mysql/mysql.conf.d/mysqld.cnf),在 [mysqld] 段下确认:
-
bind-address是0.0.0.0(监听所有 IPv4)或具体内网 IP,不是127.0.0.1 - 删掉或注释掉
skip-networking(如果存在)
改完必须重启服务:sudo systemctl restart mysql。再验证端口可达性:
telnet your_mysql_ip 3306
超时或拒绝连接?那就不是数据库问题,是防火墙或云安全组没开 3306。
最容易被忽略的点是:MySQL 报错 Host 'xxx' is not allowed 时,它已经完成了 TCP 握手,也发出了初始握手包——这意味着网络层是通的,问题一定出在权限匹配或服务绑定上,而不是去反复 ping 或查 DNS。











