前阵子帮人收拾一台测试服务器,机器上同时装了 MySQL 5.7 和 MySQL 8.0,前一天还能正常连的 5.7,第二天再去看,systemctl status mysqld 居然直接提示 Unit not found,服务就像人间蒸发了一样。更诡异的是 8.0 一直好端端的。排查了一下午,最后发现根本不是“莫名其妙”,而是多版本共存时,服务文件、配置文件、数据目录这些资源在底层互相覆盖,导致 5.7 的服务单元被 8.0 的安装包“顶掉”了。
这个场景其实非常典型——很多人在同一台机器上折腾两个版本的 MySQL,不是用 Docker,而是直接装到系统里。一旦遇到服务“消失”、启动失败、服务启动后马上退出的情况,第一反应往往是重装,结果越装越乱。这篇文章就围绕“同时装 MySQL 5.7 和 8.0,5.7 服务消失”这个问题,把根因、排查方法和正确共存方案一次讲清楚,适合对 Linux、systemd 和 MySQL 有一定基础,但还没踩过多版本部署坑的同学参考。
1. 先弄清楚“服务消失”是怎么发生的
1.1 一次经典翻车:8.0 和 5.7 打架的现场还原
先说一个我实际遇到的翻车过程。那台机器原本是 MySQL 5.7,通过官方 rpm 包安装,跑了半年一直很稳。后来因为业务需要测试 8.0 的新特性,直接用 yum 装了 mysql80-community-release 仓库,然后 yum install mysql-community-server。
装完后 8.0 能正常启动,但提示 mysqld 已经在运行。当时没多想,直接 systemctl stop mysqld 停掉旧的,又 systemctl start mysqld 启动新的,结果 8.0 也起来了,连 mysql -uroot -p 看到的版本号也是 8.0。
过了一周,需要检查 5.7 里的数据,执行 systemctl start mysqld,日志直接报错,再看 systemctl status mysqld,服务还在,但怎么都启动不起来。后来折腾半天,发现 /usr/lib/systemd/system/mysqld.service 这个文件已经被 8.0 的包覆盖了,内容里指向的 ExecStart 参数、PIDFile 路径、配置读取顺序,全是 8.0 的版本。5.7 的二进制文件倒是还在 /usr/sbin/mysqld,但已经被替换成了 8.0 的二进制——或者更准确地说,旧的 5.7 可执行文件被 rpm 升级成了 8.0。
这就是“服务消失”的第一层真相:MySQL 5.7 和 8.0 使用完全相同的服务名 mysqld.service、相同的配置路径 /etc/my.cnf、相同的数据目录 /var/lib/mysql,rpm 包按“同路径覆盖”的方式安装时,后装的版本会把先装版本的关键文件替换掉,于是旧版本看起来就像“消失”了。
1.2 服务消失的真正原因:四种典型元凶
我整理了这几次排查经历,发现所谓“5.7 服务莫名消失”,其实不外乎下面四种情况,可以拿来自查。
第一种是 systemd 单元文件被覆盖或删除。5.7 和 8.0 的 rpm 包都自带 /usr/lib/systemd/system/mysqld.service,安装新版本时,rpm 会直接覆盖这个文件。覆盖后即使你执行 systemctl start mysqld,systemd 会加载 8.0 的启动参数,要么启动的是 8.0,要么因为参数不兼容导致 5.7 起不来。如果卸载 8.0 时把原来的单元文件也清掉了,那就直接变成 Unit not found。
第二种是 数据目录冲突。5.7 和 8.0 默认都使用 /var/lib/mysql 作为 datadir。如果你在 5.7 还在跑的时候初始化了 8.0,初始化动作会往同一个目录写入新版本的数据字典格式。5.7 再去读取时,会因为数据字典版本不兼容直接失败——这不是“服务消失”,而是服务还在,但永远启动不了,systemd 会显示 failed,很多人看到 failed 就当“服务坏了”去重装。
第三种是 配置文件串台。/etc/my.cnf 只有一个,5.7 能识别 mysqlx=1 这种参数吗?不能。8.0 安装时写入的配置片段,5.7 的 mysqld 根本不认识,启动时直接报 unknown variable 'mysqlx=1',然后退出。这种情况的表现也是服务启动失败,而不是消失。
第四种是 端口或 socket 冲突。两个版本都默认监听 3306 端口、默认使用 /var/lib/mysql/mysql.sock 或 /tmp/mysql.sock 作为 socket 文件。后启动的那个会因为端口被占用或 socket 文件被占用而失败。如果 systemd 服务配置了 Restart=on-failure,系统会反复尝试重启,最终触发 StartLimitBurst 限制,systemd 干脆放弃,服务状态变成 failed 或 inactive (dead),看起来就像“彻底没了”。
还有一个容易被忽略的点:如果用户手工把某个服务执行了 systemctl mask,这个服务会在 list-unit-files 里显示为 masked,相当于被“软禁用”,任何启动命令都会被忽略,表面上也像“消失”。所以排查时不要只看 systemctl status,要配合 systemctl list-unit-files 一起看。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
