远程连接mysql需同时满足三件事:正确配置用户权限(create user+grant+flush privileges)、将bind-address设为0.0.0.0或指定ip、放行系统防火墙及云安全组的3306端口。

直接结论:不能只改 GRANT,必须同时满足三件事
只执行 GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'pwd' 是不够的。远程连接失败,90% 情况下是卡在这三个环节中的某一个:MySQL 用户权限配置、bind-address 监听设置、系统防火墙放行。缺一不可。
CREATE USER 和 GRANT 必须配对使用,且主机名不能写错
MySQL 的用户身份由 'username'@'host' 共同决定,'user'@'%' 和 'user'@'localhost' 是两个完全不同的账户。
- 不要用
UPDATE mysql.user SET Host='%' WHERE User='root'这种“改表法”——它绕过权限校验逻辑,在 MySQL 8.0+ 中可能被忽略或引发不一致 - 正确做法是显式创建远程用户:
CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPass!2026'; - 再授予权限:
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'app_user'@'%';(别盲目用ALL PRIVILEGES) - 最后必须执行:
FLUSH PRIVILEGES;—— 否则刚建的用户根本不会出现在权限缓存里 - 如果要用 root 远程,也得走同样流程:
CREATE USER 'root'@'%' IDENTIFIED BY 'xxx'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;,而不是试图“修改已有 localhost root”
bind-address 必须设为 0.0.0.0 或具体 IP,不能是 127.0.0.1
MySQL 默认配置(尤其在 Debian/Ubuntu 包安装时)常把 bind-address = 127.0.0.1 写死在 /etc/mysql/mysql.conf.d/mysqld.cnf 或 /etc/my.cnf 里。这意味着它只监听本地回环,外部 TCP 连接直接被拒,连错误都不报(表现为 timeout)。
- 编辑配置文件,找到
[mysqld]段落,把bind-address改成:bind-address = 0.0.0.0(监听所有网卡)或bind-address = 192.168.1.100(仅监听某内网 IP) - 改完必须重启服务:
sudo systemctl restart mysql(Linux)或net stop mysql && net start mysql(Windows) - 验证是否生效:
sudo ss -tlnp | grep :3306,输出中应看到*:3306或192.168.1.100:3306,而不是127.0.0.1:3306
防火墙和云服务商安全组才是最常被忽略的一环
即使 MySQL 本身已监听 0.0.0.0:3306,如果服务器防火墙或云平台(阿里云/腾讯云/AWS)的安全组没放行 3306 端口,客户端依然连不上——而且通常报错是 ERROR 2003 (HY000): Can't connect to MySQL server,容易误判为 MySQL 配置问题。
- Linux(firewalld):
sudo firewall-cmd --permanent --add-port=3306/tcp+sudo firewall-cmd --reload - Linux(iptables):
sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT,并保存规则 - 云服务器:登录控制台,找到“安全组”,添加入方向规则,协议 TCP,端口 3306,源 IP 可设为
0.0.0.0/0(测试用)或限定具体 IP 段 - Windows:打开“高级安全 Windows 防火墙”,新建入站规则 → 端口 → TCP 3306 → 允许连接 → 配置作用域(建议限制 IP 范围)
真正上线前,% 和 0.0.0.0 这两个通配符必须收缩——要么限定远程 IP 段,要么用跳板机/NAT 网关隔离,否则等于把数据库裸奔在公网。











