
我正儿八经开始系统研究 Navicat 连接 MySQL 报 2013 错误是帮同事排查一台刚部署好的 MySQL 8.0。服务已经起来了端口也在监听可 Navicat 点完连接转个几秒就弹一句Lost connection to MySQL server during query。第一次遇到的人基本都会被这串英文绕晕——明明不是“连接被拒绝”却又确实连不上。这些年我处理过的 2013 错误散落在各种场景里刚装完 MySQL 的、跑了半截存储过程的、Docker 里起 MySQL 从宿主机连的、跨办公室网络导大表的。这篇就把所有情况归纳成一条可操作的排查链路核心是三个字看阶段。先分清连接是断在哪个环节再看服务端参数最后查网络和客户端细节保证遇到同类问题的人能直接照着定位而不是靠瞎改配置碰运气。1. 先读透错误码2013 不是“连不上”而是“连上之后断了”1.1 字面意思与实际作用阶段2013 的完整文案是Lost connection to MySQL server during query中文版通常翻译成“查询过程中丢失了与 MySQL 服务器的连接”。重点就在during query这三个单词TCP 连接此时已经建立了MySQL 服务端也接受了你的账号认证掉线发生在“执行查询”或“传输结果集”的过程中。这一点特别重要因为它直接帮你划掉了大量无效排查方向。连接不是卡在“找不到服务”“端口不通”“密码错误”那些基础环节而是发生在更靠后的阶段。所以遇到 2013我一般不会浪费时间反复确认 MySQL 服务有没有启动而是把精力集中到超时参数、数据包大小、网络稳定性、SQL 本身重量这四个方向。错误码是按阶段设计的客户端看到的提示也经过翻译和包装只有把阶段搞清楚了后面的排查路线才不会偏。1.2 和 2002、2003、2059 放在一起看Navicat 报错时很多人只看数字不看英文导致把 2013 和 2003 混为一谈。其实这俩的排查方向完全不同。我把最容易混淆的几个错误码整理成一张表建议收藏错误码客户端常见提示发生在哪个阶段优先排查方向2002Cant connect to local MySQL server through socketUNIX Socket 连接阶段Socket 路径、mysqld 是否启动2003Cant connect to MySQL server on host (10061/10060)TCP 连接建立阶段端口监听、防火墙、bind-address2013Lost connection to MySQL server during query认证后的查询/传输阶段超时参数、max_allowed_packet、网络稳定性2006MySQL server has gone away查询执行阶段服务端异常终止、连接被清理2059Authentication plugin caching_sha2_password cannot be loaded认证阶段Navicat 版本过旧 / MySQL 8 默认认证插件这张表里2006 和 2013 是“亲兄弟”。2006 是客户端发现服务端没了2013 是服务端在查询执行中把连接掐了实际场景里经常交替出现。而 2059 是 MySQL 8.0 默认身份认证插件caching_sha2_password和老版本 Navicat 不兼容导致很多人把它也笼统归到 2013结果改了半天超时参数完全没用。把 2013 单独拎出来还有一个原因它往往不是单一原因。一个慢 SQL 拖太久、中间网络设备把空闲连接清了、服务端参数太小、甚至 MySQL 服务正好重启最后映射到客户端都是同一个 2013。所以下面按“什么时候断”来切场景是最实用的分法。2. 按报错时机切入连接瞬间断和处理大 SQL 时断是两条完全不同的排查线2.1 场景 A连接就断连库都进不去如果你刚点开 Navicat 的连接还没来得及执行任何 SQL 就报 2013说明连接虽然握上手了但很快被服务端或网络掐掉了。我真实遇到过的触发点有这几类MySQL 服务刚启动还没 ready或者启动后立刻崩溃。Windows 上很典型的表现就是用net start mysql启动时看到“服务正在启动”几秒后又停止Navicat 在窗口期连接就会握手成功后立刻掉线。连接数打满max_connections。新连接排队超时或被直接清理症状也可能表现为 2013。服务端正在执行 shutdown或者 redo log 刷盘卡住导致已有连接被强制关闭。客户端到服务端的握手包被防火墙策略丢弃或延迟。这种通常更像 2003但极端情况下也会表现为 2013。这种场景我建议先别碰任何参数。第一步是切到命令行客户端在同一台机器上直接执行mysql -h 127.0.0.1 -P 3306 -u root -p命令行能稳定进入问题多半在 Navicat 的配置或认证中间层命令行也进不去直接去看 mysqld 状态和错误日志重点查是不是服务启动失败、初始化没完成、端口被占用。我见过不少人在这类问题里反复修改 Navicat 的连接超时实际上服务端压根是崩溃循环方向完全跑偏。2.2 场景 B查询/导出跑到一半掉线这是 2013 出现频率最高的一种形态连接正常、表能看、简单查询没问题但执行一个大 SQL、导出一张大表、跑一个十几分钟的存储过程时中途直接报 2013。优先怀疑四件事max_allowed_packet太小客户端发起的数据包或服务端返回的结果集超过限制。net_read_timeout/net_write_timeout太短服务端在读写网络包时长时间没进展就主动断开连接。查询本身太重占满 CPU/IO服务端线程卡死连接被监控或故障切换机制清理。链路中间的 NAT、防火墙会话老化小查询秒回没问题大查询一跑几分钟中间设备先把会话拆了。如果你的报错发生在 Navicat 的查询窗口里还有一个我踩过的细节窗口执行大 SQL 时会一直处于等待状态这时候尽量别切换页面做其他操作有些版本在内部切换任务时会出现连接假死过一会儿就报 2013。这个原因虽然不如服务端超时常见但排错时完全不检查它容易多花大半天。2.3 动手改参数前先拿下这三条现场线索很多人一看到 2013 就上来改wait_timeout其实方向可能完全搞错。我每次接到这种问题会先做三件事把“现场证据”固定下来第一临时把错误日志详细级别调高。MySQL 5.7/8.0 里执行SET GLOBAL log_error_verbosity3;它会把Aborted connection的详细原因打到错误日志里。默认级别是 2这些 note 级别的记录不会出现所以很多人从头到尾都不知道服务端为什么要断。第二看状态计数。执行SHOW GLOBAL STATUS LIKE Aborted_clients; SHOW GLOBAL STATUS LIKE Aborted_connects;Aborted_clients一直涨基本可以确定服务端主动关了连接Aborted_connects涨说明很多连接在握手阶段就没成功。第三复现报错的那一刻赶紧执行SHOW PROCESSLIST看那个查询卡在什么 State。如果 State 是Reading from net或Writing to net基本可以锁定读超时或写超时。这三条线索配合起来能把 2013 从“瞎猜”变成“定位”。3. 服务端连接参数逐个核wait_timeout、max_allowed_packet、net_read_timeout3.1 max_allowed_packet执行大 SQL 脚本时的高频凶手这是我最先检查的参数。它控制 MySQL 允许接收和返回的最大单个数据包大小注意两个方向都受影响客户端发过去的 INSERT/UPDATE/大 SQL 超过它会被拒服务端返回的 SELECT 结果集超过它同样会出问题。MySQL 5.7 的默认值是 4MB8.0 默认是 64MB但这个值经常被运维改小或者被 my.ini 里的旧配置覆盖。典型场景是 Navicat 导入一个几十 MB 的 SQL 文件或者 SELECT 一张带大 TEXT/BLOB 字段的表。客户端这边超限时Navicat 往往不直接报服务端那种“Packet too large”的 1153 错误而是表现为 2013、2006 这类“连接丢了”。判断方法也简单查一下SELECT global.max_allowed_packet, session.max_allowed_packet;然后对比你那条 SQL 文件的体积就能看出玄机。3.2 三个超时参数如何配合2013 的“连接中途断开”超时参数是最直接的解释。需要用到的变量就这几个变量名MySQL 8.0 默认值作用wait_timeout28800非交互连接空闲多久后由服务端关闭interactive_timeout28800交互式连接带 CLIENT_INTERACTIVE空闲多久后关闭net_read_timeout30服务端等待从客户端读取数据的阻塞时间net_write_timeout60服务端尝试向客户端写入数据的阻塞时间connect_timeout10服务端等待客户端完成握手包的时间下面按实际场景解释wait_timeout和interactive_timeout管的是“空闲”——连接建立后没有任何 SQL。默认 8 小时日常很难触发但如果你把值改成了 60 秒Navicat 放一会儿不动下一次执行第一条 SQL 就大概率 2013。很多图形客户端在握手时会带上交互式标志是否归为交互式由客户端决定所以排查时要两个变量一起看。net_write_timeout管的是“服务端往外写但客户端迟迟不读”。公司网络跨公网导数据、结果集特别大时最容易卡在这里。net_read_timeout管的是“服务端等着读客户端发来的数据”客户端发了半截包卡住或者极端网络抖动时触发。补充一个容易误判的点net_read_timeout/net_write_timeout的计时不是按整个查询算的而是按“一次 socket 读写有没有进展”算的。所以慢查询本身不一定会触发它只有当服务端真的阻塞在读写上超过阈值才会断开。3.3 改参数的正确姿势与验证方法如果判断是超时或数据包问题改法分两步先运行时临时改验证有效后再持久化。运行时先执行SET GLOBAL max_allowed_packet 134217728; SET GLOBAL net_read_timeout 300; SET GLOBAL net_write_timeout 300; SET GLOBAL wait_timeout 28800; SET GLOBAL interactive_timeout 28800;注意SET GLOBAL只对新连接生效Navicat 里已经打开的连接必须关闭重连。验证没问题后再改到 my.ini 的[mysqld]段让它永久生效[mysqld] max_allowed_packet128M net_read_timeout300 net_write_timeout300Windows 下 my.ini 的位置可以通过mysqld --verbose --help | findstr my.ini找到或者直接看服务属性里的--defaults-file参数。改完重启服务重启命令是net stop MySQL80 net start MySQL80服务名以你机器上的实际为准。验证方法很直接改完之后再执行一次原来报错的操作同时观察Aborted_clients是否还在涨。连续跑三次都没断这个方向基本排除。4. 网络路径与 Navicat 客户端里的隐藏问题防火墙、SSL、主机名解析4.1 中间网络设备“静默断连”为什么难查如果服务端参数全正常、命令行实测也稳定但 Navicat 隔一段时间就报 2013很大概率是中间网络设备把连接“静默”清掉了。常见于跨公网连接云数据库、办公室网关做了 NAT、防火墙开了会话老化清理。小查询几十毫秒就结束自然看不出问题一旦有个查询跑几十秒或者空闲几分钟中间设备按它的会话超时把 TCP 连接拆了MySQL 两端还蒙在鼓里下一条 SQL 立刻就是 2013。这种问题难排查是因为两边服务都健康故障只出现在“链路中间”。有两个经验值可以快速判断一是看报错是不是总出现在“空闲后第一次操作”二是用一个长连接脚本每隔 30 秒发一次SELECT 1观察能不能稳定跑几小时。如果长连接稳定、停顿之后再操作就断那基本锁死是闲时会话被清理。应对办法比较务实把服务端的wait_timeout调得比会话老化时间小一点让服务端先正常断开连接客户端重连而不是被动被网络设备掐断产生 2013 这种挂在半空的状态。4.2 Navicat 的高级选项和连接超时设置Navicat 这边同样有坑。右键连接编辑连接进入高级或 SSL 页如果勾选了 Use SSL而服务端没开 SSL 或证书不对握手阶段很容易超时或失败。本地测试环境直接取消勾选。部分版本在高级页有连接超时选项默认值很小的话大查询会先从客户端这边被掐断报出来也是 2013 系列。主机名建议写具体 IP而不是写 localhost。Windows 下 localhost 可能解析成::1而 MySQL 只监听了 IPv4结果表现为连接时好时坏或超时。写127.0.0.1或者服务器真实 IP能避开这个坑。这些看似无关紧要的细节往往才是真正把你困住的点。有一次我把服务端参数开到足够大问题依旧最后发现就是 Navicat 里勾了 SSL服务端没配证书连接在握手后马上被掐断——这同样表现为 2013。4.3 用命令行客户端做隔离验证这一步是判断“到底是谁的问题”最有效的手段强烈建议在改任何参数之前先做mysql -h 127.0.0.1 -P 3306 -u root -p mysql -h 192.168.1.10 -P 3306 -u root -p两条命令一条测本机、一条测实际要走的网络地址。两条都报 2013问题在服务端或网络本机通、远端不通先查 bind-address、防火墙、安全组命令行稳定但 Navicat 断重点看 Navicat 的 SSL、超时、主机名解析设置。这个隔离思路能帮你把问题范围砍掉一大半。4.4 bind-address 与防火墙的检查清单Windows 本机部署 MySQL 时还有一个微妙点MySQL 8.0 默认监听0.0.0.0或::但如果你在 my.ini 里写了bind-address127.0.0.1那局域网其他机器用 Navicat 连就是 2003 而不是 2013反过来如果只监听了::1或 IPv6部分 Navicat 版本解析 IPv4 就会异常。检查监听状态用两条命令netstat -ano | findstr :3306 Test-NetConnection 192.168.1.10 -Port 3306第一条看本机监听地址到底是 127.0.0.1 还是 0.0.0.0第二条看端口能不能从外部通。把这两条跑完网络层的变量基本就排除干净了。5. Docker 里装 MySQL 报 2013 的高频原因端口映射、bind-address 与容器重启5.1 端口映射没生效 / 宿主端口占用Docker 场景下的 2013我最常见的前两位原因都和端口映射有关。第一个是启动时-p 3306:3306没写或者写了但宿主机的 3306 已经被本机装的 MySQL 占用了。Docker 启动很可能不报错实际端口却根本没映射出去Navicat 连上去就会超时、断连。第二个是容器重启后 IP 变了——如果你 Navicat 里写的是容器 IP而容器每次启动 IP 都可能重新分配那过一段时间就连不上了。正确做法是永远用宿主机 IP 加映射端口不要用容器 IP。先确认映射状态docker ps --format table {{.Names}}\t{{.Ports}}看到0.0.0.0:33066-3306/tcp这种输出说明映射正常Navicat 连127.0.0.1:33066即可。5.2 容器里的 bind-address 和认证插件第二个高频坑是容器内 MySQL 的 bind-address。官方 mysql 镜像默认监听所有地址但如果你挂载了自己的 my.cnf或者某些简化镜像里写了bind-address127.0.0.1那端口虽然映射出来了容器内的服务却只在本机回环上监听宿主机连过去就会连上又断开。检查方法docker exec mysql8 mysql -uroot -p -e SHOW VARIABLES LIKE bind_address;如果是127.0.0.1改成0.0.0.0。另外提醒一句官方mysql:8镜像默认认证插件是caching_sha2_password旧版 Navicat 报的通常是 2059 而不是 2013别把这两个混在一起改参数否则白忙一场。5.3 一段可直接用的 Docker 部署参考给出我本人在本地测试常用的启动命令注释都写在参数后面了docker run -d \ --name mysql8 \ -p 33066:3306 \ -e MYSQL_ROOT_PASSWORD你的密码 \ -e TZAsia/Shanghai \ --restartunless-stopped \ -v mysql_data:/var/lib/mysql \ mysql:8.0用33066而不是3306作为宿主机端口是为了避免和本机已有 MySQL 冲突映射正常后Navicat 填127.0.0.1:33066用户名 root 即可。如果这样连还是 2013回到上一小节检查 bind-address再看docker logs mysql8里有没有服务端异常记录。Docker 环境还有一个隐藏问题实测中 Docker Desktop 的网络层偶发空闲断连长时间不操作后第一次查询报 2013 的概率比其他环境高遇到时先重连一次再判断要不要深入查。6. 一次真实排查全程从报错日志到根因修复用了十分钟6.1 现场现象与最初猜测上个月同事找我说 Navicat 跑一个导出任务时报 2013查询窗口执行一条 SELECT 大表数据表里有几个 text 字段正常要跑一分多钟但经常跑到一半弹Lost connection to MySQL server during query。他自己已经改过 wait_timeout无效。我第一反应也是 max_allowed_packet但查了一圈发现数据包并不大问题不在这个方向。6.2 三层验证过程我把排查过程压缩成三步。第一步命令行复现。用mysql -h 127.0.0.1 -P 3306 -u root -p连上后执行同样的 SELECT重定向到文件果然也会中途断。这个结果排除了 Navicat 客户端本身焦点转到服务端或网络。第二步看错误日志。临时把log_error_verbosity调到 3重新跑一次导出错误日志里出现一行关键记录Aborted connection ... Got timeout writing communication packets。writing这个单词直接把方向锁到net_write_timeout。这里我特别想强调客户端提示永远是笼统的 2013精准方向其实在服务端日志里。第三步查参数。SHOW GLOBAL VARIABLES LIKE net_write_timeout;返回 60默认值。结合导出场景结果集有几百万行服务端向客户端写数据时中间网络偶发拥塞一次 socket 写超过 60 秒没进展服务端就主动断开。6.3 根因、修复与验证结果根因其实不是 MySQL 配置“错了”而是默认的net_write_timeout60对“跨网络导大结果集”这个场景太短。修复分两步先SET GLOBAL net_write_timeout300; SET GLOBAL net_read_timeout300;让新连接生效再在 my.ini 的[mysqld]段写入同样参数重启 MySQL 固化。改完重新执行导出连续三次都稳定跑完没有再报 2013。这里有个很关键的知识点客户端提示是 2013排查依据却来自服务端错误日志里的Aborted connection行。日志里会写明是reading还是writing这是 2013 最精准的方向指示器。如果你的生产环境默认不记录这些 note建议临时开log_error_verbosity3定位完再调回 2。6.4 踩完这个坑之后我固定的排查顺序现在再遇到 Navicat 报 2013我不会再像以前那样先把所有参数改一遍。固定顺序是命令行复现判断是 Navicat 独有还是全局问题开log_error_verbosity3抓Aborted connection日志看是 reading 还是 writing看Aborted_clients/Aborted_connects状态变化按“连接瞬间断”还是“执行中断”分线检查max_allowed_packet、net_read_timeout、net_write_timeout、wait_timeout网络层用netstat和Test-NetConnection排查端口与防火墙Docker 场景单独查端口映射、bind-address、容器日志。这套流程走下来处理时间通常能控制在半小时以内。根据我个人经验2013 不是玄学它是 MySQL 最容易定位的连接类问题之一——前提是别跳过日志直接改参数。真正花时间的往往不是错误本身而是你愿不愿意先去日志里看一眼服务端到底在抱怨什么。