mysql 5.7远程连接需同时满足三条件:用户授权(create user + grant + flush privileges)、服务监听(bind-address=0.0.0.0并重启)、网络放行(防火墙/selinux/云安全组),且'localhost'与'%'是完全独立账户。

MySQL 5.7 默认禁止远程连接,直接用 root 远程登录基本会失败——不是密码错,而是账户没授权、服务没监听、防火墙拦了,三者缺一不可。
CREATE USER 和 GRANT 必须配对执行
只运行 CREATE USER 不赋予权限,用户连登录都进不去;只 GRANT 不先建用户,在 MySQL 5.7 中会报错 ERROR 1133 (42000): Can't find any matching row in the user table。
-
CREATE USER 'appuser'@'%' IDENTIFIED BY 'StrongPass123!';——@'%'表示任意 IP,但不包含localhost -
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'appuser'@'%';—— 按最小权限原则,别一上来就ALL PRIVILEGES -
FLUSH PRIVILEGES;必须执行,否则权限不生效(MySQL 5.7 不自动重载)
bind-address=0.0.0.0 不是万能解药
很多教程让你改 /etc/mysql/mysql.conf.d/mysqld.cnf 里的 bind-address,但实际路径可能在 /etc/my.cnf 或被 !includedir 下的其他配置覆盖。MySQL 5.7 启动时会合并所有 .cnf 文件,最终生效的是最后一个定义的 bind-address。
- 先查真实生效值:
mysql -uroot -p -e "SHOW VARIABLES LIKE 'bind_address';" - 如果输出是
127.0.0.1,说明配置没生效或被覆盖 - 确认修改位置:优先检查
/etc/mysql/mysql.conf.d/mysqld.cnf,找到[mysqld]段落再加bind-address = 0.0.0.0 - 改完必须重启服务:
sudo systemctl restart mysql(CentOS/Ubuntu 均适用)
防火墙和 SELinux 是隐形拦路虎
即使 MySQL 服务监听了 0.0.0.0:3306,外部机器仍连不上,大概率卡在系统层。
- 检查端口监听:
sudo ss -tlnp | grep :3306,确认LISTEN状态且 PID 是mysqld - 开放防火墙:
sudo ufw allow 3306(Ubuntu)或sudo firewall-cmd --permanent --add-port=3306/tcp && sudo firewall-cmd --reload(CentOS 7) - SELinux 若启用,需额外放行:
sudo setsebool -P mysqld_connect_any 1(否则客户端连上后立刻断开) - 云服务器还要检查安全组规则——这步常被本地测试忽略
localhost 和 % 是两个完全不同的账户
你执行 CREATE USER 'dev'@'%' 后,mysql -h127.0.0.1 -udev -p 能连,但 mysql -hlocalhost -udev -p 会提示 Access denied。因为 MySQL 把 localhost 当作 socket 连接,匹配的是 'dev'@'localhost',跟 'dev'@'%' 毫无关系。
- 本地命令行测试务必用
mysql -h127.0.0.1,而非mysql -hlocalhost - 如需支持
localhost登录,单独建账户:CREATE USER 'dev'@'localhost' IDENTIFIED BY '...'; - 生产环境建议禁用
root的@'%',哪怕只读也用专用账号
真正卡住人的从来不是 SQL 语句写错,而是权限、配置、网络三层叠加验证——每层漏一个,就白调半小时。











