应先确认mysql是否监听外网端口、用户凭据(用户名+密码+host)是否存在且匹配、认证插件是否兼容,再检查防火墙和安全组;三者缺一不可。

远程连接报错 Error 1045 或 “access denied for user” 怎么定位?
这不是密码输错了那么简单——MySQL 把「用户名 + 密码 + host」三者当做一个完整凭据,缺一不可。你连的是 root@localhost,但远程实际尝试的是 root@'192.168.1.100'(或 root@'%'),哪怕密码对,只要没对应记录,就直接拒绝。
- 先本地登录 MySQL,执行
select User, Host FROM mysql.user;,重点看有没有root行的Host是%或具体客户端 IP - 如果只有
localhost,说明远程凭据根本不存在,不是“权限不足”,是“压根不认你这个人” - 注意:MySQL 8.0+ 默认用
caching_sha2_password加密,老客户端(如旧版 navicat、某些 JDBC 驱动)可能不兼容,会静默失败
给 root 开远程权限,为什么 GRANT 后还是连不上?
因为只做 GRANT 不够,还必须确保三件事同时成立:用户存在、密码匹配、认证插件兼容。
- 执行
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;—— 这步只是授权,不创建用户也不设密码 - 如果
'root'@'%'还没在user表里,得补一句ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 必须跟
FLUSH PRIVILEGES;,否则权限缓存不更新(MySQL 不实时读表) - 检查是否误开了
skip-grant-tables:查/etc/my.cnf或C:my.ini,有这行就删掉并重启 mysqld
bind-address 和防火墙才是真正的“拦路虎”
就算 MySQL 用户权限全开,外面也连不进来——因为服务根本没监听外网端口,或者被系统/云平台防火墙挡了。
- 查 MySQL 实际监听地址:
sudo netstat -tlnp | grep :3306,如果只看到127.0.0.1:3306,说明bind-address = 127.0.0.1(默认值),要改成0.0.0.0或具体内网 IP - 改完配置后必须重启 MySQL:
sudo systemctl restart mysqld(linux)或服务管理器(windows) - 云服务器(阿里云、腾讯云等)额外要开安全组规则,放行 TCP 3306 端口,且源 IP 要填对(
0.0.0.0/0很危险,建议限定 IP 段)
生产环境别碰 root,用授权法建专用用户
直接开 root@'%' 是高危操作,一旦密码泄露或被爆破,整个库就裸奔了。应该按最小权限原则建新用户。
- 例如只给应用访问
app_db库:CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED WITH mysql_native_password BY 'strong_pass_2026'; - 再精确授权:
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'192.168.1.%'; - host 写成
'192.168.1.%'比'%'安全得多,既避免公网暴露,又兼容内网多台机器 - 记得
FLUSH PRIVILEGES;,然后用这个账号测试连接,而不是反复折腾 root
最容易被忽略的是:MySQL 8.0 的认证插件变更和 bind-address 配置这两层,它们不出错时一切正常,一出错就完全无日志提示,只能靠 netstat 和 SELECT User,Host FROM mysql.user 交叉验证。别急着重置密码,先确认“MySQL 有没有在听、认不认识你、敢不敢让你进”。