ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RHEL 8 安装 MySQL 9.1 完整指南:Yum仓库与模块冲突避坑

RHEL 8 安装 MySQL 9.1 完整指南:Yum仓库与模块冲突避坑

直接说结论:想在 RedHat 8 上装 MySQL 9.1,最省心的路子是用官方 Yum 仓库装 RPM 包,而不是自己去源码编译或者下二进制包硬解。官方仓库会帮你解决依赖、服务脚本、SELinux 上下文这些乱七八糟的事,把坑提前填掉大半。这篇文章就专门捋一捋 RHEL 8 装 MySQL 9.1 的完整流程,包括仓库配置、模块冲突处理、初始化、改密码、加固,还有我实测过程中踩过的几个坑,按步骤照做就行。

1. 动手前的关键认知:先搞清楚 9.1 是什么版本

开始敲命令之前,有几件事必须先说清楚。MySQL 的版本号策略在 8.0 之后变过一次,现在分两条线:一条是 LTS 长期支持版(比如 8.4),另一条是 Innovation 创新版(9.x 系列)。MySQL 9.1 属于 Innovation 版,意味着它更侧重新功能快速迭代,不是那种给你放在生产环境里跑五年的保守选择。如果你是想在测试环境、开发环境体验新特性,或者正好有需求用到 9.x 才有的功能,那装它没问题;如果是要上生产,我个人建议你再斟酌一下,毕竟 LTS 版的支持周期和稳定性预期完全不一样。

另外注意一个很现实的点:RHEL 8 自带的 AppStream 仓库里,MySQL 模块默认提供的版本是 8.0,而不是 9.1。直接dnf install mysql-server装出来的是 8.0,不是你要的 9.1。这就是为什么必须单独配置 MySQL 官方仓库的原因。

还有一个容易忽略但非常关键的细节:MySQL 9.x 系列移除了mysql_native_password认证插件。默认认证插件是caching_sha2_password。这意味着如果你有老版本客户端、老语言驱动还在用原生密码认证,连 9.1 会直接报错。这个我后面会在常见问题部分展开说,但你现在最好心里有数,别到时候连不上就开始怀疑安装过程出问题了。

2. 环境准备:确认系统版本、架构和基础依赖

2.1 确认操作系统版本

RedHat 8 这个说法其实涵盖了一批兄弟系统,包括 RHEL 8.x、CentOS 8、AlmaLinux 8、Rocky Linux 8。它们在兼容层面基本一致,以下步骤都能用。先确认一下你的系统版本:

cat /etc/redhat-release

比如输出Red Hat Enterprise Linux release 8.10 (Ootpa),那就说明是 RHEL 8.10,可以用接下来的所有操作。理论上 8.x 全系列都没问题,但我实测比较多的是 8.8 和 8.10,如果你用的是更老的 8.0、8.1,建议先把系统更新到比较新的小版本再操作,省得碰到一些莫名的依赖兼容问题。

2.2 确认硬件架构

MySQL 官方仓库的 RPM 包是按照架构分目录存放的。x86_64 是最常见的,但如果你用的是 ARM 架构(比如华为鲲鹏服务器),仓库 URL 里的el8后面还要带架构标识。命令如下:

uname -m

x86_64 就按本文走,如果是 aarch64,记得把后面的仓库 URL 里的路径从x86_64换成aarch64,或者干脆用官方提供的自动配置 RPM,它会自动探测架构,省去手动改 URL 的麻烦。

2.3 搞定基础依赖包

建议先把系统里已有的软件包更新到一致状态,避免安装过程中依赖解析出问题:

dnf update -y dnf install -y wget

wget 只是用来下载官方源配置包的,如果你更习惯用 curl,也没问题,二选一即可。这里不推荐手动去编辑 repo 文件还有一个原因是:MySQL 官方提供的mysql91-community-release这个 RPM 包会自动帮你把仓库文件写到/etc/yum.repos.d/下,并且把 GPG 密钥也一并导入,比手写 repo 文件要省事且不容易出错。

3. 配置 MySQL 官方 Yum 仓库:这一步藏着最大的坑

3.1 下载并安装官方仓库配置包

在写这篇文章时,MySQL 9.1 对应的官方仓库配置包是mysql91-community-release-el8系列。不要想当然地找mysql-community-release,因为官方现在已经按照大版本号拆分了相关配置包。直接执行:

wget https://dev.mysql.com/get/mysql91-community-release-el8-1.noarch.rpm rpm -ivh mysql91-community-release-el8-1.noarch.rpm

装完之后可以用下面命令验证仓库是否生效:

dnf repolist | grep mysql

正常情况下你应该能看到mysql91-community和mysql91-connectors-community、mysql91-tools-community这些仓库。如果这里看不到,后续安装必挂,别往下走,先排查网络或者仓库文件路径。

3.2 处理 AppStream 模块冲突:RHEL 8 特有的坑

这是 RHEL 8 系列安装 MySQL 9.1 时最常见的坑,没有之一。RHEL 8 的 AppStream 仓库自带了一个mysql模块,默认版本是 8.0。如果你装完官方仓库之后直接dnf install mysql-community-server,系统可能会纠结到底从哪个仓库装,很有可能会把依赖解析到 AppStream 自带的 MySQL 8.0 上,装出来根本不是 9.1。

解决办法是先把 AppStream 自带的 mysql 模块禁用掉:

dnf module disable mysql -y

这一步非常关键。禁用模块之后,dnf在解析 mysql 相关包时,就只能从我们刚配置的 MySQL 官方仓库去找,这样才能准确安装 9.1 系列。顺便说一句,如果将来某天你想用回系统自带的 MySQL 8.0,可以再执行dnf module reset mysql把它启用回来。

3.3 验证仓库优先级

万一你的系统上还有 EPEL 或者其他第三方仓库,理论上存在包冲突的可能。虽然我实测过程中很少遇到,但稳妥起见,装完官方仓库后可以查一下优先级:

dnf repolist --priority

如果发现第三方仓库的 priority 比官方仓库更小(数字越小优先级越高),建议在/etc/yum.repos.d/mysql91-community.repo的[mysql91-community]段落末尾加上priority=1,确保优先从官方源拉取。这个属于锦上添花的操作,大部分默认配置下不弄也能正常装。

4. 安装 MySQL 9.1:一步步实操全过程

4.1 安装 mysql-community-server 包

仓库配好之后,安装就是一条命令的活:

dnf install -y mysql-community-server

这一步会拉取mysql-community-server、mysql-community-client、mysql-community-libs、mysql-community-icu-data-files等一堆依赖包。9.1 的安装包体积比 8.0 略大,如果网速一般可能需要等一会儿。装完之后验证版本:

mysql --version

如果你看到mysql Ver 9.1.0 for Linux on x86_64,说明客户端部分已经装好。服务端版本可以用下面的命令确认:

mysqld --version

正常会输出类似/usr/sbin/mysqld Ver 9.1.0 for Linux on x86_64。

4.2 理解数据目录和配置文件布局

RHEL 8 上通过 RPM 安装 MySQL 之后,目录结构是固定的,这点需要提前知道:

  • 配置文件主目录:/etc/my.cnf
  • 配置文件分段目录:/etc/my.cnf.d/
  • 数据目录:/var/lib/mysql/
  • 日志目录:/var/log/mysqld.log
  • 错误日志:默认写入/var/log/mysqld.log
  • socket 文件:/var/lib/mysql/mysql.sock
  • PID 文件:/var/run/mysqld/mysqld.pid

这些路径后面排查问题会频繁用到,先记下来。配置文件默认会读取/etc/my.cnf,然后 include 掉/etc/my.cnf.d/下所有.cnf结尾的文件。也就是说,你后面想自定义配置,最佳实践是在/etc/my.cnf.d/下新建一个独立配置文件,而不是直接改/etc/my.cnf,这样方便管理和回滚。

4.3 初始化数据目录

这里有个好消息:RHEL 8 上通过 RPM 安装的 MySQL 9.1,首次启动时数据目录会自动初始化,不像 5.7 时代需要手动跑mysqld --initialize。但这不代表你什么都不用管。启动前建议先看一眼数据目录权限:

ls -ld /var/lib/mysql

默认属主应该是mysql:mysql。如果不是,手动改一下:

chown -R mysql:mysql /var/lib/mysql

如果不改权限直接启动,十有八九会因为无法创建临时文件或者写入数据字典而启动失败。这个坑很隐蔽,因为很多教程压根不会提。

4.4 首次启动:用 systemd 管理服务

启动服务:

systemctl start mysqld

查启动状态:

systemctl status mysqld

如果一切正常,你会看到active (running)。然后设置开机自启:

systemctl enable mysqld

启动完成之后,立刻验证一下端口是否在监听:

ss -lntp | grep 3306

注意:MySQL 默认监听的是3306端口,只有本地回环地址127.0.0.1和::1。这个默认行为在安全上是对的,后面如果需要远程连接再单独配置,别一上来就图省事改 bind-address 绑到0.0.0.0,后面加固部分我会细说。

5. 首次登录与安全加固:绕过临时密码和权限设置

5.1 拿到临时密码

9.1 和 8.0 一样,首次启动后 MySQL 会为 root 用户生成一个临时密码,写在错误日志里。不用到处找,就一条命令的事:

grep -i 'temporary password' /var/log/mysqld.log

输出会类似这样:

[Note] [MY-010454] A temporary password is generated for root@localhost: abc123DEFgh

拿着冒号后面的字符串去登录:

mysql -uroot -p

输入临时密码进入 MySQL 命令行,然后立刻修改 root 密码。必须强调:不要问能不能不改临时密码直接用,不可能。MySQL 9.1 的密码策略默认等级是MEDIUM,要求密码至少 8 位、包含大小写字母、数字和特殊字符,你如果设了一个简单密码,它会直接给你报错弹回来。

修改密码的 SQL 如下:

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '你的新密码'; FLUSH PRIVILEGES;

这里指定了caching_sha2_password认证插件,因为这是 9.x 的默认认证方式,显式写出来可以避免某些客户端因为默认插件不明确而连接失败。FLUSH PRIVILEGES是为了确保权限表重新加载,虽然ALTER USER通常不需要它,但多一步不亏。

5.2 跑一遍安全加固脚本

MySQL 官方其实更推荐你手动执行几条关键的加固 SQL,而不是盲目信任交互式脚本。但mysql_secure_installation这个工具依然有价值,适合快速处理几件事:移除匿名用户、禁用 root 远程登录、删除 test 数据库、清理权限表。在 RHEL 8 上直接运行:

mysql_secure_installation

它会让你输入 root 密码,然后依次问几个问题。我的建议是:

  • 是否设置密码验证强度插件(VALIDATE PASSWORD COMPONENT):如果你对密码策略没特殊要求,可以选 No,因为 9.1 默认就已经启用了密码验证组件,这块后面想改再单独配。
  • 是否移除匿名用户:选 Yes,必选。
  • 是否禁止 root 远程登录:选 Yes,必选。生产环境 root 只能本机登录,远程连接要用专门建的业务账号。
  • 是否删除 test 数据库:选 Yes。
  • 是否重新加载权限表:选 Yes。

跑完之后,MySQL 的基础安全水位就上来了。

5.3 新建业务账号并授权

root 只保留给本地运维用,业务连接必须用独立账号,这是铁律。创建账号的姿势如下:

CREATE USER 'appuser'@'192.168.1.%' IDENTIFIED BY '强密码'; GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'appuser'@'192.168.1.%'; FLUSH PRIVILEGES;

有几个细节需要特别提醒:

  • @'192.168.1.%'限定了来源 IP 网段,只允许从这个网段连接,别写'%'裸奔。
  • 权限原则是最小化,应用账号需要哪些权限就给哪些权限,不要动不动就GRANT ALL。
  • 如果业务需要远程连接,记得确认 MySQL 的bind-address配置。默认监听的地址只有127.0.0.1,外部连接会被直接拒绝。修改方式是在/etc/my.cnf.d/下新建一个bind.cnf:
[mysqld] bind-address = 0.0.0.0

改完重启服务:

systemctl restart mysqld

但这里有个连锁反应:绑定了0.0.0.0之后,还要检查系统的 firewalld 是否放行了 3306 端口:

firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload

不想对外网开放的话,可以指定具体内网网卡 IP 而不是0.0.0.0,比如bind-address = 192.168.1.10,这样只在公司内网可用,更安全。

6. 常见问题与排查技巧实录

6.1 问题速查表

先给出一张我在多次安装中总结的速查表,建议截图收藏。

症状常见原因解决办法
dnf install报Unable to find a match: mysql-community-servermysql 模块未禁用或官方仓库未生效执行dnf module disable mysql -y,用dnf repolist确认官方仓库存在
启动失败,日志报Can't create/write to file '/var/run/mysqld/mysqld.pid'/var/run/mysqld目录权限不对chown mysql:mysql /var/run/mysqld
启动失败,日志报[ERROR] [MY-010134] ... failed to initialize数据目录属主不是 mysql 或磁盘空间不足检查磁盘df -h,执行chown -R mysql:mysql /var/lib/mysql
连接时报Access denied for user 'root'@'localhost'密码错误或者用了旧认证插件确认临时密码,或通过 skip-grant-tables 模式紧急重置,见下文
报Authentication plugin 'mysql_native_password' cannot be loaded客户端驱动太老,不支持 9.x 的默认认证升级客户端驱动,或把用户改成caching_sha2_password
远程连接超时或者被拒firewalld 未放行 3306 或 bind-address 仅限本地firewall-cmd --add-port=3306/tcp,配置 bind-address
systemctl start卡很久,最后超时数据目录初始化耗时太久,或者系统熵不足耐心等待,查看日志,必要时手动执行mysqld --initialize

6.2 详细排错实践:忘了 root 密码怎么办

这个场景我遇到不止一次了,属于 Docker 和物理机部署都容易踩的坑。你不小心把临时密码错过了,或者改完密码之后又忘了,而现在的密码策略又这么复杂,谁记谁头疼。解决方案是进入「跳过授权表」模式:

第一步,停止服务:

systemctl stop mysqld

第二步,以跳过授权表的方式启动:

mysqld --user=mysql --skip-grant-tables --skip-networking &

加上--skip-networking是为了防止在这个无认证状态下对外提供服务,这是底线安全操作。

第三步,另开一个终端进 MySQL:

mysql -uroot

第四步,重置密码前必须先刷新权限表,否则ALTER USER会报错:

FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '新强密码';

第五步,退出并杀进程,然后正常启动:

pkill mysqld systemctl start mysqld

这段操作我在 9.1 上实测过,完全可行。注意不要用UPDATE mysql.user SET authentication_string=...这种老办法,9.x 的权限表结构已经变了,直接ALTER USER更稳妥。

6.3 排查系统日志的正确姿势

MySQL 的日志路径是/var/log/mysqld.log,遇到启动失败先看这个文件,里面带着[ERROR]标记的才是真正关键的信息。日志滚动比较频繁,建议用grep -i 'error' /var/log/mysqld.log | tail -n 30来过滤,不然几百行日志翻得头疼。

如果连日志文件都没生成,那大概率是mysqld进程根本还没走到日志初始化那一步,这时候检查 SELinux:

getenforce

如果返回Enforcing,试试看:

setsebool -P mysql_connect_any 1

或者临时用setenforce 0来排除是不是 SELinux 拦截。实测下来,RHEL 8 的 SELinux 对 MySQL 默认策略还算友好,但如果数据目录放在了自定义路径(比如/data/mysql),就得手动设置上下文:

semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?" restorecon -Rv /data/mysql

这个操作最容易被人忽略,放在自定义路径时十有八九会踩中。

7. 安装后的性能与配置调优建议

7.1 基础参数调整

装好 MySQL 9.1 之后,默认配置其实偏向保守。如果你跑的不是小项目,建议至少调整几个核心参数。在/etc/my.cnf.d/下新建custom.cnf:

[mysqld] # 缓存表和线程相关 table_open_cache = 4096 thread_cache_size = 16 # InnoDB 缓冲池,建议设为物理内存的 60%-70% innodb_buffer_pool_size = 2G # 日志与刷盘策略 innodb_log_file_size = 512M innodb_flush_log_at_trx_commit = 2 # 连接数 max_connections = 300

innodb_buffer_pool_size是 InnoDB 存储引擎最核心的参数,很多查询性能不佳其实不是 SQL 写得差,而是缓冲池太小,数据频繁走磁盘。注意,这里改成 2G 只是示例,你要根据自己的机器内存来定。innodb_flush_log_at_trx_commit = 2是平衡性能和数据安全的一个值,纯测试环境也可以设成 0 追求更高写入性能,但只要不是丢得起数据的场景,建议用 2 或者默认的 1。

修改完配置之后:

systemctl restart mysqld

7.2 确认参数生效

不要以为改完配置就完事了,一定要回查实际生效的值:

SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'max_connections';

如果发现跟你设置的不一致,大概率是配置文件写错位置或者my.cnf里的includedir被注释掉了。回查参数这步是实操里最容易跳过、也最容易出问题的环节,建议养成习惯:改完配置重启服务之后先查一遍变量,再继续下一步。

8. 卸载与清理:备用技能

虽然这不是安装的正向流程,但我还是建议你了解一下,因为很多人装完发现版本不对或者装失败了,需要干净清理。卸载 MySQL 9.1 的正确姿势:

systemctl stop mysqld dnf remove -y mysql-community-server mysql-community-client mysql-community-libs mysql-community-common

如果想要连配置文件和数据目录一起清掉:

rm -rf /var/lib/mysql rm -rf /etc/my.cnf*

注意:数据目录删除不可逆,操作前要想清楚。仅卸载 RPM 包是不会自动删除数据目录的,这算是设计上的一种安全保护,不想要数据了再手动删。

最后说说我个人的体会:MySQL 9.1 在 RHEL 8 上的安装路径并不复杂,但每一步都需要对系统底层的包管理机制、模块流、SELinux 和目录权限有所理解。很多人装不上不是命令敲错,而是没理解模块禁用、仓库优先级、认证插件这些关键点的逻辑。按照这篇文章的步骤走一遍,装完基本就能稳稳跑起来,后面再根据需要慢慢调优就行。如果遇到文里没覆盖到的问题,建议先看/var/log/mysqld.log的[ERROR]段,再结合官方文档排查,别病急乱投医乱改配置。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进