遇到“Mysql8 连接失败”这个报错八成是刚从5.7或5.6升上来或者新装8.0之后老客户端突然连不上了。这两天后台也收到好几个朋友问装完了连本地都进不去用Navicat连直接弹错误看日志又没什么明显问题。其实MySQL 8和旧版本在连接层面最大的差异就是默认认证插件换掉了再加上服务、端口、权限这些老生常谈的环节很多人一上来就被“Access denied”和“Authentication plugin”这两类报错搞懵了。这篇文章就把我排查Mysql8连接失败的完整思路、常用命令、踩过的坑一次说清楚从认证插件到防火墙、从服务状态到连接串写法都会覆盖适合刚从5.7迁移过来的老用户也适合刚装好8.0准备上手的初学者。1. 内容整体设计与思路拆解1.1 连接失败这件事先分清是哪一层出的问题排查Mysql8连接失败最忌讳的就是东戳一下西戳一下。我个人的习惯是先把“连不上”这句话拆成三个层次第一层是网络层能不能到第二层是MySQL服务本身有没有在监听第三层才是认证和权限问题。举个例子你本地跑了一个mysql -uroot -p敲完密码直接报ERROR 1045 (28000): Access denied for user这和远程用Navicat报Cant connect to MySQL server on x.x.x.x (10060)完全是两个性质的问题。前者说明TCP连接已经建立MySQL也回复了只是用户名密码或权限不对后者根本还没到MySQL那一层服务可能压根没启动或者防火墙把3306挡掉了。所以我在做任何操作之前一定会先确认客户端有没有真正触达服务端。telnet ip 3306通不通ping通不通本机mysql -u root -p能不能进这三条命令可以快速帮你锁定故障层。大部分Mysql8连接失败之所以排查很久就是因为没先分清楚是连不上还是不能认证的问题。1.2 为什么MySQL 8一上来就搞出这么多连接问题MySQL 8.0发布时把默认认证插件从mysql_native_password换成了caching_sha2_password这是所有连接问题的最大根源。老版本客户端比如PHP 5.x的mysql扩展、比较老版本的JDBC驱动、旧版Navicat一开始根本不认识这个新插件连接的时候要么直接报Authentication plugin caching_sha2_password cannot be loaded要么就是密码明明正确却一直Authentication failed。另外8.0还移除了mysql_query这种老接口密码加密方式也变了很多老程序升级后直接就地报废。我自己就遇到过用Python的PyMySQL老版本连8.0报错信息非常隐晦一度怀疑是网络问题后来看了眼驱动版本才反应过来。还有一类情况属于安装时留下的坑用免安装版也就是zip解压包方式装MySQL的人特别容易踩。环境变量没配好、my.ini文件没写对、初始化时data目录没生成结果服务起不来连接自然是失败的。这类问题从连接报错层面完全看不出来只能回头查服务状态和错误日志。2. 核心细节解析与实操要点2.1 认证插件导致连接失败的三种解法先明确一个核心概念MySQL客户端和服务器建立连接时服务端会告诉客户端当前用户用的认证插件是什么然后双方按这个插件的规则完成密码校验。如果客户端不支持这个插件那不管你密码输多对连接都会失败。caching_sha2_password相比老的mysql_native_password安全性更高但也因此牺牲了老客户端的兼容性。遇到这种情况解决思路大致有三条把用户的认证插件改回mysql_native_password这是最快的方式但安全性会降一档适合内网或测试环境。升级客户端驱动版本比如JDBC换成mysql-connector-java 8.0.x以上PyMySQL升到0.9.3以上Navicat升级到16以上版本基本都能兼容新插件。修改MySQL服务端的默认认证插件让新建用户默认走mysql_native_password一劳永逸但同样牺牲部分安全性。我实际处理过一家公司的内网系统他们的Java服务用的是老版本Druid连接池搭配老驱动怎么升级都不愿意动代码。最后我直接在MySQL端把应用账号的插件改掉五分钟解决战斗。如果完全由你掌控客户端环境我更推荐升级驱动毕竟安全这东西能多留一点是一点。2.2 修改认证插件的常用SQL和参数说明把某个用户改成老插件一句SQL就够了ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;root和localhost按实际情况替换localhost可以换成%或其他主机名。改完不需要重启服务但建议执行一下FLUSH PRIVILEGES;让权限立即生效。如果想全局改默认让以后新建的用户都走老插件需要修改配置文件。Linux下通常是/etc/my.cnfWindows下是安装目录的my.ini在[mysqld]段下加一行default-authentication-pluginmysql_native_password改完必须重启MySQL服务。这里有个坑提醒一下这个参数在8.0的某些小版本里改名成了authentication_policy可以同时指定caching_sha2_password和mysql_native_password两个插件的策略写法比旧参数复杂。如果是8.0.27以上的版本建议直接查文档确认当前版本支持哪种写法别照抄老配置导致启动失败。2.3 免安装版的连接失败和初始化问题mysql8免安装版这种zip包很多人图省事直接解压就运行mysqld结果服务起不来或者起来了怎么都连不上。问题基本出在三个环节第一是初始化。8.0版本的免安装版解压后必须手动执行初始化命令生成data目录和数据字典mysqld --initialize-insecure注意--initialize-insecure会生成一个root空密码账号适合刚装好马上登录再用ALTER USER设置密码。如果你用--initialize那root会生成一个临时密码在错误日志里需要你自己去日志文件里翻很多人不知道这点一直用自己猜的密码去连当然失败。第二是配置文件。免安装版默认没有任何配置需要自己建my.ini至少要把basedir和datadir写对。datadir如果指到了一个不存在的目录服务起不来连接自然失败。第三是环境变量。mysql命令能运行不代表服务端在跑很多人把MySQL的bin目录加入PATH之后执行mysql -u root -p报Cant connect through socket就以为问题在MySQL这边其实socket文件还没生成先确认服务到底有没有起来。3. 实操过程与核心环节实现3.1 从零开始定位服务端状态不管是自己装的还是公司服务器上的MySQL连接失败第一步永远不是改密码而是确认服务活没活着。Linux下直接看进程和端口ps -ef | grep mysqld netstat -tlnp | grep 3306 ss -tlnp | grep 3306如果netstat或ss的输出里看不到3306端口那问题基本在服务层要么mysqld没启动要么启动后就崩了。这时候要看错误日志通常配置里会写log_error路径没写的话默认在数据目录下文件名类似hostname.err用tail -n 50看最后一段就能发现崩溃原因比如datadir权限不对、my.ini里某个参数不合法之类。如果服务在跑但只监听127.0.0.1那就是bind-address配置问题了。这种情况远程连接必然失败本地也偶发连不上因为默认socket通信可能正常但TCP监听范围不对。你想让远程连就必须在my.ini或my.cnf里加bind-address0.0.0.0改完重启。Windows下如果服务起不来可以去“服务”里看MySQL服务的状态右键查看“启动参数”或者直接在命令行里用net start MySQL80手动启看系统返回什么错误。3.2 客户端连接报错对照表把常见的Mysql8连接失败报错整理成了一张速查表这些错误我全部亲手踩过报错信息含义优先排查方向ERROR 1045 (28000): Access denied for user...用户名或密码错误或认证插件不匹配检查密码、用户权限、认证插件ERROR 2059 (HY000): Authentication plugin caching_sha2_password cannot be loaded客户端不支持新认证插件升级驱动或改用户认证插件Cant connect to MySQL server (10060)网络不通服务未启动或防火墙拦截telnet测试端口、查服务状态、防火墙Cant connect to MySQL server (10061)服务未启动或端口未监听启动服务、检查bind-addressERROR 2003 (HY000): Cant connect to MySQL server on ip连接被拒绝可能是端口或防火墙问题netstat查监听、telnet测试ERROR 1130 (HY000): Host x.x.x.x is not allowed to connect客户端IP不被允许授权用户host为%或具体IPLost connection to MySQL server during query连接中断可能超时或网络抖动检查超时参数、网络稳定性很多人在网上搜“Mysql8连接失败”时看到的报错五花八门但本质上没有跳出这几类。你要做的就是把报错文本拆开看定位到表格里对应分类然后按分类去查。3.3 远程访问权限的完整配置过程远程连接失败还有一个高频原因是授权问题。MySQL 8里创建远程用户和授权是两条SQL不能合在一起写这点和5.7时代不太一样了得分开执行CREATE USER testuser% IDENTIFIED BY Test123456; GRANT ALL PRIVILEGES ON *.* TO testuser%; FLUSH PRIVILEGES;注意8.0的GRANT语句不能在不存在用户时自动建用户了必须先CREATE USER再GRANT这是很多人踩过的坑。另外All PRIVILEGES粒度太大生产环境一般不建议这么给按实际库表授权更稳妥。还有一点很多人创建了testuser%之后本地用mysql -u testuser -p却登录失败。原因很简单MySQL匹配用户时按host精确匹配优先于模糊匹配。如果你库里恰好还有一个testuserlocalhost而你本地连接走了localhost匹配上了这个账号密码对不上自然报1045。遇到这种诡异情况先查一遍mysql.user表里到底有几个同名用户。SELECT user, host, plugin FROM mysql.user WHERE user testuser;3.4 连接串写法对连接成败的影响这个问题很多人忽略但其实很重要。JDBC连接串、Python连接串、命令行参数里写错host或端口也会导致“连接失败”的错觉。比如JDBC连接串要写成jdbc:mysql://127.0.0.1:3306/testdb?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue其中allowPublicKeyRetrievaltrue这个参数非常关键。使用caching_sha2_password插件时如果客户端无法从服务端获取公钥连接会在认证阶段卡住报错信息通常是Public Key Retrieval is not allowed。很多Java项目连不上MySQL 8加了这个参数就通了。Python这边如果用PyMySQL连接参数也要注意版本import pymysql conn pymysql.connect( host127.0.0.1, port3306, userroot, passwordyour_password, databasetestdb )PyMySQL 0.9.3以下版本连8.0基本都会在认证阶段报错升级到1.0以上版本基本就不再有兼容问题了。命令行连接时也要注意端口MySQL 8默认3306但如果你改过端口-P参数必须对应写错同样报连接失败。3.5 Windows环境下的额外注意点Windows上装MySQL 8的用户很多连接失败的原因还多了一条安全软件。360、火绒这类安全软件经常把MySQL进程的3306端口监听行为拦掉或者直接拦截mysqld.exe的network access你不管怎么调配置都没用。排查方式是临时退掉安全软件再试一次连接如果通了那问题就在安全软件规则里。Windows还经常遇到服务启动后又立刻停止的情况。这时候去Windows事件查看器在“Windows日志-应用程序”里找MySQL相关的错误记录往往能看到具体原因比瞎猜快得多。另外Windows上用mysql -u root -p连接时如果提示找不到socket文件通常是因为配置里socket路径和实际不一致或者服务没起来前者改配置后者启动服务即可。4. 常见问题与排查技巧实录4.1 做一次完整的故障复现我在一台测试机上完整复现过一遍Mysql8连接失败的流程。环境是CentOS 7 MySQL 8.0.36客户端在另一台Windows机器上Navicat 15。第一次操作是直接在Windows上用Navicat填IP、用户名root、密码连接报错Authentication plugin caching_sha2_password cannot be loaded。这个报错非常经典基本不用再猜别的就是客户端太老。我当时没去动MySQL配置而是直接把Navicat升级到16再连就通了。但这里有一个细节Navicat升级后如果还连不上可能是连接配置里没勾选允许公钥检索选项新版本客户端一般自动处理了老版本如果没这个选项就需要降级方案——改用户认证插件。第二次复现是模拟防火墙问题。我在Linux服务器上执行firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload之前Navicat报10060执行之后立刻就通了。如果你们公司服务器用iptables检查规则要更细致一点因为可能有多条链的规则互相影响。第三次复现是密码正确但报1045。查了半天发现mysql.user表里root只有rootlocalhost而我用Java服务连接串里写的host是服务器内网IPMySQL把它当成root内网IP去匹配结果没这个用户。解决方案是新建一个root192.168.x.%或root%用户并授权而不是改现有用户的密码。4.2 生产环境最容易被忽略的连接数问题连接失败还有个大坑是连接数满了。MySQL 8默认的max_connections是151如果应用连接池配置不合理连接数很容易被占满。新连接进来直接报Too many connections表现也是“连不上”很容易被误判成网络或认证问题。碰到这个情况先执行SHOW VARIABLES LIKE max_connections; SHOW STATUS LIKE Threads_connected;如果Threads_connected接近max_connections基本就是连接数瓶颈了。临时解法是把max_connections调大根治解法是检查应用的连接池配置比如Druid或HikariCP的最大连接数和等待时间参数别让应用野蛮占用连接。还有一种情况是wait_timeout和interactive_timeout设置过短导致连接被服务端主动断开。表现是查询一段时间后偶发Lost connection to MySQL server during query这种不算是“连接失败”但体验上几乎一样排查时也要注意。4.3 一个冷门但真实的坑DNS反查导致的连接超时MySQL 8在客户端连接时默认会做主机名反查。如果DNS解析很慢连接建立过程就会卡很久最终表现是超时或连接失败。这类问题在跨网段、跨机房连接时特别容易出现。解决方式是在配置里加一行skip-name-resolve加了之后MySQL就不做反查直接用IP匹配mysql.user表里的host。副作用是user表里host必须用IP或%不能写主机名否则连不上。改完配置记得重启MySQL。我帮人排查过一次诡异故障同一个IP有时候能连上有时候超时最后定位就是DNS反查偶尔抽风。4.4 排查顺序速查表总结一下我每次处理Mysql8连接失败的固定排查顺序照着一步步走基本能在十分钟内定位问题步骤操作判断依据第1步本机执行mysql -u root -p能进则本地认证OK进不去查密码和插件第2步ps/netstat查服务和端口服务没起或没监听先解决服务层问题第3步远程机器telnet ip 3306通网络层OK不通查防火墙和bind-address第4步用Navicat或JDBC模拟真实连接复现报错按报错对照表定位第5步查mysql.user表和插件核对用户host、认证插件、密码第6步查连接数和超时参数排除连接数满和超时断开问题这个顺序不是随便排的它的核心逻辑是从底层到上层逐层排除先确认服务本身没问题再看网络是否可达然后才是认证和权限。很多人一上来就改用户密码、改配置文件结果问题根本不在那里白忙活半天。4.5 关于日志的补充说实话很多Mysql8连接失败的排查难点不在于“查不到日志”而在于日志太多不知道看哪个。error log里能看到启动失败、崩溃、认证异常这些关键信息general log默认是关的。如果你实在查不出原因可以临时开一下general log看看客户端连接时到底发生了什么SET GLOBAL general_log ON; SET GLOBAL log_output TABLE;开了之后mysql.general_log表会记录每一条客户端命令包括连接和认证过程。排查完记得关掉生产环境开general log很容易撑爆磁盘。我自己排查过一次很诡异的问题客户端用SSL连接MySQL时报错开了general log才看到是SSL证书校验阶段失败关掉SSL或者正确配置证书就解决了这种问题只看error log根本看不出所以然。5. 个人经验收尾实际上排查Mysql8连接失败这件事只要抓住认证插件、服务监听、网络端口、权限匹配这四件事百分之九十九的问题都能解决。我个人在实操中最深的体会是大部分时候问题不在MySQL本身而是老客户端和新版本之间的代沟。每次遇到连接报错先看一眼客户端版本和驱动版本能帮你省下大半时间。最后再分享一个小技巧如果你频繁要测端口通不通可以不用telnet直接Linux下执行timeout 3 bash -c /dev/tcp/127.0.0.1/3306能通就什么都不输出不通会报错。这个写法在有些telnet没安装的精简服务器上非常管用。另外改完配置重启服务之后一定记得用mysql -u root -p试一次本地连接先把服务端这关过了再去折腾远程连接排查起来会清爽很多。
阅读完成 · 觉得有帮助?