宝塔面板MySQL远程连接失败主因是用户host为localhost、bind-address=127.0.0.1、3306端口未放行及MySQL 8+认证插件不兼容;须改host为%并执行FLUSH PRIVILEGES、bind-address设为0.0.0.0、开放四层防火墙、切换认证插件为mysql_native_password。

MySQL 用户 host 字段是 localhost,远程根本连不进来
宝塔默认创建的数据库用户,host 字段几乎全是 localhost,这意味着 MySQL 只认本机发起的连接。哪怕你从 Navicat、PHP 应用或另一台服务器发请求,服务端压根不会把包交给认证模块——直接拒绝。
实操建议:
- 进宝塔终端,执行
mysql -uroot -p,然后运行SELECT host, user FROM mysql.user WHERE user = '你的用户名';,确认结果里有没有%或对应 IP 的记录 - 如果只有
localhost,必须重建权限:CREATE USER 'myuser'@'%' IDENTIFIED BY 'mypass'; GRANT ALL ON mydb.* TO 'myuser'@'%'; FLUSH PRIVILEGES; - 已有用户不能只改
GRANT,得先删旧的:DROP USER 'myuser'@'localhost';,再建@'%'版本 - 生产环境别用
@'%',换成具体 IP 段更稳妥,比如@'192.168.10.%'
bind-address 还是 127.0.0.1,请求根本进不了 MySQL 进程
即使用户权限全开了,bind-address = 127.0.0.1 会让 MySQL 主动丢弃所有非本地来的 TCP 包。这不是权限问题,是网络层拦截,telnet your-ip 3306 会直接超时或报 No route to host。
实操建议:
- 编辑配置文件:
/www/server/mysql/etc/my.cnf(宝塔固定路径) - 找到
bind-address行,改成bind-address = 0.0.0.0,或直接注释掉整行 - 顺手检查
skip-networking是否被注释(前面带#),没注释就加上 - 改完必须重启:
systemctl restart mysqld(CentOS)或systemctl restart mysql(Ubuntu/Debian) - 重启后立刻验证:
netstat -tlnp | grep :3306输出中应含*:3306或0.0.0.0:3306,不是127.0.0.1:3306
3306 端口在四层防火墙里被拦了三道
云服务器上,3306 要过四关:云平台安全组 → 系统防火墙(firewalld/ufw)→ 宝塔自带防火墙 → MySQL 自身监听配置。少开任意一层,连接就断在半路。
实操建议:
- 阿里云/腾讯云控制台 → 安全组 → 添加入方向规则:协议 TCP,端口范围
3306/3306,授权对象填宝塔服务器公网 IP(别填127.0.0.1) - 查系统防火墙状态:
sudo firewall-cmd --state(CentOS)或sudo ufw status(Ubuntu),若启用则放行:sudo firewall-cmd --permanent --add-port=3306/tcp && sudo firewall-cmd --reload - 宝塔面板 → 安全 → 放行端口 → 添加
3306(TCP 协议) - 验证是否真通:
telnet your-remote-db-ip 3306或nc -zv your-remote-db-ip 3306;连不上就别调代码,先回退查防火墙
MySQL 8+ 默认认证插件导致客户端握手失败
MySQL 8.0+ 默认用 caching_sha2_password,但旧版 PHP、某些 Navicat 版本、甚至部分宝塔插件只支持 mysql_native_password,会报错:Client does not support authentication protocol requested by server。
实操建议:
- 确认用户当前插件:
SELECT user, host, plugin FROM mysql.user WHERE user = 'myuser'; - 强制切换认证方式:
ALTER USER 'myuser'@'%' IDENTIFIED WITH mysql_native_password BY 'mypass'; - 执行完仍需
FLUSH PRIVILEGES; - 该操作不影响安全性,只是兼容性补救;新项目建议升级客户端而非降级认证插件
真正卡住人的地方,往往不是某一步没做,而是改了 my.cnf 忘重启 MySQL,或者开了安全组却没等 30 秒生效,又或者 FLUSH PRIVILEGES 漏敲——这些动作不落地,前面所有操作等于零。


















