MySQL远程连接需同时满足四条件:用户host设为'%'或指定IP、bind-address改为0.0.0.0或注释、防火墙开放3306端口、MySQL 8.0+需设mysql_native_password认证插件,缺一不可。

MySQL 远程访问连不上,90% 的情况不是权限没开,而是 host 字段改错了、bind-address 没放开、或者防火墙规则压根没生效——三者缺一不可,且顺序不能乱。
MySQL 用户的 host 字段必须是 % 或具体 IP,不能是空或 localhost
执行 SELECT user, host FROM mysql.user WHERE user = 'root';,如果看到 host 是 localhost,那这个账号永远无法被远程连接,哪怕你加了 -h 127.0.0.1 也不行。
-
host = '%'表示允许任意 IPv4/IPv6 地址连接(注意:不是空字符串,也不是*) -
host = '192.168.10.%'可匹配该子网下所有 IP,但不支持 CIDR 写法(如192.168.10.0/24会报错) - MySQL 8.0+ 禁止直接
UPDATE mysql.user SET host = '%',会触发ERROR 1396 (HY000)或--skip-grant-tables报错 - 正确做法是:
CREATE USER 'root'@'%'(新用户),或ALTER USER 'root'@'localhost' RENAME TO 'root'@'%'(已有用户) - 改完必须跟
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'+FLUSH PRIVILEGES;,否则内存缓存不更新
bind-address 必须设为 0.0.0.0 或注释掉,不能留默认的 127.0.0.1
MySQL 默认只监听 127.0.0.1:3306,外部流量根本到不了 MySQL 进程,防火墙再怎么放行都白搭。
- 配置文件路径常见于:
/etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian)或/etc/my.cnf(CentOS/RHEL) - 找到
[mysqld]段下的bind-address行,改成:bind-address = 0.0.0.0,或直接删掉/注释该行 - 确认无
skip-networking = 1,否则 MySQL 主动关闭 TCP 监听 - 改完必须重启服务:
sudo systemctl restart mysql(Ubuntu)或sudo systemctl restart mysqld(CentOS) - 验证是否生效:
ss -tlnp | grep :3306,输出中应含*:3306或0.0.0.0:3306,而非127.0.0.1:3306
防火墙规则要匹配实际连接路径,ufw/firewalld/iptables 逻辑完全不同
很多用户开了 ufw allow 3306 却仍连不上,是因为没确认 MySQL 是否真在监听公网地址,或规则未持久化/未重载。
- Ubuntu 上用 ufw:
sudo ufw allow 3306(放行所有 IP),或限制来源:sudo ufw allow from 192.168.10.55 to any port 3306 - CentOS 上用 firewalld:
sudo firewall-cmd --permanent --add-port=3306/tcp,然后必须sudo firewall-cmd --reload - iptables 规则顺序敏感:放行规则必须在 DROP 规则之前,用
sudo iptables -L --line-numbers查看顺序 - 云服务器(阿里云、AWS、腾讯云)还需额外配置安全组,开放入方向 TCP 3306,仅靠系统防火墙不够
- 测试前先用
telnet your_server_ip 3306或nc -zv your_server_ip 3306确认端口可达,再排查 MySQL 权限
MySQL 8.0+ 连接失败常卡在认证插件,不是权限问题
用 Navicat、DBeaver 等工具连 MySQL 8.0+ 时出现 ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password',说明客户端不支持默认加密方式。
- 不要改客户端驱动,直接在 MySQL 里切回兼容模式:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 执行后务必再跑一遍
FLUSH PRIVILEGES; - 如果用户是新建的,创建时就指定插件:
CREATE USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 该步骤和权限、bind-address、防火墙无关,但它是远程连接成功的最后一道关卡
真正卡住人的地方,往往不是某一步做错了,而是做了 A 却忘了 B 和 C;比如改了 host 却没 FLUSH PRIVILEGES,或开了防火墙却没改 bind-address,又或者用了 MySQL 8.0+ 却没处理认证插件——四件事得全对上,远程连接才算真正通了。


















