mysql远程连接报错“host 'xxx' is not allowed to connect”根本原因是mysql.user表中用户host字段不匹配客户端ip,需用create user/alter user创建或修改'username'@'%'用户,再grant授权并执行flush privileges;同时须开放防火墙3306端口、将bind-address设为0.0.0.0或注释掉,并重启mysql服务。

MySQL远程连接报错 Host 'xxx' is not allowed to connect to this MySQL server
这是最典型的权限拒绝提示,根本原因不是密码错、端口不通,而是当前用户在 mysql.user 表里对应的 host 字段值不匹配远程客户端的来源 IP 或主机名。
比如你用 root@localhost 登录本地没问题,但远程连时实际走的是 root@192.168.1.100 或 root@% 这条记录——而这条记录要么不存在,要么 host 值是 localhost(只允许本机),或者是个具体 IP(没覆盖你的客户端)。
- 先确认当前用户真实记录:
SELECT user, host FROM mysql.user WHERE user = 'your_username';
-
host值为localhost的账号,永远无法远程连接,哪怕加了-h 127.0.0.1 - 想通配所有地址,
host必须设为%(不是空字符串,也不是*) - 修改后必须执行
FLUSH PRIVILEGES;,否则内存权限缓存不更新
执行 UPDATE mysql.user SET host='%' WHERE user='root' AND host='localhost' 安全吗?
不安全,而且大概率失败——MySQL 8.0+ 默认禁用直接改 mysql.user 表,会报错 The MySQL server is running with the --skip-grant-tables option 或更常见的 ERROR 1396 (HY000): Operation ALTER USER failed。
正确做法是用 CREATE USER 或 ALTER USER,它们会自动处理底层表和加密逻辑:
- 如果用户还不存在远程版本:
CREATE USER 'root'@'%' IDENTIFIED BY 'your_password';
- 如果已存在但
host不对:ALTER USER 'root'@'localhost' RENAME TO 'root'@'%';
- 别漏掉授权:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
- 再次强调:
FLUSH PRIVILEGES;不是可选步骤,是必须
改完还是连不上:检查防火墙和 bind-address
MySQL 层权限开了,只是第一步。远程连不上还有两个高频拦路虎:
- Linux 防火墙拦了
3306端口:sudo ufw allow 3306
(Ubuntu)或sudo firewall-cmd --add-port=3306/tcp --permanent
(CentOS) - MySQL 配置强制绑定了
127.0.0.1:bind-address在/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/my.cnf里,必须改成0.0.0.0或注释掉该行 - 改完配置要重启服务:
sudo systemctl restart mysql
(不是reload,restart 才生效) - 验证监听状态:
sudo netstat -tlnp | grep :3306
,看到*:3306才算真正对外放开
为什么不用 GRANT ... ON *.* TO 'user'@'%' 就报错?
因为 GRANT 语句在用户不存在时不会自动创建它(MySQL 5.7 默认行为),只会报错 ERROR 1396 (HY000): Operation GRANT failed。
所以顺序不能错:
- 先确保用户存在且
host正确(用CREATE USER或ALTER USER) - 再
GRANT权限 - 最后
FLUSH PRIVILEGES - 如果用旧版脚本习惯写
INSERT INTO mysql.user,现在基本会失败——MySQL 8.0+ 的authentication_string字段加密方式变了,手动插容易导致密码失效
真正麻烦的从来不是改个 %,而是改完发现没 flush、没开防火墙、没调 bind-address、用户根本不存在——四个点卡住一个,远程就死在半路。











