ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

虚拟机MySQL连不上?从网络到认证的全链路排查指南

虚拟机MySQL连不上?从网络到认证的全链路排查指南 “装好了虚拟机里的 MySQL宿主机却连不上 Navicat”是我这几年被问得最多的问题之一。在 Windows 上装好 VMware虚拟机里跑一个 Ubuntu 或 CentOSMySQL 也启动了从宿主机打开 Navicat 却总是报各种莫名其妙的错误——2002 Cant connect、2003 Cant connect、10060、SSL connection error甚至 Access denied。这篇文章就把这条链路从头到尾拆开分清网络层、服务配置层、认证兼容层分别出了什么问题以及每一步怎么验证、怎么改。无论是刚接触 MySQL 的新手还是临时排查环境问题的老手都应该能直接照着做。1. 先搞清楚连不上是不是连错了对象1.1 NAT 模式下最容易犯的错把虚拟机当成了本机一提到“本地虚拟机”很多人下意识觉得它就在自己电脑里所以 Navicat 的主机名填127.0.0.1端口填3306结果怎么都连不上还抱怨“MySQL 明明装了为什么连不上”。这里我们必须先把概念拧过来虚拟机是一台独立的机器它有自己的 IP 地址、自己的网卡、自己的防火墙、自己的 MySQL 实例。所谓“本地虚拟机”只是说这台机器的物理资源是从宿主机分出来的不代表它的服务跑在宿主机的回环地址上。127.0.0.1这个地址在每台机器上都是指向“我自己”。Navicat 填127.0.0.1:3306的时候它连接的是Windows 宿主机自己的 3306 端口。宿主机没装 MySQL 时这个端口根本不存在直接报 2003就算宿主机装了 MySQL连上的也是 Windows 上的那个实例而不是虚拟机里的。正确做法是先查虚拟机的实际 IP。在虚拟机终端里执行ip addr show或者传统一点的ifconfig找到类似ens33、ens160或eth0网卡下的inet地址。如果输出是192.168.x.x这种记下它这就是 Navicat 里该填的主机名。1.2 VMware 三种网络模式与 MySQL 访问的关系了解 VMware 的网络模式是因为很多人连不上根源在于对网络模型的理解偏差。VMware 提供三种常见模式NAT、桥接Bridged、仅主机Host-only它们对 MySQL 远程连接的影响完全不一样。NAT 模式默认模式虚拟机通过宿主机共享 IP 上网。宿主机和虚拟机之间其实是在一个虚拟内网里宿主机可以通过虚拟机 IP 直接访问虚拟机不需要额外做端口映射。桥接模式虚拟机直接和宿主机在一个局域网里相当于接入网络的另一台独立电脑。局域网内其他机器也能直接访问它但要注意 IP 是由路由器或 DHCP 分配的。仅主机模式虚拟机只能和宿主机通信没有对外网络只适合内部调试一般不会拿来跑对外服务。很多人在网上搜到“NAT 模式下虚拟机不能被外部访问”就误以为宿主机要加“端口转发规则”才能连 MySQL。其实那是针对局域网内其他机器的宿主机访问 NAT 网络里的虚拟机走的是 VMnet8 虚拟网卡的网段直接访问虚拟机 IP 即可。举个例子我的 VMware 里 NAT 网段默认是192.168.137.0/24虚拟机的 IP 是192.168.137.129。宿主机上 ipconfig 能看到一块叫 “VMware VMnet8” 的虚拟网卡IP 通常是192.168.137.1。宿主机 ping192.168.137.129能通TCP 访问192.168.137.129:3306也是自然可行的前提是虚拟机的防火墙和 MySQL 配置都放行。理解这一层之后很多“为什么 localhost 连不上”的困惑就消失了不是 Navicat 有问题而是你填的上网对象本就不对。2. 网络层排查先确认虚拟机本身能被找到2.1 宿主机 ping 虚拟机通还是不通改 Navicat 主机名之前先做一个最基础的网络层测试宿主机能不能 ping 通虚拟机。在宿主机命令行执行ping 192.168.137.129如果你连 ping 都不通后面所有关于 MySQL 的折腾都是白费。这个阶段常见的三个原因虚拟机没拿到 IP虚拟机开机后没进入系统或者网卡没配置。用ip addr show检查网卡状态是不是UP有没有inet地址。VMnet8 网卡被禁用打开“控制面板 → 网络连接”确认 “VMware VMnet8” 没有被禁用ipconfig 里能看到对应网段。虚拟机防火墙禁 pingLinux 发行版不一定默认禁 ICMP但某些云镜像或定制系统会。这个我们放到防火墙那一节一起处理。另外一个小技巧如果 ping 不通可以重启 VMware 的虚拟网络服务。打开“编辑 → 虚拟网络编辑器”点击左下角“更改设置”然后选择“还原默认设置”。这个操作会重置 VMnet8 网段有一定概率解决虚拟网卡状态异常的问题代价是之前自定义的网络配置会丢失。2.2 测端口是否可达telnet、nc、Test-NetConnectionping 通之后下一步确认 TCP 3306 端口能不能从宿主机访问到。Windows 宿主机上最直观的方式是 PowerShell 自带的命令Test-NetConnection 192.168.137.129 -Port 3306如果输出里TcpTestSucceeded : True说明端口已通跳过去看第 3 章如果是 False就要继续排查。Linux/Unix 宿主或装了 WSL 的话可以用 ncnc -zv 192.168.137.129 3306也可以试试 Windows 自带的 telnet 客户端。不过 Windows 的 telnet 默认是没安装的需要在“启用或关闭 Windows 功能”里勾选 Telnet 客户端不想折腾就直接用 Test-NetConnection。还有一种情况端口测试显示Connection refused但虚拟机里 MySQL 明明在跑。这时候要区分两个错误现象含义最常见原因连接超时Timeout / 10060网络路由不通或防火墙默默丢弃数据包虚拟机防火墙拦截或网络隔离连接被拒绝Refused / 10061目标主机收到了数据包但对应端口没有服务在监听MySQL 没启动或没监听 3306记住这个区分排错时能省很多时间。很多人在“连接被拒绝”状态下还去改防火墙完全找错了方向。2.3 防火墙拦了哪些流量虚拟机内部防火墙与热门命令确认端口不通或者想排查防火墙时进虚拟机看它自己的防火墙状态。不同发行版用的工具不一样最常见的三种Ubuntu/Debian 系用ufwCentOS/RHEL 系用firewalld通用底层是iptables查看是否启用了防火墙# Ubuntu sudo ufw status # CentOS sudo systemctl status firewalld如果防火墙开着就需要放行 3306 端口# Ubuntu / ufw sudo ufw allow 3306/tcp sudo ufw reload # CentOS / firewalld sudo firewall-cmd --zonepublic --add-port3306/tcp --permanent sudo firewall-cmd --reload如果是 iptables 直接管理sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT但注意iptables命令直接加的规则重启后会失效要持久化得保存规则或用 firewalld/ufw 这种上层管理工具。我实际遇到过一种容易忽略的情况Ubuntu Server 安装时选了 OpenSSH但默认 ufw 是 inactive 的防火墙根本没开这时端口仍然不通。所以不要只看防火墙状态还得用ss -tlnp | grep 3306确认 MySQL 的监听地址这就是下一章的重点。提示改完防火墙规则后回到宿主机重新跑一次Test-NetConnection确认状态变化。不要想当然觉得放行了就一定通我见过太多“放了端口还是连接超时”的案例最后发现是云平台或物理路由器层面还有安全策略。3. MySQL 服务端配置监听地址和账号权限3.1 bind-address 这个默认配置太容易踩了如果端口通了连接还是失败那么问题基本出在 MySQL 自己身上。大家都知道“MySQL 安装后默认只允许本机访问”但很少有人知道这句话背后的关键参数是bind-address。MySQL 默认监听127.0.0.1也就是只接受来自本机的连接。虚拟机里的 Navicat 客户端当然连得上但宿主机通过 TCP 发来的连接即使网络层、防火墙全通了MySQL 也会直接无视。查看当前监听状态sudo netstat -tlnp | grep 3306如果输出是tcp6 0 0 127.0.0.1:3306 :::* LISTEN说明只监听了本机回环地址。改成全部网卡监听编辑 MySQL 配置文件。Ubuntu/Debian/etc/mysql/mysql.conf.d/mysqld.cnfCentOS/RHEL/etc/my.cnf或/etc/my.cnf.d/在[mysqld]段下找到bind-address 127.0.0.1改成bind-address 0.0.0.0重启服务# Ubuntu sudo systemctl restart mysql # CentOS sudo systemctl restart mysqld再检查一次监听sudo netstat -tlnp | grep 3306这时候应当看到 MySQL 监听在0.0.0.0:3306说明它已经准备好接收来自任意网卡的 TCP 连接了。3.2 skip-networking 与 mysqld.sock 的误导比 bind-address 更隐蔽的是skip-networking。这个参数一旦开启MySQL 会完全关闭 TCP/IP 监听只保留 Unix socket 文件通常位于/tmp/mysql.sock或/var/run/mysqld/mysqld.sock。这时候就算 bind-address 改成 0.0.0.0 也没用因为网络栈整个被关掉了。检查配置grep -r skip-networking /etc/mysql/如果找到了注释掉这一行再重启 MySQL。顺带提一句很多人在 Linux 本机执行mysql命令排出错时看提示里提到/var/run/mysqld/mysqld.sock就觉得是 sock 文件的问题。其实当 Navicat 通过 TCP 连接时跟 sock 文件一点关系都没有那是 Linux 本地客户端默认走 socket 才有的报错。别把两种连接方式混在一起。另外MySQL 8 还会默认启动一个 MySQL X 插件监听 33060 端口。如果ss -tlnp里看到127.0.0.1:33060那是 X 协议MySQL Shell 用不是普通 Navicat 连接要用的端口别被它带偏。Navicat 默认连的是 3306。3.3 初装环境的 root 认证与授权问题网络层通了、MySQL 也监听了接着最常见的拦路虎就是权限认证。尤其是 Ubuntu 上用apt安装的 MySQL默认 root 用户使用的是auth_socket插件而不是密码认证。如果你在虚拟机里执行sudo mysql能直接进去但宿主机 Navicat 用“root 你设置的密码”却报Access denied十有八九就是这个原因。先用本机 root 权限进入 MySQLsudo mysql然后查看用户表和认证插件SELECT user, host, plugin FROM mysql.user;如果看到 root 的 plugin 是auth_socket说明它只认 socket 身份认证不认 TCP 密码。手动改成密码认证ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;改完再用宿主机 Navicat 试一次。如果你希望 root 也能从远程 IP 登录还需要补一条ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; CREATE USER root192.168.137.% IDENTIFIED WITH mysql_native_password BY 你的密码; GRANT ALL PRIVILEGES ON *.* TO root192.168.137.%; FLUSH PRIVILEGES;这里用网段限制而不是%是为了避免 root 密码被任意 IP 暴力尝试。3.4 为 Navicat 创建一个专用远程账号推荐做法虽然把 root 改成远程可登录能解决眼前问题但我实际工作中更推荐单独建一个专用账号。原因很简单日常开发调试不该拿超级管理员裸奔账号越少改动线上环境越安全。在 MySQL 里执行CREATE USER navicat192.168.137.% IDENTIFIED BY Navi2024; GRANT ALL PRIVILEGES ON *.* TO navicat192.168.137.%; FLUSH PRIVILEGES;这段命令的关键是navicat192.168.137.%。后面跟着来源主机限制192.168.137.%表示只允许这个网段的 IP 连接。如果你不确定虚拟机 IP 可能变化可以放宽到navicat%但在真实环境中这是有风险的至少应该用网段或具体 IP而不是不管三七二十一全放开。创建完账号后回到宿主机 Navicat 用这个新账号登录。如果这时候还报错往下看第 4 章问题很可能不在网络和权限而在客户端和服务端的认证协议不匹配。4. Navicat 侧的兼容性认证插件、SSL 和版本4.1 MySQL 8 的 caching_sha2_password 与旧版 Navicat 的冲突MySQL 8 默认认证插件是caching_sha2_password而很多老版本 Navicat尤其是 15 之前的版本只认识旧的mysql_native_password。结果就是连接时报Authentication plugin caching_sha2_password cannot be loaded我第一次遇到这个错误时第一反应是密码错了反复确认密码无误后才发现是认证插件不兼容。解决办法有三种优先级从上到下升级 Navicat 到 16 或 17新版本完全支持 MySQL 8 的默认认证插件这是最省事、最推荐的方案。把账号认证方式改回mysql_native_password如果你暂时不想升级 Navicat又必须用它连库可以把对应账号改回旧插件ALTER USER navicat192.168.137.% IDENTIFIED WITH mysql_native_password BY Navi2024; FLUSH PRIVILEGES;换用其他客户端DBeaver、DataGrip 等工具对 MySQL 8 的认证支持也都不错可以作为临时替代。需要提醒的是mysql_native_password是 MySQL 官方已经在淘汰的认证方式不建议把它当作长期方案。如果只是个人开发环境图省事那随意但生产环境应优先升级客户端而不是拉低服务端的认证强度。4.2 SSL connection error 到底从哪来有相当多的人在解决完认证插件问题后又遇上一个新错误——SSL connection error。MySQL 8 默认开启了 SSL服务器启动时会读取系统里的 SSL 证书。如果证书文件缺失、路径不对或者客户端校验失败就会报 SSL 相关错误。先确认 MySQL 服务端 SSL 的状态SHOW VARIABLES LIKE %ssl%; SHOW STATUS LIKE Ssl_cipher;如果have_ssl是DISABLED说明服务端没有启用 SSL 或没有正确加载证书。这时候客户端反复报 SSL 错误就很奇怪但现实中确实存在服务端配置了 SSL 但证书无效客户端验证不通过。最简单的应急处理是在 Navicat 连接配置里关闭 SSL。在“连接属性”页签里找到 SSL 相关的设置通常在“高级”或“SSL”标签页把“使用 SSL”的勾选去掉重新测试连接。命令行验证时可以加--ssl-mode参数mysql -h 192.168.137.129 -u navicat -p --ssl-modeDISABLED如果这样能连上说明问题就在 SSL 握手环节普通开发环境直接把客户端 SSL 关掉即可。如果连服务端都想彻底不要 SSL可以在[mysqld]里加skip_ssl重启 MySQL。但这会降低传输安全公网环境千万别用只在纯内网开发调试时才有意义。4.3 Navicat 版本与驱动差异带来的隐藏问题讲一个我实际踩过的场景宿主机上同时装了 Navicat Premium 17 和 Navicat for MySQL 15两个工具连同一个虚拟机一个能连一个不能连。核心原因就是版本对认证协议支持不同而很多人会因为先安装了旧版本就一直停留在错误里出不去。除了版本Navicat 本身的安装来源也值得关注。网上经常能看到“Navicat 永久许可密钥”“Navicat 破解安装”“navicat premium 17 永久许可证”这类关键词这里劝一句破解版和注册机既不稳定也容易带后门生产环境出了问题哭都来不及。官方长期免费试用版虽然限时临时调试完全够用如果日常必须用优先考虑正版订阅或者直接切到免费开源的 DBeaver Community。另外如果虚拟机里 MySQL 是 Docker 方式跑的注意确认宿主机映射端口时是把3306映射到宿主机的哪个端口。Navicat 里的端口要填映射后的端口而不是总默认 3306。这个坑跟虚拟机的网络模式本质上是同一类问题服务实际监听的地址/端口和你填写的不一致。5. 一次完整的修复实录从报错到连通的排查路径5.1 一个案例复盘2002 报错的全部处理步骤拿一个具体环境来走一遍完整流程。假设环境是VMware Workstation 16 Ubuntu 22.04 Server MySQL 8.0宿主机是 Windows 11 Navicat 16。启动虚拟机后Navicat 新建连接主机名填127.0.0.1端口3306点“连接测试”报错2002 - Cant connect to local MySQL server through socket /var/run/mysqld/mysqld.sock注意这里的措辞它说“local MySQL server”本质上就是因为填了127.0.0.1Navicat 默认走了本地 socket 而不是 TCP 连接。第一步先改正理解在虚拟机终端执行ip addr show查到 IP 是192.168.137.129。把 Navicat 主机名改成192.168.137.129再试。这次报错变成了2003 - Cant connect to MySQL server on 192.168.137.129 (10060)10060 是连接超时。宿主机 ping 虚拟机发现能通于是判断问题出在端口或防火墙。用 Test-NetConnection 测试 3306结果为 False。进虚拟机检查 ufw 状态发现 ufw 是 inactive 的不是防火墙问题。这时用netstat -tlnp | grep 3306发现 MySQL 监听的是127.0.0.1:3306问题找到了。修改/etc/mysql/mysql.conf.d/mysqld.cnf的bind-address 0.0.0.0重启 MySQL 后监听变为0.0.0.0:3306。回宿主机重新测试端口显示通了。但 Navicat 连接时又报Access denied for user root192.168.137.1进入sudo mysql发现 Ubuntu 默认 root 用的是auth_socket插件。于是新建了专用账号navicat192.168.137.%并授权Navicat 里用新账号重新连接这次成功进入数据库。整个链路看下来问题的根源其实分散在三层配置地址写错、MySQL 未监听外部连接、账号认证方式不对。每一层都有对应的验证手段只要按顺序排查都不会卡太久。5.2 报错信息速查常见错误码与处理动作把上面的经验整理成一张速查表作为以后排错的参照报错或现象含义最可能原因处理动作2002 local MySQL server through socketNavicat 走本机 socket 连接失败主机名填了 localhost/127.0.0.1改用虚拟机实际 IP2003 (10060)TCP 连接超时防火墙丢弃、网络不可达、VMnet8 未启用检查防火墙和虚拟网络配置2003 (10061)目标端口拒绝连接MySQL 未启动、未监听 3306、bind-address 不对启动 MySQL 并修改监听地址Access denied for user认证失败账号密码错误、来源 IP 未授权、认证插件不匹配检查用户授权和 pluginAuthentication plugin cannot be loaded客户端不认识认证插件MySQL 8 默认插件与旧版 Navicat 不兼容升级 Navicat 或改回旧插件SSL connection errorSSL 握手失败服务端证书无效、客户端校验失败临时关闭客户端 SSL 选项这张表的价值在于帮你快速定位而不是让你每遇到报错就把网上所有方案试一遍。先判断错误属于网络层、服务层、还是认证层再对症处理。5.3 最后说几条经验我在处理这类问题时最喜欢坚持一个顺序网络通 → 端口通 → 账号通 → 客户端兼容。不管新换环境还是帮别人远程排查都先从“宿主机能不能 ping 通虚拟机”开始然后一层层往下走。大多数“连不上 MySQL”的案例最终定位到的都不是 MySQL 本身的问题而是监听地址和防火墙。还有一个容易被忽略的小细节Navicat 连接配置里主机名和端口旁边往往有“测试连接”按钮每改一个配置点一次测试不要一口气改完再纠结。改完测试、测试完再改效率反而比盲猜快得多。如果你已经把 bind-address、防火墙、授权账号都排查过了仍然连不上试着在虚拟机本机执行一次mysql -u 用户名 -p -h 127.0.0.1。本机能连、宿主机不能连问题必然出在网络链路本机也不能连问题就出在 MySQL 配置或账号本身。这一条原则基本可以覆盖 90% 的排查场景。
返回列表