应使用grant语句而非update user表修改host字段,因后者易破坏认证逻辑;正确操作是grant all privileges on . to 'root'@'%' identified by 'strong_pwd',并确保bind-address=0.0.0.0、防火墙放行3306、plugin兼容客户端。

直接改 user 表的 host 字段风险很高
MySQL 5.7 及以后版本(尤其是 MySQL 8.0+)不推荐用 UPDATE user SET host = '%' 直接修改系统表。这种操作可能破坏用户认证逻辑,尤其在启用了 caching_sha2_password 插件时,authentication_string 和 plugin 字段不匹配会导致连接直接报错 ERROR 1045 (28000): Access denied。
更稳妥的方式是用 GRANT 语句——它会自动处理用户创建、密码加密、插件适配和权限写入,不会绕过校验流程。
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' 必须配 IDENTIFIED BY(MySQL 8.0+)
MySQL 8.0 默认禁用空密码远程登录,且 GRANT 语句中若省略 IDENTIFIED BY,会沿用旧密码哈希,但很可能与当前认证插件不兼容。常见错误现象是:命令执行成功,flush privileges 也成功,但远程连接仍提示 Access denied for user 'root'@'x.x.x.x'。
必须显式指定密码:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_strong_password' WITH GRANT OPTION;
- 密码必须满足 MySQL 8.0 的密码策略(默认 require at least 8 chars, 1 upper, 1 lower, 1 digit, 1 special)
- 如果原 root 密码是空或弱密码,先用
ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass';更新本地密码再授权 -
WITH GRANT OPTION不是必需项,仅当你需要该用户能再授予权限时才加
FLUSH PRIVILEGES 在 GRANT 后其实多数情况不需要
GRANT 语句本身就会立即写入权限系统并加载到内存,FLUSH PRIVILEGES 主要用于直接修改 mysql.user 表后强制重载缓存。滥用它反而可能触发权限缓存异常,尤其在高并发环境下。
正确顺序只有两步:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_strong_password';<br>FLUSH PRIVILEGES; <!-- 仅当上面 GRANT 报错或你真改了 user 表才需要 -->
验证是否生效,直接查:
SELECT Host, User, plugin FROM mysql.user WHERE User = 'root';
看到 '%' | 'root' | 'caching_sha2_password'(或 mysql_native_password)才算真正就位。
别忘了 bind-address 和防火墙这两道关卡
即使 MySQL 用户权限全开,如果配置文件里 bind-address = 127.0.0.1(默认值),mysqld 就只监听本地回环,外部请求根本进不来。必须改成:
bind-address = 0.0.0.0
或指定服务器真实 IP(如 192.168.1.100),改完重启服务:systemctl restart mysqld。
Linux 防火墙也要放行 3306:
- CentOS/RHEL:
firewall-cmd --permanent --add-port=3306/tcp && firewall-cmd --reload - Ubuntu:
ufw allow 3306 - 云服务器(阿里云/腾讯云):安全组必须额外放通 3306 入方向
最容易被忽略的是:MySQL 8.0+ 的 plugin 字段和客户端驱动兼容性。Navicat、DBeaver 等工具若连不上,优先检查是否提示 Authentication plugin 'caching_sha2_password' cannot be loaded——这时得在 GRANT 时显式指定插件:IDENTIFIED WITH mysql_native_password BY 'xxx'。











