mysql连接失败分四类:服务未启动或bind_address配置错误致connection refused;用户权限三元组不匹配或密码过期引发access denied;网络链路不通或安全组未放行3306端口导致超时;mysql 8.0+默认强制ssl引发ssl connection error。

MySQL 连接失败不是单一原因,而是四类问题叠加的结果:服务没起来、权限不匹配、网络不通、认证机制不兼容。直接看日志里的错误码,比猜更省时间。
Connection refused(错误码 2003)
这是最常被误判为“网络问题”的错误,实际八成是 MySQL 自身没监听正确地址。
- 先确认 mysqld 进程是否真在运行:
systemctl status mysql(Ubuntu/Debian)或systemctl status mysqld(CentOS/RHEL),状态不是active (running)就别往下查了 - 检查
bind_address配置:默认值常是127.0.0.1或localhost,这会让 MySQL 拒绝所有远程 TCP 连接;需改成0.0.0.0或具体网卡 IP,并重启服务 - 用
ss -tlnp | grep :3306确认监听地址是否生效 —— 如果输出里是127.0.0.1:3306,说明改配置没生效或没重启 - 注意
skip_networking = ON会彻底禁用 TCP 连接,SHOW VARIABLES LIKE 'skip_networking';查一下
Access denied for user(错误码 1045)
这个报错只说明三元组 'user'@'host' 不匹配,不是密码错了就重设密码,得先定位到底哪个组合缺失。
-
SELECT User, Host FROM mysql.user;查当前所有授权记录,重点看你要连的用户是否出现在目标Host值下(比如用-h 192.168.1.100连,就得有'user'@'192.168.1.100'或'user'@'%') -
localhost和127.0.0.1是两个不同 host:前者走 socket 文件,后者走 TCP;用mysql -h 127.0.0.1就不会命中'root'@'localhost' - 密码过期也会触发该错误:
SELECT User, Host, password_expired FROM mysql.user;,若为Y,执行ALTER USER 'user'@'host' PASSWORD EXPIRE NEVER; - MySQL 8.0+ 默认用
caching_sha2_password插件,老客户端(如某些 JDBC 驱动、Navicat 旧版)不支持,需显式降级:ALTER USER 'user'@'host' IDENTIFIED WITH mysql_native_password BY 'password';
Can't connect to MySQL server(超时无响应)
这类错误本质是 TCP 握手卡死,MySQL 甚至没收到连接请求,排查必须跳过 MySQL 层,直击链路。
- 先做最小验证:
telnet your_mysql_ip 3306或nc -zv your_mysql_ip 3306—— 失败说明中间某处拦截,和 MySQL 无关 - 云服务器(阿里云/AWS/腾讯云)务必检查安全组规则:入方向必须放行
3306/tcp,源地址不能只写0.0.0.0/0,要按实际客户端 IP 段精确设置 - 本地防火墙也要查:
sudo ufw status(Ubuntu)、sudo firewall-cmd --list-all(CentOS),确认3306在允许列表里 - 虚拟机场景(如 VirtualBox)额外检查端口转发:宿主机访问的 IP:Port 是否正确映射到虚拟机的
3306
SSL connection error(MySQL 8.0+ 默认强制 SSL)
新装 MySQL 8.0+ 实例默认要求 SSL 连接,但多数开发工具或脚本没配证书,就会静默失败。
- 临时绕过(仅测试环境):
mysql --ssl-mode=DISABLED -u user -p -h host - 生产环境应启用 SSL 并配置客户端:生成证书后,在连接字符串中指定
--ssl-ca、--ssl-cert、--ssl-key - 或在服务端关闭强制 SSL(不推荐):
SET GLOBAL require_secure_transport = OFF;,并写入配置文件[mysqld]下的require_secure_transport = OFF - 注意:某些 ORM(如 Django)需显式设置
OPTIONS={'ssl': {'ssl_mode': 'DISABLED'}}才能生效
真正难的不是单点问题,而是多个条件同时成立:比如 bind_address = 127.0.0.1 + 'user'@'localhost' + 客户端用 -h 192.168.x.x 连 —— 表面像网络问题,实际每层都卡住。动手前,先看清楚错误信息里那个具体的错误码和括号里的数字。











