根本原因是mysql未监听外部网络接口,bind-address默认为127.0.0.1导致远程连接在系统层面被拒绝,未进入权限校验环节;需改为0.0.0.0或指定ip并重启服务。

MySQL 用户主机设置为 % 为什么还是连不上
根本原因往往不是用户权限没开,而是 MySQL 实例压根没监听外部网络接口。即使你执行了 GRANT ALL ON *.* TO 'user'@'%' 并 FLUSH PRIVILEGES,只要 bind-address 锁死在 127.0.0.1,所有远程 TCP 连接请求在系统层面就被拒绝了,压根到不了权限校验环节。
实操建议:
- 先确认当前绑定地址:
mysql -e "SHOW VARIABLES LIKE 'bind_address';" - 编辑 MySQL 配置文件(通常是
/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/my.cnf),找到bind-address行,改为:bind-address = 0.0.0.0 - 如果服务器有多个网卡,也可指定为具体内网 IP(如
192.168.1.100),不推荐直接用0.0.0.0暴露公网 - 改完必须重启服务:
sudo systemctl restart mysql(Ubuntu/Debian)或sudo systemctl restart mysqld(CentOS/RHEL)
执行 GRANT 后仍提示 Access denied for user
常见于用户主机名匹配失败——MySQL 的 @ 后面不是通配符模糊匹配,而是精确字符串比对(% 和 _ 是唯一通配符)。比如客户端从 192.168.1.50 连入,但你只建了 'user'@'192.168.1.%',这没问题;但如果建的是 'user'@'localhost',就完全不生效。
实操建议:
- 查当前用户记录:
SELECT User, Host FROM mysql.user; - 创建远程用户时,明确用
'user'@'%'或更安全的'user'@'192.168.1.%',避免依赖 DNS 反解(MySQL 默认关 DNS 解析) - 密码要显式指定,尤其 MySQL 8.0+ 默认用
caching_sha2_password插件,旧客户端可能不兼容,可加IDENTIFIED WITH mysql_native_password BY 'pwd' - 执行完
GRANT必须跟FLUSH PRIVILEGES;,否则内存权限缓存不会更新
MySQL 8.0 远程连接报 Client does not support authentication protocol
这是 MySQL 8.0 默认认证插件升级导致的典型兼容性问题。老版本客户端(如 MySQL 5.7 客户端、某些 Python mysql-connector 旧版、Navicat 旧版)不支持 caching_sha2_password,但新用户默认用它。
实操建议:
- 临时方案:改用户认证方式:
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 长期方案:升级客户端驱动,例如 Python 改用
pymysql或新版mysql-connector-python>=8.0.23 - 不建议全局降级默认插件(改
default_authentication_plugin),会影响后续新建用户
防火墙和云平台安全组是最后一道关卡
即使 MySQL 配置全对、用户权限全开,Linux 防火墙(ufw / iptables)或云厂商安全组(阿里云、腾讯云等)若没放行 3306 端口,连接照样超时或被拒绝。
实操建议:
- 检查本地防火墙:
sudo ufw status,如启用则加规则:sudo ufw allow 3306 - 云服务器务必进控制台查安全组,入方向规则需明确允许 TCP:3306,源 IP 建议限制为可信段(如
192.168.1.0/24),别写0.0.0.0/0 - 用
telnet your-server-ip 3306或nc -zv your-server-ip 3306在客户端测端口连通性,比直接连 MySQL 更快定位是网络层还是数据库层问题
bind-address、用户 Host、认证插件、防火墙——四个点漏一个,远程访问就断在半路。最容易被忽略的是第一个:很多人改完用户权限就以为万事大吉,却没意识到 MySQL 根本没对外“开门”。











