ARTICLE DETAIL

资讯详情

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

CentOS下MySQL版本不匹配?彻底卸载与重装完整指南

CentOS下MySQL版本不匹配?彻底卸载与重装完整指南 我最早遇到MySQL“版本不匹配”这个报错是在一台CentOS 7.9的服务器上当时图省事直接从官网下载了最新的MySQL 8.0二进制包结果rpm安装时直接给我弹了一堆依赖错误说什么libaio版本不对、numactl缺失最后我硬是折腾到半夜才把环境恢复干净。后来帮同事排查发现十个人里有七八个都是同一个问题安装源太乱系统里同时残留着多个MySQL版本的信息或者干脆是下载的包和系统架构不匹配。这篇文章就是围绕这个问题写的核心解决三件事搞明白什么叫“版本不匹配”、把系统里残留的MySQL彻底卸干净、再安装一个和CentOS兼容的版本。无论你是刚入行的运维新手还是被测试环境折腾到崩溃的开发者只要按着下面的步骤走基本不会再踩我当年踩过的坑。1. 先搞懂“版本不匹配”到底是怎么回事1.1 系统与MySQL匹配的四个关键维度很多人一看到“版本不匹配”就开始盲目下载新版MySQL实际上这个词在CentOS场景下有四种完全不同的含义处理方式也截然不同。第一是操作系统发行版与MySQL官方的支持矩阵不匹配。MySQL官方对操作系统的支持是明确写进文档的比如CentOS 7官方推荐使用MySQL 5.7或8.0的特定小版本CentOS 8则对MySQL 8.0的支持更完善。如果你在CentOS 7上强行安装为CentOS 8编译的RPM包系统会直接拒绝因为RPM包内部的依赖关系无法满足。第二是硬件架构不匹配。这块最容易被忽视。我的一个朋友在ARM架构的服务器上装MySQL下载了x86_64的包安装时系统提示“wrong architecture”他还以为是包损坏了。CentOS 7对ARM架构aarch64的支持和x86_64包完全不同源弄混了直接白折腾一小时。用uname -m看一眼架构再对照下载页面的标识这个习惯非常重要。第三是软件依赖不匹配。MySQL运行时依赖libaio、libncurses、perl等基础库CentOS 7 minimal版默认不会装全这些依赖。很多人直接rpm -ivh mysql-community-server.rpm结果报错说依赖缺失就误以为“版本不匹配”其实是没装依赖包。第四才是大家最常遇到的系统里残留的旧版本MySQL与新版安装包冲突。我之前用yum装过一次MySQL 5.6后来想升级到5.7没有先卸载旧的直接安装新的RPM包系统提示“file /usr/bin/mysql already exists”这不就是版本冲突吗在Linux里同一套软件的不同版本很难共存尤其是MySQL这种涉及系统服务、数据目录、配置文件的软件。怎么判断你遇到的是哪一种最简单的办法把完整的报错信息贴到搜索引擎里不要自己猜。rpm -ivh报错和yum install报错、service mysql start报错的排查方向完全不一样。1.2 为什么“不能直接覆盖安装”我见过太多人试图在现有MySQL之上直接覆盖安装新版本这种做法在Windows上勉强可以但在Linux上会引发一系列连锁反应。先说说数据目录的兼容性。MySQL 5.7和8.0的数据目录结构差异很大8.0引入了数据字典不再以.frm文件存储表结构直接覆盖安装会导致数据目录无法识别。就算从5.7升到5.7的小版本也可能因为系统表结构升级导致无法启动。我见过最惨烈的案例是有人直接从5.6跳到8.0启动时直接报“Table mysql.user doesnt exist”因为5.6的权限表结构和8.0要求的完全不一样。再说配置文件覆盖问题。/etc/my.cnf里包含了大量参数新旧版本对参数的支持程度不同。8.0对某些旧参数直接报“unknown variable”服务根本起不来。覆盖安装时yum或rpm默认不会覆盖你手改过的配置文件而是生成.rpmnew文件这种新旧配置并存的混乱状态排查起来比卸载重装麻烦十倍。最后是服务管理器的冲突。CentOS 7用的是systemdMySQL安装包会注册mysqld.service服务。如果你先装了5.7再装8.0服务文件会被覆盖或混淆systemctl start mysqld启动的可能是旧版本残留的启动脚本也可能指向新的可执行文件但调用旧的配置文件。这种状态我在生产环境遇到过日志文件里既有5.7的启动记录又有8.0的进程信息查起来非常崩溃。所以我的结论非常明确在CentOS上从旧版本迁移到新版本唯一稳妥的路径是“先完整卸载再全新安装”。数据可以通过逻辑备份mysqldump导出重建后再导入虽然耗时但绝对不坑。下面我按这个逻辑把步骤拆开讲。2. 卸载前的准备工作别急着动手2.1 摸清系统里现在有什么卸载的第一步不是直接删包而是先搞清楚系统里到底装了哪些MySQL相关的组件。用下面这几个命令逐一排查# 查看已安装的MySQL相关RPM包 rpm -qa | grep -i mysql # 查看MySQL相关的系统服务 systemctl list-unit-files | grep -i mysql # 查看MySQL进程是否在运行 ps -ef | grep mysql # 查看MySQL端口占用情况 ss -tlnp | grep 3306这一步的作用是建立“卸载清单”。我见过有人在没看清的情况下直接删了mysql-community-common结果mysql-community-server还在启动时发现命令都没了又得重新下载依赖包纯粹是自找麻烦。把rpm -qa的输出记下来这就是你系统里的MySQL全家桶。常见的包括mysql-community-server、mysql-community-client、mysql-community-common、mysql-community-libs、mysql-community-libs-compat。这几个包有严格的依赖关系卸载时必须按照server → client → libs → common的顺序或者直接用yum remove一键处理让yum自动解决依赖顺序。同时如果之前是用源码编译安装的MySQLrpm命令查不到但/usr/local/mysql目录可能存在。这种情况在卸载时要把手动编译的安装目录也纳入清理范围。2.2 数据备份卸载之前必须做的事这一步很多人跳过了但我强烈建议你保留。哪怕只是测试环境MySQL里也可能有某个临时项目的建表语句丢了重新写一遍也是浪费时间。最稳妥的备份方式是mysqldump逻辑备份它生成的是SQL文本文件不依赖MySQL的具体版本恢复时兼容性最好# 导出所有数据库 mysqldump -uroot -p --all-databases --single-transaction all_databases.sql # 如果只想导出特定库 mysqldump -uroot -p --single-transaction mydb mydb.sql--single-transaction参数很关键它基于InnoDB的事务特性生成一致性快照备份过程中不会锁表对正在运行的服务影响很小。如果是MyISAM表单事务不适用可以改用--lock-all-tables但测试环境下直接锁表也无所谓。备份文件建议复制到系统盘以外的位置比如/home目录避免卸载时误删。我在实际操作中习惯再压缩一份gzip all_databases.sql体积能缩小到原来的五分之一传送到其他机器也更方便。另外记住数据文件的位置默认是/var/lib/mysql。卸载时yum remove不会自动删除这个目录需要手动清理这一点后面详细说。3. MySQL完整的卸载流程3.1 停止服务与关闭开机自启卸载的第一步永远是停止服务不是删除软件包。直接强制卸载正在运行的软件包会导致进程成为孤儿进程占用数据库文件句柄后面想删除文件目录时会报“Text file busy”。# 查看MySQL服务状态 systemctl status mysqld # 停止MySQL服务 systemctl stop mysqld # 禁用开机自启防止残留服务文件导致重启后又起来 systemctl disable mysqld这里有个小坑systemctl stop mysqld执行后最好再用ps -ef | grep mysql确认一下进程真的没了。因为mysqld有时会fork出多个线程正常停止需要几秒钟如果超过10秒没结束可以视为异常卡死用kill -9强制结束。但注意kill -9是大杀器只适合确认要卸载的场景使用正常运维时这招要慎用。关闭开机自启的意义在于CentOS 7的systemd会在/usr/lib/systemd/system/目录下注册服务文件即使软件包被卸载服务文件有时也会残留。如果不开这个disable重装MySQL后可能遇到诡异的问题新的服务实例还没启动旧的残留脚本已经在尝试拉起旧版本路径了。3.2 卸载软件包的三种方式和选型逻辑卸载软件包我见过三种做法按推荐程度排序分别是yum remove、rpm -e、手动删除文件。第一种也是我最推荐的yum自动依赖清理。yum remove -y mysql-community-server mysql-community-client mysql-community-common mysql-community-libs mysql-community-libs-compat直接一把梭把所有MySQL相关包一口气卸掉。yum会自行解析依赖顺序先卸载依赖方再卸载被依赖方整个过程干净利落。如果记不全包名可以简化为yum remove -y $(rpm -qa | grep mysql)这个写法会先把rpm输出的所有mysql相关包名作为参数传入yum remove亲测有效。但缺点是如果输出为空yum会报“No Match for argument”这时说明系统里没装rpm格式的MySQL不需要走这一步。第二种rpm -e 逐个卸载。适合你对依赖关系非常了解或者yum源出问题无法联网的情况。顺序必须严格遵守server最后卸或最先卸都行关键是libs必须在server和client之后卸。直接rpm -e mysql-community-libs而server还在会报“libmysqlclient.so.18 is needed by mysql-community-server”很常见的错。第三种手动删除文件。这种方式不推荐除非是源码编译安装的MySQL。rpm卸载后会在系统里留下大量散落文件手动删不干净后面排查问题很容易被误导。源码编译的MySQL倒是可以手动删因为它的文件都集中在/usr/local/mysql目录里删除起来反而干净。3.3 清理残留文件和数据目录这是整个卸载过程中最容易翻车的地方。yum remove只删除软件包安装的文件但MySQL运行时生成的数据、日志、配置文件、socket文件全部不在管理范围内。需要清理的路径归纳如下路径内容是否需要清理/var/lib/mysql数据目录包含所有数据库文件按需清理。如果以后不用旧数据必须删想保留数据先备份再删/etc/my.cnf主配置文件建议删除避免残留配置项干扰新版本启动/etc/my.cnf.d/配置目录建议删除里面可能有自定义配置/var/log/mysqld.log日志文件建议删除或清空避免旧日志干扰排查/tmp/mysql.socksocket文件必须删除残留socket会导致新实例启动失败/var/run/mysqld/PID文件和目录必须删除残留PID会导致systemctl误判手动执行清理命令rm -rf /var/lib/mysql rm -rf /etc/my.cnf rm -rf /etc/my.cnf.d rm -rf /var/log/mysqld.log rm -f /tmp/mysql.sock rm -rf /var/run/mysqld对于/var/lib/mysql我额外强调一点删除之前务必再确认一次备份真的存在并且能读取。我见过有人备份完忘了把备份文件复制出来直接全盘清理备份和原数据一起没了连哭都找不到地方哭。3.4 验证卸载结果确保系统已完全“忘记”MySQL卸载完了别急着安装新版本。花两分钟验证一下系统是否已经被清理干净这是最容易被跳过但最有价值的一步。# 确认没有MySQL相关rpm包 rpm -qa | grep mysql # 确认没有MySQL相关进程 ps -ef | grep mysql # 确认服务列表中不存在mysqld systemctl list-unit-files | grep mysql # 确认3306端口已释放 ss -tlnp | grep 3306这四个查询全部无输出说明系统已经“忘记”了MySQL的存在这时候安装新版本才是安全的。如果还有某个包残留回到3.2节把残留的包名加入卸载命令继续清理。验证还有一个好处避免新装时报“conflicts with file from package mysql-community-server”这类错误。这类错误不是因为版本不匹配纯粹是旧文件没删干净但新安装总是被误判为“版本不匹配”耽误排查时间。4. 重新安装这次一定装对4.1 选择安装方式yum源安装 vs rpm安装Uninstall流程走完后重装时最关键的是选对安装方式。我在标题里强调过“版本不匹配”这个核心痛点而很多版本不匹配问题在安装方式选择这一步就已经决定了。主流的安装方式有三种我来逐一说下优劣第一种配置MySQL官方Yum源安装。这是最推荐的方式。MySQL官方提供了rpm格式的源安装包装上之后yum就能直接安装MySQL自动解决依赖问题。CentOS 7上配置源只需要一条命令rpm -Uvh https://repo.mysql.com/mysql80-community-release-el7-7.rpm这个包里面带了多个repo配置默认启用的是MySQL 8.0的源。如果要装5.7需要手动禁用8.0源、启用5.7源用yum install前先执行yum-config-manager --disable mysql80-community yum-config-manager --enable mysql57-community这个方式的优势是依赖自动解决、升级方便后续yum update mysql-server就能小版本升级。劣势是官方源在国内访问速度有时不够理想耐心等待即可。第二种直接下载rpm包安装。适合离线环境或者对版本有精确要求。去MySQL官网下载页面选择对应系统版本和架构的RPM Bundle包解压后获得一系列rpm文件然后rpm -ivh mysql-community-common-*.rpm rpm -ivh mysql-community-libs-*.rpm rpm -ivh mysql-community-client-*.rpm rpm -ivh mysql-community-server-*.rpm顺序不能乱因为libs依赖于commonclient和server都依赖于libs。这种方式在下载时需要严格核对系统版本el7对应CentOS 7el8对应CentOS 8x86_64对应Intel/AMD架构aarch64对应ARM架构。搞错任何一个标签都会在安装时报“版本不匹配”把新建的系统搞得一团糟。第三种通用二进制包Generic Linux解压安装。这种适合指定数据目录、指定安装路径的定制化场景。把官方提供的tar包解压到/usr/local/mysql然后手动初始化。这种方式的灵活性最高但配置步骤多后续维护需要自己处理systemd服务文件对新手不太友好这里先不展开。4.2 安装MySQL 5.7.x的完整示例既然标题提到“版本不匹配”我以CentOS 7 MySQL 5.7.445.7系列的最后一个版本为例给出完整安装流程。选择5.7的原因是虽然8.0已经非常成熟但很多企业内部的老项目仍然停留在5.7而且5.7与CentOS 7的兼容性极佳几乎没有依赖坑。# 第一步配置MySQL官方yum源 rpm -Uvh https://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm # 第二步导入GPG公钥如果yum报公钥错误 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 # 第三步安装MySQL服务端 yum install -y mysql-community-server这个过程中yum会自动安装mysql-community-client、mysql-community-common、mysql-community-libs等依赖组件不需要手动逐个安装。如果中间报“Could not resolve host: repo.mysql.com”说明网络DNS有问题可以尝试临时更换为国内镜像源或者使用第二种rpm包离线安装。安装完成后启动服务并设置开机自启systemctl start mysqld systemctl enable mysqld systemctl status mysqld4.3 初始化与首次登录5.7和8.0的密码获取差异这里有一个CentOS上MySQL首次安装最常见的坑初始密码在哪里看MySQL 5.7和8.0安装完成后都会自动生成一个临时root密码记录在/var/log/mysqld.log日志中。用下面命令查看grep temporary password /var/log/mysqld.log输出的末尾那一串字符就是临时密码形如rootlocalhost: xxxxxxxx。首次登录后用ALTER USER修改密码mysql -uroot -p # 输入临时密码登录后执行 ALTER USER rootlocalhost IDENTIFIED BY New-Passwd-2024!; FLUSH PRIVILEGES;8.0的密码策略默认是中等强度要求至少8位且包含大小写字母、数字和特殊字符。5.7的密码策略相对宽松但也不建议设置弱密码。如果密码修改时提示“ERROR 1819 (HY000): Your password does not satisfy the current policy requirements”说明密码强度不够换一个更复杂的密码即可。如果/var/log/mysqld.log里找不到临时密码一种可能是日志权限问题导致未能写入另一种可能是数据目录里有了旧的初始化痕迹。碰到这种情况可以手动删除数据目录然后重新初始化rm -rf /var/lib/mysql/* mysqld --initialize --usermysql初始化完成后再次查看日志文件获取临时密码。5. 重装过程中常见的深水区问题5.1 “版本不匹配”最常见的五个场景和解决方案重装过程中遇到的“版本不匹配”大多数不是指MySQL和CentOS官方不兼容而是以下几种情况。我把它们整理成一个速查表场景报错特征根因解决方案安装包架构不对wrong architecture下载了x86_64包装在aarch64系统上用uname -m确认架构重新下载对应包依赖缺失libaio.so.1 not found系统缺少MySQL运行依赖库yum install -y libaio numactl-libs后重装旧文件冲突conflicts with file from package系统残留旧版MySQL文件回到第3章完整卸载清理后再装GPG公钥异常public key not available官方源key未导入rpm --import导入官方GPG keyglibc版本过低/lib64/libc.so.6: version GLIBC_2.28 not found新版MySQL要求更高版本glibc使用与CentOS 7匹配的MySQL 5.7或8.0.xx老版本重点说说glibc这个问题。CentOS 7默认的glibc版本是2.17而MySQL 8.0.21之后的部分版本开始要求glibc 2.28以上。这就导致一个很尴尬的局面你在CentOS 7上尝试安装最新版的MySQL 8.0.36系统直接报兼容性错误。这不是系统坏了也不是包损坏纯粹是操作系统基础库太老。解决思路有两个一是选用与CentOS 7官方兼容的MySQL 5.7或MySQL 8.0.20及更早的版本二是升级操作系统到CentOS 8或迁移到其他发行版。生产环境显然选前者测试环境想尝鲜可以选后者。5.2 远程连接不上防火墙与授权问题在CentOS上装好MySQL后新用户最典型的困惑是本机能登录但远程工具Navicat、DBeaver连接时直接“Access denied”或“Cant connect”。这里有两道关卡要过。第一道防火墙。CentOS 7默认使用firewalld3306端口默认不对公网开放。firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload如果不想用firewalld直接用iptables也可以但我建议统一用firewalld管理避免规则互相覆盖。第二道MySQL用户授权。root用户默认只允许从localhost登录需要单独创建远程用户或授权root远程访问。我一般推荐创建专用用户降低安全风险CREATE USER appuser% IDENTIFIED BY App-Passwd-2024!; GRANT ALL PRIVILEGES ON *.* TO appuser%; FLUSH PRIVILEGES;%表示允许从任意主机连接。有条件的话更安全的做法是精确到IPappuser192.168.1.%只允许内网网段访问。5.3 字符集不一致导致的“数据乱码”重装完成后还有一个高频问题就是字符集。CentOS系统的默认字符集是UTF-8但MySQL 5.7默认的字符集和排序规则跟上时代的方式不太一样启动后直接写入中文数据可能出现乱码。建议在/etc/my.cnf的[mysqld]段加上以下配置character-set-server utf8mb4 collation-server utf8mb4_general_ciutf8mb4是UTF-8的超集支持四字节的emoji表情和生僻字。utf8mb4_general_ci是通用的排序规则兼容性最好。如果需要的业务场景涉及多种语言的排序可以考虑utf8mb4_unicode_ci但性能上稍逊一点非特殊场景优先选general。修改配置后需要重启MySQL才能生效systemctl restart mysqld。已经创建的数据库和表的字符集不会自动修改需要手动调整ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;注意第二种写法转换的是整张表的字符集表中的数据会一并转码期间表会短暂锁定线上环境要注意窗口期。6. 问题排查速查表从卸载到重装的完整避坑指南6.1 常见问题排查实录结合我自己的实操经验把从卸载到重装过程中的高频问题整理如下问题现象可能原因排查命令/方法解决方案卸载时报“libmysqlclient.so.18 is needed by...”卸载顺序错误rpm -qa | grep mysql先卸载server和client再卸载libs清理后系统命令mysql不存在卸载不完整或PATH未更新which mysql确认所有rpm包已卸载重装时自然会装新命令新装MySQL启动失败日志报“Cant open the mysql.plugin table”数据目录有旧版本残留ls -la /var/lib/mysql删除/var/lib/mysql下所有内容后重新初始化修改密码报“ERROR 1819”密码强度不够无使用大小写字母数字特殊字符组合不少于8位远程连接超时防火墙未放通firewall-cmd --list-ports放通3306端口并reload远程连接报“Access denied”用户未授权远程访问SELECT User, Host FROM mysql.user;创建带%或特定IP的授权用户忘记密码无法登录密码丢失无使用skip-grant-tables模式重置密码见下文安装报“Public key for mysql-community-server... not found”GPG公钥未导入rpm -qa gpg-pubkey导入官方GPG key6.2 忘记root密码的应急处理还有一个非常实用的技巧就是在卸载重装之间如果遇到忘记密码的情况没必要再卸载一遍。用skip-grant-tables方式可以临时绕过权限验证# 在/etc/my.cnf的[mysqld]段添加 skip-grant-tables # 重启服务 systemctl restart mysqld # 无密码登录 mysql -uroot # 修改密码MySQL 5.7 UPDATE mysql.user SET authentication_string PASSWORD(New-Passwd-2024!) WHERE User root; FLUSH PRIVILEGES; # 修改密码MySQL 8.0 ALTER USER rootlocalhost IDENTIFIED BY New-Passwd-2024!; FLUSH PRIVILEGES;用完务必从配置文件里删掉skip-grant-tables这行再重启服务否则MySQL会一直处于“不验证密码”的危险状态任何拿到服务器权限的人都能直接登录数据库。6.3 重装后的安全加固建议既然费了这么大劲把MySQL重装了一遍趁这个机会把最基本的安全配置做一遍是值得的。首先是修改root密码的同时创建一个日常使用的低权限账号。生产环境不要拿root连接业务这是个习惯问题。其次是删除匿名账号和空密码账号DELETE FROM mysql.user WHERE User; DELETE FROM mysql.user WHERE authentication_string; FLUSH PRIVILEGES;再处理一下默认数据库测试用的test库如果不需要直接删掉即可。最后是日志文件的配置。MySQL默认只记录错误日志不记录慢查询日志。对开发测试环境来说开启通用日志可以排查SQL问题但生产环境开通用日志会导致IO开销暴涨一般不推荐。慢查询日志可以打开设置阈值1秒后续调优SQL时非常有用。6.4 几个提升效率的小工具和习惯在重装MySQL时顺手把日常运维要用的小工具都装齐可以减少很多后续折腾mycli一个带自动补全和语法高亮的MySQL命令行客户端比自带mysql客户端好用太多pip install mycli即可安装。percona-toolkitPercona提供的一套MySQL运维工具包包含pt-query-digest慢查询分析、pt-table-checksum数据一致性校验等神兵利器。dbeaver免费的通用数据库管理工具界面比Navicat清爽支持MySQL、PostgreSQL等多种数据库。mysqldumper一个基于Perl的并行逻辑备份工具比mysqldump的导出速度在数据量大时能快不少。当然工具只是辅助最重要的还是理解MySQL的运行机制和常见的目录结构。把这些基础夯实了任何版本、任何系统的MySQL环境都能游刃有余。我在实际运维中最大的体会是所谓的“版本不匹配”问题十有八九不是真的不匹配而是安装方式、依赖关系、残留文件没有处理好。只要你把卸载做得足够彻底把安装源选对CentOS上装MySQL其实是一个非常顺畅的过程。下次再遇到安装失败先别急着换版本耐心走一遍文中的检查和清理流程大部分问题都能迎刃而解。
返回列表