1. 为什么过了这么多年还要在ARM64架构上装MySQL5.7
1.1 存量业务迁移是最大的现实需求
如果你最近在做ARM服务器迁移,大概率会遇到和我一样的问题:一台基于aarch64架构的CentOS 7服务器,要装一套老项目依赖的MySQL 5.7。网上搜到的教程十个有九个都是x86_64平台的,照抄命令的结果往往不美丽。
最早我接到这个任务时,心里想的是"装个MySQL还不简单,yum一条命令的事"。等到实际操作才发现,ARM64环境下坑远比想象中多。老的业务系统跑在CentOS 7上,数据库从MySQL 5.6升级到5.7后就没再动过,应用层很多SQL写法都绑定了5.7的行为,比如默认的utf8mb4排序规则、子查询优化方式、分区表语法等。这种情况下,直接让业务切换到MySQL 8.0或PostgreSQL,代价非常大。
所以现实中最稳妥的方案就是:操作系统保持CentOS 7,数据库版本保持MySQL 5.7,只把底层硬件从x86_64换成ARM64。ARM服务器在云上的成本优势非常明显,不少团队都在往鲲鹏、飞腾、Ampere这类平台上迁移,于是"CentOS7安装MySQL5.7(ARM64)"就成了一个绕不开的硬需求。
1.2 ARM64下的MySQL支持到底怎么样
先说结论:Oracle官方早就提供了适配aarch64架构的MySQL 5.7软件包,所以技术上完全可行,但前提是你必须下载对应架构的包。
MySQL 5.7的官方下载页面里,Linux平台除了最常见的“Linux - Generic (glibc 2.12) (x86_64)”之外,还有“Linux - Generic (glibc 2.12) (ARM64)”以及适用于Red Hat Enterprise Linux 7的aarch64 RPM包。如果你不看清楚架构,把x86_64的rpm包传到ARM服务器上,rpm会直接报“Wrong architecture”,对应的tar包就算解压了也跑不起来。
ARM64在Linux内核里通常表示为aarch64,CentOS 7官方镜像对应的仓库在镜像站上也会有专门的“centos-altarch”目录。很多人配置yum源时直接把x86_64的源地址复制过去,导致后续安装依赖各种404或找不到包,这一块我会在第2章详细讲。
1.3 为什么版本要选5.7.44
MySQL 5.7的生命周期里,最后一个正式版本是5.7.44。新装环境我强烈建议直接选这个版本,不要选老的5.7.20或5.7.30之类。原因是5.7.44包含了多年的安全修复和稳定性补丁,尤其在ARM64架构上,后期版本对glibc和编译器兼容性的调整更多,踩坑概率明显更低。
另外,热词里很多人搜“mysql5.7下载”,说明找不到正确的下载渠道。官方软件包的下载路径是:
- MySQL Community Downloads页面,选择Product Version为5.7.44
- Operating System选择“Red Hat Enterprise Linux / Oracle Linux”
- OS Version选择“Red Hat Enterprise Linux 7”
- Architecture选择“ARM64”
这个组合下会同时出现RPM Bundle和Generic Linux tar包,两种方式我都会在后面详述。
2. 安装前的系统检查与仓库准备:先把“喂料”问题解决
2.1 确认架构和系统版本,别想当然
服务器到手以后,第一件事不是急着下载安装包,而是先确认系统基本信息。ARM64的环境下,uname -m会输出aarch64,但在某些基于KVM的虚拟机上也可能显示arm64,两者其实指同一个架构。建议用以下命令确认:
uname -m arch cat /etc/redhat-release cat /etc/os-release我在一台云主机上遇到过,系统release显示CentOS Linux release 7.9.2009 (AltArch),uname -m输出aarch64,这就确认是ARM64环境了。如果输出的是x86_64,那安装方式就完全不同,后续步骤也就不用按本文执行。
还需要检查内核版本和glibc版本。CentOS 7默认内核一般是3.10.0-1160,glibc是2.17,MySQL 5.7的Generic包要求glibc 2.12以上,所以满足条件。检查命令:
uname -r ldd --version这个检查特别重要。某些ARM开发板或定制系统虽然跑着CentOS 7,但内核和glibc被裁剪过,直接初始化MySQL很容易出现“libaio.so.1”找不到或“Fatal error: Please read Security section”之类的错误。
2.2 配置yum源:CentOS 7的源已经停了
CentOS 7已经停止维护,官方mirrorlist源早就不可用。如果不换源,接下来yum装任何依赖都会报404或Could not resolve host。网上热词里“centos7更换国内yum源”搜的人多,就是因为这个问题让很多人卡住了。
ARM64架构下,不能去配置x86_64的centos仓库,必须找AltArch仓库。以阿里云镜像为例,CentOS 7 ARM64的base仓库配置如下:
[base] name=CentOS-7 - Base - mirrors.aliyun.com baseurl=https://mirrors.aliyun.com/centos-altarch/7.9.2009/os/aarch64/ gpgcheck=0 enabled=1 [updates] name=CentOS-7 - Updates - mirrors.aliyun.com baseurl=https://mirrors.aliyun.com/centos-altarch/7.9.2009/updates/aarch64/ gpgcheck=0 enabled=1 [extras] name=CentOS-7 - Extras - mirrors.aliyun.com baseurl=https://mirrors.aliyun.com/centos-altarch/7.9.2009/extras/aarch64/ gpgcheck=0 enabled=1注意路径里是“centos-altarch”,而不是“centos”。这个细节非常容易踩坑。配置好后执行yum clean all && yum makecache验证可用性。如果还需要EPEL源,要下载aarch64版本的epel-release包,例如:
yum install -y https://mirrors.aliyun.com/epel/7/aarch64/epel-release-latest-7.noarch.rpm2.3 安装基础依赖
MySQL 5.7不管用RPM还是通用二进制包,都依赖一些基础库。在纯净的CentOS 7 ARM64上,我习惯先装下面这些:
yum -y install libaio numactl-libs openssl perl net-tools- libaio:MySQL进行AIO异步I/O操作的依赖,缺失的话mysqld启动直接报error while loading shared libraries
- numactl-libs:用于NUMA内存管理,ARM多核服务器上很关键
- openssl:MySQL 5.7的SSL连接功能依赖
- perl:部分初始化脚本和安全加固脚本需要
如果是离线内网环境,这些库可能要提前找好rpm包。优先从上面配好的AltArch仓库下载,注意rpm包架构必须是aarch64。这里提前做好,后面安装MySQL时能省掉大量临时去补依赖的时间。
3. 安装方式的选择:RPM、二进制包还是源码
3.1 方式一:官方RPM Bundle离线安装(最省事)
如果是在标准CentOS 7 ARM64环境,我最推荐的就是RPM Bundle方式。它把所有MySQL组件打成一个tar包,解压后按顺序安装即可。
下载时选择ARM64架构的“RPM Bundle”,文件大概是类似mysql-5.7.44-1.el7.aarch64.rpm-bundle.tar的文件。解压后能看到一系列aarch64的rpm包:
tar xvf mysql-5.7.44-1.el7.aarch64.rpm-bundle.tar在纯净系统上,建议按依赖顺序安装,不要一股脑用rpm -Uvh *.rpm,否则容易出现包冲突:
rpm -ivh mysql-community-common-5.7.44-1.el7.aarch64.rpm rpm -ivh mysql-community-libs-5.7.44-1.el7.aarch64.rpm rpm -ivh mysql-community-client-5.7.44-1.el7.aarch64.rpm rpm -ivh mysql-community-server-5.7.44-1.el7.aarch64.rpm如果某个rpm提示依赖缺失,比如缺perl或libaio,先yum装对应依赖,再重新执行。整个过程不需要额外配置yum源给MySQL官方源,因为官方源里MySQL 5.7的aarch64目录支持并不总是完整,离线RPM包是最可控的。
RPM方式装完后,mysqld的二进制在/usr/sbin/mysqld,数据目录默认是/var/lib/mysql,日志在/var/log/mysqld.log,systemd服务文件也已经生成好了。
3.2 方式二:通用二进制包解压安装(最灵活)
如果你希望把MySQL放到自定义路径,或者有多实例部署需求,通用二进制包更合适。下载“Linux - Generic (glibc 2.12) (ARM64)”的tar.gz文件,比如mysql-5.7.44-linux-glibc2.12-aarch64.tar.gz。
安装过程如下:
groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql tar xzf mysql-5.7.44-linux-glibc2.12-aarch64.tar.gz -C /usr/local/ ln -s /usr/local/mysql-5.7.44-linux-glibc2.12-aarch64 /usr/local/mysql mkdir -p /usr/local/mysql/data chown -R mysql:mysql /usr/local/mysql这里的用户mysql不需要登录shell,纯粹是进程权限用。二进制包方式的好处是,目录结构完全自己掌控,多套MySQL版本可以共存,升级时只要切软链接和版本目录名即可。缺点是需要自己管理systemd服务、日志轮转和配置文件,没有RPM那么“傻瓜化”。
我通常会把bin目录加入PATH或直接使用全路径操作,避免多个MySQL版本互相干扰:
export PATH=/usr/local/mysql/bin:$PATH3.3 方式三:源码编译(不推荐,但讲清原因)
网上有些教程让你从源码编译MySQL 5.7,在ARM64上这个体验真的不太好。MySQL 5.7源码依赖boost 1.59库,编译过程需要cmake、gcc-c++以及大量内存,往往一个编译任务跑下来要一两个小时,中间还可能因为内存不足被OOM杀掉。
更麻烦的是,MySQL 5.7源码在ARM64上编译时,某些编译器优化选项会触发警告甚至报错,需要手动打补丁。除非你确实需要针对特定硬件做深度优化,否则直接用官方aarch64二进制包,已经是官方调优过的结果,性能不会差多少。
所以我的建议很明确:新环境优先RPM,需要定制路径优先二进制包,源码编译留给极少数有特殊需求的场景。
4. 初始化数据目录与my.cnf配置要点
4.1 目录规划与权限
安装方式不同,目录权限的注意事项也不一样。
RPM方式装完后,安装脚本会自动生成mysql用户,并把/var/lib/mysql目录属主设置为mysql:mysql。但你最好确认一下:
ls -ld /var/lib/mysql如果属主不对,比如是root,mysqld启动时会报“Couldn't find the mysql server at /var/lib/mysql”或权限拒绝。执行chown -R mysql:mysql /var/lib/mysql即可。
二进制包方式更要注意,手动创建的data目录必须由mysql用户拥有。我有一个习惯是在建目录后额外检查:
chown -R mysql:mysql /usr/local/mysql chmod 750 /usr/local/mysql/data不要用root直接运行mysqld,MySQL 5.7的安全机制会直接拒绝root用户启动服务,日志里会提示“Please read the Security section”。
4.2 my.cnf配置详解
MySQL 5.7的配置文件默认读取顺序是/etc/my.cnf、/etc/mysql/my.cnf等。我习惯统一使用/etc/my.cnf,里面按实际需要覆盖参数。
下面是一份适合ARM64、内存8到16G的起步配置:
[mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3306 pid-file=/usr/local/mysql/mysql.pid log-error=/var/log/mysqld.log user=mysql server-id=1 character-set-server=utf8mb4 collation-server=utf8mb4_general_ci skip-name-resolve max_connections=500 max_connect_errors=1000 innodb_buffer_pool_size=4G innodb_buffer_pool_instances=4 innodb_flush_log_at_trx_commit=1 sync_binlog=1 innodb_flush_method=O_DIRECT几个关键参数在ARM64下的考量:
- innodb_buffer_pool_size:通常设置为物理内存的50%到70%,如果服务器只跑MySQL就往上限靠。设太大会导致系统swap频繁。
- innodb_buffer_pool_instances:在ARM64多核环境下可以按内存池大小分片,减少并发锁,一般每个实例1G到2G比较合适。
- innodb_flush_method=O_DIRECT:跳过文件系统缓存,避免双缓冲浪费ARM服务器的内存带宽。
- skip-name-resolve:关闭DNS反查,减少连接建立时的延迟,但注意使用host为localhost的授权时,需要配合root登录调整。
如果你用的是RPM安装,basedir和datadir不需要写,但写上也不影响。二进制包必须写对。
4.3 初始化命令与初始密码处理
MySQL 5.7.6以后,初始化数据目录的命令从mysql_install_db变成了mysqld --initialize。初始化时必须在mysql用户权限下执行,并且不能以root运行。
RPM安装后,如果datadir为空,执行:
mysqld --initialize --user=mysql --log-error=/var/log/mysqld.log二进制包方式则要指定basedir和datadir:
/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --log-error=/var/log/mysqld.log这里有两个初始化模式:
- --initialize:生成一个临时随机root密码,密码会写进错误日志,形如“A temporary password is generated for root@localhost: xxxxxx”
- --initialize-insecure:生成空密码,适合测试环境
生产环境我建议用--initialize,拿到临时密码后首次登录再立刻修改。如果初始化时报错,先看/var/log/mysqld.log,大部分原因在日志里描述得很清楚。
5. 启动服务、开机自启与基础安全加固
5.1 systemd管理方式
RPM安装的好处是systemd服务已经写好了。直接执行:
systemctl enable --now mysqld然后查看状态:
systemctl status mysqld二进制包需要自己写service文件。在/etc/systemd/system/mysqld.service里写入:
[Unit] Description=MySQL Server 5.7 After=network.target [Service] Type=forking User=mysql Group=mysql PIDFile=/usr/local/mysql/mysql.pid ExecStart=/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.targetmysqld_safe会以mysql用户拉起mysqld进程,配置文件路径需要对应。写好后执行:
systemctl daemon-reload systemctl enable --now mysqld启动后确认进程:
ps -ef | grep mysqld | grep -v grep如果启动失败,立刻看/var/log/mysqld.log,不要反复重启,日志不会骗人。
5.2 首次登录、改密码与远程访问
拿到临时密码后,下面这条命令登录:
mysql -uroot -p'临时密码' -h127.0.0.1 -P3306登录后第一步是改密码。MySQL 5.7默认安装了validate_password插件,密码策略默认是MEDIUM,要求至少8位并包含大小写数字和特殊字符。如果嫌麻烦可以另行调整,但建议先满足策略:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPass@123'; FLUSH PRIVILEGES;如果需要远程连接,要创建一个专用账号,不建议直接放开root的远程权限:
CREATE USER 'app'@'%' IDENTIFIED BY 'AppPass@2024'; GRANT ALL PRIVILEGES ON *.* TO 'app'@'%'; FLUSH PRIVILEGES;这里host用了%,意味着任意IP都可以连,必须依靠防火墙控制访问来源。更安全的方式是把host设为具体应用服务器的IP。
5.3 防火墙与SELinux处理
CentOS 7默认firewalld是开启的,外部机器没法直接访问3306端口。开放端口:
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload firewall-cmd --list-ports然后是SELinux。如果状态是enforcing,MySQL启动后监听端口和读写数据目录可能被拦截。最简单的验证方式是:
getenforce生产环境不建议直接setenforce 0,但很多时候为了快速恢复业务,很多人会临时关闭。我的建议是先用sestatus -v确认相关文件上下文,如果嫌麻烦,短期测试可以setenforce 0,后续再通过semanage配好:
yum install policycoreutils-python semanage port -a -t mysqld_port_t -p tcp 3306 semanage fcontext -a -t mysqld_db_t "/usr/local/mysql/data(/.*)?" restorecon -Rv /usr/local/mysql/data第2章已经装了numactl-libs等依赖,这里semanage可能需要额外安装policycoreutils-python。如果这套配置实在折腾不明白,至少也要把SELinux临时改为permissive并写进/etc/selinux/config,但要清楚这属于安全妥协。
6. 运行中的报错排查与性能调优:ARM64下的特殊玩法
6.1 常见启动失败案例
下面是几个我实际遇到过的启动失败案例,整理成表格方便对照:
| 错误现象 | 根本原因 | 解决方法 |
|---|---|---|
| error while loading shared libraries: libaio.so.1 | 缺少libaio库 | yum install libaio |
| Can't connect to MySQL server through socket '/tmp/mysql.sock' | 服务未启动或socket路径不一致 | 检查mysqld进程和my.cnf socket路径 |
| [ERROR] Could not create file /usr/local/mysql/mysql.pid | 数据目录权限不对 | chown -R mysql:mysql /usr/local/mysql |
| Can't start server: Bind on TCP/IP port: Permission denied | SELinux拦截3306端口 | semanage port 或临时setenforce 0 |
| Wrong architecture (aarch64) | 安装了x86_64的rpm或运行了x86_64的二进制包 | 重新下载arm64/aarch64版本 |
排查启动问题有一个通用顺序:先journalctl -u mysqld查systemd日志,再tail -n 100 /var/log/mysqld.log查MySQL日志,最后ldd /usr/sbin/mysqld查动态库依赖。不管报什么错,这三步做完基本能定位。
6.2 内存分配器jemalloc配置
热词里“mysql5.7 配置 jemalloc”搜的人很多,因为在高并发场景下,MySQL默认使用的glibc内存分配器在长时间运行后容易产生内存碎片,最终出现内存占用越来越高但实际活跃数据并不多的情况。jemalloc对多线程和内存碎片控制更好,尤其在ARM多核服务器上表现明显。
在CentOS 7 ARM64上安装jemalloc:
yum install -y jemalloc确认库文件路径:
ls -l /usr/lib64/libjemalloc.so*配置文件有两种方式。第一种,在/etc/my.cnf的[mysqld_safe]段加入:
[mysqld_safe] malloc-lib=/usr/lib64/libjemalloc.so.2第二种,在systemd服务文件里通过环境变量注入:
Environment="LD_PRELOAD=/usr/lib64/libjemalloc.so.2"我自己的经历是,使用mysqld_safe的malloc-lib参数最直接,但前提是启动方式走mysqld_safe。如果直接用mysqld作为ExecStart,就需要用LD_PRELOAD方式。
配置后重启MySQL并验证jemalloc是否真的加载:
systemctl restart mysqld cat /proc/$(pidof mysqld)/maps | grep jemalloc如果能看到jemalloc.so的映射,说明生效了。需要注意的是,jemalloc版本不同,库文件结尾可能不同,比如.so.1或.so.2,配置前一定先确认实际路径,否则mysqld_safe会报找不库文件的错误。
6.3 ARM64下建议再多做几步
ARM64服务器的核心数通常很多,内存带宽也高,但如果不针对性地调整内核和MySQL参数,性能优势发挥不出来。
内存页和NUMA方面,多路ARM服务器可以尝试让mysqld进程内存交叉访问。使用numactl启动mysqld:
numactl --interleave=all /usr/sbin/mysqld --defaults-file=/etc/my.cnf &如果是在systemd环境下,可以在ExecStart前加上numactl,但要注意numactl命令本身要为aarch64架构。这种调整要压测验证,不是所有场景都有效。
内核参数方面,建议把swap使用调低一点:
sysctl vm.swappiness=10日志里如果出现大量“Table open cache”相关的警告,可以适当调大:
table_open_cache=4096 thread_cache_size=128注意,这些参数不是越高越好,设定后要通过sysbench或业务的真实负载来观察,观察指标包括QPS、内存占用、慢查询数。
7. 从5.7到8.0的升级提醒(避坑)
7.1 升级8.0需要注意的架构差异
虽然标题是安装5.7,但热词里“linux 如何将mysql5.7升级到8”也是高频搜索。我建议你现在就清楚升级路径,免得后面临时抓瞎。
MySQL 8.0官方对aarch64的支持更完善,但升级不是简单的替换二进制文件。MySQL 8.0默认认证插件改成了caching_sha2_password,很多老版本的应用驱动会出现认证失败,报“Authentication plugin 'caching_sha2_password' cannot be loaded”。如果业务侧的JDBC或客户端驱动版本较老,升级8.0前一定要先验证连接。
另外8.0对SQL_MODE更严格,之前5.7里一些隐式类型转换和默认排序规则,在8.0下可能直接报错或行为不一致。热词里“mysql5.7 配置 jemalloc”的热度也说明,很多人已经开始对5.7做深度调优,这其实是升级前的好基础。
7.2 升级前必做的检查与准备
如果真的准备从5.7升8.0,我建议至少完成下面四步:
- 全量备份。mysqldump导出所有库,并做一次二进制日志增量备份,确保任何时刻都能回滚。
- 检查应用连接串。确认应用侧数据库驱动版本是否支持MySQL 8.0和caching_sha2_password,不支持的驱动先升级。
- 使用pt-query-digest或者慢日志分析,找出SQL里可能与8.0不兼容的写法,比如旧的group by比较、分区表语法等。
- 在测试环境用相同的ARM64架构实例,先降到目标版本做一次完整验证,别直接在生产环境执行mysql_upgrade。
如果你暂时不打算升级,那就在5.7.44上做好配置固化,比如前面提到的jemalloc、innodb参数、定期备份,这套组合足够让老系统在ARM64上稳定运行很长时间。
最后分享一个实用技巧:装完MySQL后,建议把/var/log/mysqld.log里的初始密码和最终生效的/etc/my.cnf一起备份到固定目录,比如/root/mysql_install_backup/下,并生成配置文件的md5值。以后不管是排查问题还是做配置漂移比对,都会非常方便。ARM64环境下安装MySQL5.7,本质上就是把架构、依赖和安装包这三个点搞对,后面的步骤反而比x86_64更简单。