mysql迁移后远程访问受限,根本原因是mysql.user表中用户host字段不匹配新环境客户端ip,需用create/alter user修改host为'%'或具体ip,再grant授权并执行flush privileges;同时确认bind-address=0.0.0.0、3306端口开放且安全组放行。

云迁移后权限受限,90%不是密码错了,而是 mysql.user 表里那条记录的 Host 字段不匹配新环境的真实来源 IP —— 你连的是公网 IP,用户却只允许 'localhost' 或旧内网段。
查清楚 CURRENT_USER() 和 USER() 到底是谁
登录后立刻执行:SELECT USER(), CURRENT_USER();。如果两者不一致,说明 MySQL 匹配到了一个“看似同名、实则 host 不符”的用户。比如你用 mysql -h 47.98.x.x -u app -p 连,USER() 返回 'app'@'47.98.x.x',但 CURRENT_USER() 返回 'app'@'10.0.2.5',那就证明没这条记录,MySQL 退而匹配了更宽泛或更旧的一条。
- 接着查所有匹配项:
SELECT Host, User FROM mysql.user WHERE User = 'app'; - 特别注意:
localhost只走 Unix socket,127.0.0.1才走 TCP 回环;云环境基本不用localhost做远程连接 - 若返回空,说明该用户根本没被创建进新实例(常见于跳过
mysql系统库导入)
别 UPDATE mysql.user,用 CREATE/ALTER USER 重建 host
MySQL 8.0+ 禁止直接改 mysql.user 表,UPDATE 会报 ERROR 1396 (HY000),且可能损坏 authentication_string 或插件状态。
- 用户完全不存在:运行
CREATE USER 'app'@'%' IDENTIFIED WITH caching_sha2_password BY 'xxx'; - 已有本地用户想扩展:用
ALTER USER 'app'@'localhost' RENAME TO 'app'@'%';(不是UPDATE) - 只放行某云厂商 VPC 网段(更安全):
CREATE USER 'app'@'100.64.0.%' IDENTIFIED BY 'xxx'; - 必须补授权:
GRANT SELECT, INSERT ON mydb.* TO 'app'@'%'; - 最后强制刷新:
FLUSH PRIVILEGES;——这步漏掉,改了等于白改
检查 bind-address 和云平台安全组是否放行 3306
权限对了但还是连不上?大概率卡在 TCP 层。MySQL 默认 bind-address = 127.0.0.1,云实例必须显式放开:
- 确认配置文件中
bind-address = 0.0.0.0(或具体内网 IP),不是注释掉的状态 - 重启服务后,用
ss -tlnp | grep :3306看监听地址是不是*:3306 - 阿里云/腾讯云/AWS 控制台里查安全组规则:必须有入方向 3306 TCP,源 IP 设为
0.0.0.0/0(测试用)或你办公 IP 段 - 容器环境(如 Docker)还要加
-p 3306:3306并确认container_aware=ON(MySQL 9.6+ 新选项)
导入权限脚本前必须清理旧用户残留
直接 source grants.sql 几乎必失败,因为里面全是 GRANT ... TO 'user'@'host',但目标库压根没有这个用户,报错 ERROR 1133 (42000): Can't find any matching row in the user table。
- 导出时就该包含
DROP USER IF EXISTS 'app'@'%'; CREATE USER ...;前置语句 - 若只有
SHOW GRANTS输出,先手动补上CREATE USER,注意指定IDENTIFIED WITH caching_sha2_password(8.0+ 默认) - 过滤掉无效语句:
grep -v "USAGE" grants.sql > clean_grants.sql - 导入前删空旧用户:
DROP USER IF EXISTS 'app'@'%'; DROP USER IF EXISTS 'app'@'localhost';
最常被忽略的点是:你以为改了 /etc/my.cnf,但云平台(比如宝塔、阿里云 RDS 自定义参数)实际加载的是 /www/server/mysql/my.cnf 或环境变量指定路径;务必用 mysqld --verbose --help | grep "Default options" 确认真实生效配置位置。











