直接改 mysql.user 表的 host 字段极易出错,必须加 where 条件限定(如 and host='localhost')、执行 flush privileges 刷新权限,并验证监听配置;update user set host='%' where user='root' 会批量覆盖所有 root 记录,导致本地连接失效。

直接改 mysql.user 表的 host 字段是最容易出问题的操作,不是不能做,而是必须加限定条件、配刷新、再验监听。
为什么 UPDATE user SET host='%' WHERE user='root' 很危险
这条语句会把所有 root 用户记录(比如 'root'@'10.0.0.5'、'root'@'localhost')的 host 全部改成 '%',覆盖原有精细权限;更糟的是,如果存在 'root'@'::1'(IPv6 本机),它也会被一并改掉,导致本地 socket 连接失效。
正确做法是只动目标记录:
UPDATE user SET host='%' WHERE user='root' AND host='localhost';- 执行后必须跟
FLUSH PRIVILEGES;,否则内存缓存没更新,改了也白改 - 改完用
SELECT user,host FROM mysql.user WHERE user='root';确认只新增或修改了预期的一行
GRANT 比 UPDATE 更安全的场景
当你需要给新 IP 或新用户开权限时,GRANT 是首选——它自动创建账户记录,不干扰已有条目。
例如允许 app_user 从内网某台机器连接:
GRANT SELECT,INSERT ON mydb.* TO 'app_user'@'192.168.1.20' IDENTIFIED BY 'strong_pass_2026';-
FLUSH PRIVILEGES;(GRANT后部分版本可省略,但显式写上更稳) - 注意:MySQL 8.0+ 必须先
CREATE USER再GRANT,不能一步完成
改完权限还连不上?检查这三处硬性拦截
权限只是第一关,后面还有两道墙常被忽略:
-
bind-address配置:在/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/my.cnf中确认不是127.0.0.1;设为0.0.0.0或注释掉该行,然后sudo systemctl restart mysql - 防火墙:Ubuntu 用
sudo ufw allow 3306,CentOS 用sudo firewall-cmd --permanent --add-port=3306/tcp && sudo firewall-cmd --reload - 云服务器安全组:阿里云/腾讯云控制台里必须手动放行 3306 TCP 入方向,这个比本地防火墙优先级更高
验证是否真正监听外网:ss -tlnp | grep :3306 输出应含 *:3306,而非 127.0.0.1:3306。
生产环境千万别用 '%' 开放 root 远程
开发测试临时用 '%' 可以理解,但上线前必须收窄:
- 用具体 IP 替代通配符,如
'192.168.10.50'或子网段'192.168.10.%' - 避免给
root开远程,新建专用账号并限制库表级权限 - 如果必须远程管理,建议走跳板机或 SSH 隧道,而不是暴露 MySQL 端口
真正卡住人的往往不是 SQL 语句写错,而是 bind-address 没改、防火墙没开、安全组没配——三者缺一,GRANT 写得再对也连不上。











