最近在ARM64架构的机器上部署 CentOS 7 + MySQL 5.7,网上搜了一圈,资料大多针对 x86_64,真正能在硬件平台上直接照抄的其实不多。这篇文章把我完整的实操过程整理出来,从环境确认、方案选型到依赖安装、源码编译、初始化配置以及最后的坑点排查,一次性说清楚,给同样在 ARM 环境里折腾数据库的朋友一个参考。
这篇文章适合三类人:一类是拿到了 ARM64 服务器(比如鲲鹏、飞腾这类平台),需要在上面跑存量业务的;一类是在嵌入式或 Android BSP 方向做开发,需要顺手搭一套 CentOS 7 环境的;还有一类是手头没有真机,打算用 QEMU 模拟 ARM64 先演练流程的。无论哪种情况,只要目标是在 ARM64 上跑 MySQL 5.7,这套流程都适用。
1. 装之前先把三件事搞清楚:架构、版本和方案
1.1 先确认你的硬件到底是不是 ARM64
很多人拿到机器就开始敲 yum install,结果装到一半发现架构不对,白忙活一场。所以我建议第一步永远先确认硬件信息。
uname -m uname -a cat /etc/redhat-release如果输出是aarch64,那就是 ARM64 架构;如果是x86_64,下面内容可以参考,但很多坑不会踩到。再用lscpu看看 CPU 核数和内存大小,这个在后面编译的时候非常关键,直接影响用-j参数开多少个并行任务。
我见过有人拿一台 ARM 开发板装 CentOS 7,内存只有 2G,结果编译到一半直接被 OOM 杀掉。所以先看清楚自己的家底,再决定后面怎么干。
顺带说一句,ARM64 的 CentOS 7 镜像和 x86_64 不一样,通常要从镜像站点的altarch/7目录下载,官方叫 Alternative Architectures。如果你准备自己装系统,记得找对应 aarch64 的 ISO,别下错版本。
1.2 为什么 MySQL 5.7 在 ARM64 上不能直接拿来主义
在 x86_64 机器上装 MySQL 5.7,大家已经习惯了“yum install mysql-community-server”三步走,但到了 ARM64 上,这条路往往走不通。
原因很简单:官方针对 aarch64 的 MySQL 5.7 rpm 包覆盖并不完整。尤其是 CentOS 7 的 aarch64 环境,直接配置官方 yum 仓库后,经常出现“没有可用软件包”或者依赖解析失败的情况。我去查过几次,也试过强制安装 rpm 包,最终都被依赖关系绊住了。
所以在这种情况下,最稳妥、也最通用的方案就是源码编译安装。源码编译的好处是:不依赖第三方是否做好了 ARM 包,只要编译器能跑,软件就能装上去。代价也很明显——耗时长,过程繁琐,中间任何一个依赖缺失都会卡住。
另外还有一个“替代品”选择:Percona Server 5.7 提供了 aarch64 的二进制包,安装很轻松。如果业务上不强制要求“MySQL 官方版本号”,而且团队愿意接受兼容性变化,这条方案也能落地。但如果你想保持官方原汁原味的 5.7,那源码编译就是主力方案。
1.3 安装方案怎么选:源码编译、rpm 包、Percona 兼容包
我把几种方案整理成一个对比表,一目了然:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 官方 yum 仓库安装 | 配置简单,一条命令 | aarch64 包覆盖不全,经常找不到 5.7 | 先试一把,不行就换 |
| rpm 包强制安装 | 安装速度快 | ARM 包难找,依赖解析麻烦 | 很少成功,不推荐 |
| 官方源码编译 | 通用性强,可定制,不依赖 ARM 包 | 编译时间长,需要手动管理 | 推荐方案 |
| Percona 5.7 二进制包 | 有完整 aarch64 包,安装快 | 非官方 MySQL 版本,审计可能不认 | 业务允许时可用 |
我最终选的是“官方源码编译”。这个过程虽然折腾,但一旦把依赖关系和编译参数搞明白,后面遇到任何 ARM 平台的数据库需求,心里都有底。
2. 编译前的依赖准备与基础环境调整
2.1 安装编译工具链:CentOS 7 的 cmake 版本是个大坑
源码编译 MySQL 5.7 必须用到 cmake,版本要求是 3.0 以上。但 CentOS 7 自带的源里,默认 cmake 版本只有 2.8.12,直接执行 cmake 配置一定会报错:
CMake 2.8.12 is lower than required version 3.0
解决办法是安装 cmake3,命令是:
yum install -y epel-release yum install -y cmake3装完之后系统里会多一个cmake3命令,后面配置的时候用cmake3而不是cmake。这个坑几乎每个人都会踩,提前说清楚能省很多时间。
除了 cmake3,编译工具链和依赖库也一并装齐:
yum install -y gcc gcc-c++ make ncurses-devel bison openssl-devel libaio-devel numactl-devel perl逐个解释一下为什么需要这些:
gcc、gcc-c++:编译 C/C++ 代码的基本工具链,MySQL 5.7 源码编译必须有。ncurses-devel:终端文本界面库,MySQL 客户端和部分工具依赖。bison:语法分析器生成器,MySQL 源码编译过程中要用到。openssl-devel:MySQL 的 SSL 连接功能依赖 OpenSSL 开发库。libaio-devel:异步 I/O 库,InnoDB 的 native AIO 特性会用到,运行的时候也需要libaio.so.1。numactl-devel:NUMA 相关开发库,MySQL 在分配内存时会用。
确认一下 gcc 版本和 cmake3 是否可用:
gcc --version cmake3 --version到这里编译环境就准备好了。
2.2 下载源码包与准备 Boost 库依赖
MySQL 5.7 源码编译还有一个特殊要求:必须指定 Boost 库。5.7 系列从很早就开始依赖 Boost 1.59.0,如果本机没有对应版本的 Boost,cmake 配置阶段会直接报错。
官方下载页面其实提供了一个“一揽子”方案——mysql-boost-5.7.44.tar.gz,这个包里面已经把 Boost 1.59.0 的源码打包进去了,省去单独下载的麻烦。我在实际使用中强烈推荐这个包,尤其是国内网络环境,省一次下载就少一次折腾。
cd /usr/local/src wget https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-5.7.44.tar.gz tar zxf mysql-boost-5.7.44.tar.gz cd mysql-5.7.44解压之后,源码目录下会有一个boost/子目录,后面 cmake 配置时直接-DWITH_BOOST=./boost就行。
这里还要提醒一句:如果你选择下载不带 boost 的源码包,那就得自己从 Boost 官网下载boost_1_59_0.tar.gz,并且解压到固定目录,还要保证路径里没有权限问题。既然官方已经给了打包好的版本,就别自己给自己加戏了。
2.3 创建运行用户与数据目录
编译安装不会像 rpm 包那样自动创建 mysql 用户,所以需要手动搞定。
useradd -r -s /sbin/nologin mysql mkdir -p /data/mysql/logs chown -R mysql:mysql /data/mysql这里我把数据目录放在/data/mysql,日志也统一放进/data/mysql/logs。生产环境最好把数据目录单独挂载在一块独立磁盘上,避免根分区满了导致数据库异常。如果你有独立数据盘,先把盘挂载到/data,再执行上面的操作。
注意:/usr/local/mysql这个安装目录不需要chown给 mysql 用户。很多教程喜欢把整个 mysql 目录全部赋权给 mysql,其实从安全角度讲是不必要的,甚至有点危险。mysqld 运行的时候只需要对数据目录有写权限,安装目录保持 root 所有即可。
3. 源码编译安装 MySQL 5.7 全流程
3.1 cmake 配置参数解析:每个参数都有讲究
进入源码目录后,执行下面这组 cmake 配置命令。以我实际使用为准,参数都经过验证:
cd /usr/local/src/mysql-5.7.44 cmake3 . \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ -DMYSQL_DATADIR=/data/mysql \ -DSYSCONFDIR=/etc \ -DMYSQL_TCP_PORT=3306 \ -DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock \ -DDEFAULT_CHARSET=utf8mb4 \ -DDEFAULT_COLLATION=utf8mb4_general_ci \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_PARTITION_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_FEDERATED_STORAGE_ENGINE=1 \ -DWITH_MYISAM_STORAGE_ENGINE=1 \ -DWITH_SSL=system \ -DWITH_ZLIB=system \ -DWITH_BOOST=./boost \ -DENABLED_LOCAL_INFILE=1 \ -DMYSQL_USER=mysql逐项说明一下我的选择逻辑,方便你按需调整:
CMAKE_INSTALL_PREFIX:安装路径。默认是/usr/local/mysql,我保持默认,因为这是 MySQL 社区最常用的目录。MYSQL_DATADIR:数据目录,提前创建的那个/data/mysql。SYSCONFDIR:配置文件目录。设为/etc后,mysqld 启动时会自动读取/etc/my.cnf。MYSQL_TCP_PORT、MYSQL_UNIX_ADDR:端口和 socket 文件位置,保持和后续配置文件一致。DEFAULT_CHARSET、DEFAULT_COLLATION:默认字符集和排序规则。MySQL 5.7 默认是latin1,如果不改,建表时不指定字符集就会出现中文乱码的隐患。现在的主流选择是utf8mb4,排序规则我用的是utf8mb4_general_ci,兼顾性能和兼容性。如果你是精细化排序需求,可以换utf8mb4_unicode_ci。WITH_INNOBASE_STORAGE_ENGINE、WITH_MYISAM_STORAGE_ENGINE等:要编译的存储引擎。InnoDB 和 MyISAM 是必须的,Partition 分区表在 5.7 里默认集成,显式开启一下更稳。其余引擎按需开启,不用的可以去掉。WITH_SSL=system:使用系统 OpenSSL 库,而不是编译内置的 OpenSSL,减少后续安全补丁的维护成本。WITH_ZLIB=system:使用系统 zlib 压缩库,用于压缩备份等场景。WITH_BOOST=./boost:指向源码包内置的 Boost 目录。如果这个参数写错或没写,配置阶段会卡在 Boost 检测上。ENABLED_LOCAL_INFILE=1:开启LOAD DATA LOCAL INFILE能力。这个功能默认是关闭的,但很多数据导入脚本会用到,提前打开后面会省事。MYSQL_USER=mysql:指定运行用户,和前面创建的 mysql 用户对应。
配置完成后,如果看到-- Configuring done和-- Generating done,说明这一步顺利通过。如果中途报红色错误,优先排查上面提到的依赖库和 Boost 路径。
3.2 make 编译与耗时说明:内存不够别硬扛
配置完成之后就是最耗时的编译阶段:
make -j$(nproc)这个-j$(nproc)会自动使用所有 CPU 核数。在核数多的服务器上确实快,但有个前提:内存要扛得住。每个编译进程大概会吃掉几百 MB 到 1GB 内存,如果 16 核但只有 8G 内存,开-j16大概率会 OOM。
我自己的建议是:内存低于 4G,老老实实make -j2;内存 4G 到 8G,make -j4;内存大于 16G,再考虑跑满核心。ARM 平台的单核编译速度普遍不如 x86,做好心理准备——一台 4 核 ARM64 机器编 5.7,差不多要一两个小时。
编译过程中如果被 OOM 杀掉,除了降低并行数,还可以临时加 swap 空间撑过去:
dd if=/dev/zero of=/swapfile bs=1M count=4096 chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile swap swap defaults 0 0' >> /etc/fstab编译完之后,安装:
make installmake install很快,就是把编译出的二进制文件拷贝到/usr/local/mysql,然后可以顺手验证一下目录结构:
ls -l /usr/local/mysql/bin/mysqld看到mysqld文件存在,安装这步就完成了。
3.3 make install 后的权限修正与路径优化
安装完成后,还存在两个细节:
第一,再次确认数据目录权限。之前已经chown -R mysql:mysql /data/mysql,这一步要再做一次,防止编译过程生成的文件改动权限:
chown -R mysql:mysql /data/mysql第二,把 mysql 的 bin 目录加入 PATH,方便后面mysql、mysqld命令直接使用:
echo 'export PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh source /etc/profile.d/mysql.sh有人习惯建软链接ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql,也可以,但用 profile 文件更干净,卸载的时候直接删文件就行。
4. 初始化数据目录、配置文件和 systemd 管理
4.1 手写一份够用的 my.cnf
编译安装不会自动生成/etc/my.cnf,需要自己写。我把配置按模块拆开,方便你按需复制:
[client] port=3306 socket=/data/mysql/mysql.sock [mysql] prompt="mysql> " auto-rehash [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/mysql socket=/data/mysql/mysql.sock pid-file=/data/mysql/mysqld.pid port=3306 server-id=1 character-set-server=utf8mb4 collation-server=utf8mb4_general_ci skip-name-resolve explicit_defaults_for_timestamp=true max_connections=1000 max_connect_errors=100000 back_log=500 wait_timeout=3600 interactive_timeout=3600 tmp_table_size=64M max_heap_table_size=64M log-error=/data/mysql/logs/error.log slow_query_log=1 slow_query_log_file=/data/mysql/logs/slow.log long_query_time=2 log_bin=/data/mysql/logs/mysql-bin binlog_format=row expire_logs_days=7 max_binlog_size=256M innodb_buffer_pool_size=2G innodb_log_file_size=256M innodb_flush_log_at_trx_commit=2 innodb_file_per_table=1 innodb_buffer_pool_instances=8 innodb_flush_method=O_DIRECT performance_schema=ON说明几个关键点:
basedir和datadir必须和 cmake 参数一致,不然启动会找不到路径。pid-file建议放在数据目录下,避免/var/run的权限问题。skip-name-resolve:跳过反向域名解析,否则客户端连接时会因为 DNS 解析慢而卡顿。但这个选项开了之后,grant授权时就不能用主机名,只能写 IP 或%。innodb_buffer_pool_size:InnoDB 缓冲池大小,通常设为物理内存的 50% 到 70%,按当前机器内存调整。示例里的 2G 只是保守值。innodb_flush_log_at_trx_commit=2:事务提交时日志不立即刷盘,性能好一些。如果业务要求最高数据安全等级,改成1。- 开启了
log_bin就是开启了二进制日志,为后续主从复制或者数据恢复做准备。如果确定不需要,可以注释掉。
4.2 初始化数据目录:initialize 和 initialize-insecure 的区别
配置写好后,执行初始化操作。MySQL 5.7 已经完全用mysqld --initialize替代了旧的mysql_install_db脚本。
/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --initialize-insecure --user=mysql--initialize和--initialize-insecure的区别要讲清楚:
--initialize:会生成一个临时随机 root 密码,打印在/data/mysql/logs/error.log文件里。很多人初始化完找不到密码,就是因为没看这个日志。--initialize-insecure:root 账号初始为空密码,登录后马上设置密码即可。我在测试和学习环境里更推荐这种方式,清爽很多。
初始化完成后,再生成 SSL 证书和 RSA 密钥:
/usr/local/mysql/bin/mysql_ssl_rsa_setup --basedir=/usr/local/mysql --datadir=/data/mysql这一步会生成ca.pem、server-cert.pem、client-cert.pem等文件,MySQL 的 SSL 连接能力依赖它们。如果不执行,之后启动虽然正常,但客户端想要启用 SSL 加密连接时会遇到麻烦。
初始化过程通常几秒钟就结束。如果报错,99% 是数据目录权限不对或者 my.cnf 里配置项写错,去看 error.log 比瞎猜有效得多。
4.3 手写 systemd 服务单元文件
rpm 包装完会自动注册 systemd 服务,但编译安装不会。所以需要手动创建一个服务单元文件/etc/systemd/system/mysqld.service:
[Unit] Description=MySQL Community Server 5.7 After=network.target After=syslog.target [Service] Type=notify User=mysql Group=mysql PIDFile=/data/mysql/mysqld.pid ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf LimitNOFILE=65535 LimitNPROC=65535 TimeoutSec=300 PrivateTmp=true Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target这里用的是Type=notify,mysqld 启动成功后会向 systemd 发通知,相比传统的Type=forking更加快速可靠。但有一个注意点:部分旧内核环境可能对 notify 支持不佳,如果启动时一直卡在 “Activating start” 超过 30 秒,把 Type 改成simple,或者换成ExecStart=/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf搭配Type=forking都能绕过去。
注册并启动服务:
systemctl daemon-reload systemctl enable mysqld systemctl start mysqld systemctl status mysqld启动后立刻看一眼日志,确认没有异常:
tail -50 /data/mysql/logs/error.log看到类似ready for connections就说明数据库已经正常起来了。
4.4 启动后的基本验证与安全设置
服务启动后,验证最基本的登录和版本信息:
mysql -uroot -p # 因为用了 --initialize-insecure,密码直接回车登录成功后:
SELECT version(); ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPassword'; FLUSH PRIVILEGES;设置完密码后,再敲exit重新登录一次,确认新密码生效。
此外,检查一下字符集是否按预期生效:
SHOW VARIABLES LIKE 'character_set_server'; SHOW VARIABLES LIKE 'collation_server';我这里做验证时,两个输出分别是utf8mb4和utf8mb4_general_ci,说明 my.cnf 的配置已经正确读取。
如果后面要远程连接,还要处理防火墙和账号:
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reloadCREATE USER 'app'@'%' IDENTIFIED BY 'YourAppPassword'; GRANT ALL PRIVILEGES ON *.* TO 'app'@'%'; FLUSH PRIVILEGES;5. 常见问题与排查实录
5.1 快速问题速查表
我把实际踩过的坑汇总成一张速查表,遇到问题先对照排查:
| 报错信息或现象 | 原因 | 解决办法 |
|---|---|---|
| CMake 2.8.12 is lower than required version 3.0 | CentOS 7 自带 cmake 版本太老 | yum install cmake3,用cmake3命令 |
| Could NOT find Boost | Boost 路径未指定或版本不对 | 用mysql-boost-5.7.44.tar.gz源码包,-DWITH_BOOST=./boost |
| error while loading shared libraries: libaio.so.1 | 缺少异步 I/O 运行库 | yum install -y libaio libaio-devel |
| mysqld: Can't create/write to file '/data/mysql/mysqld.pid' | 数据目录权限不对 | chown -R mysql:mysql /data/mysql |
| Failed to initialize DD storage engine | 数据目录权限或 my.cnf 配置错误 | 查看 error.log,修正配置和权限 |
| systemctl start 后状态一直是 activating | Type=notify 在部分环境兼容性差 | 改成Type=simple或换mysqld_safe |
| Access denied for user 'root'@'localhost' | root 密码与预期不符 | 初始化时用--initialize-insecure,或从 error.log 找临时密码 |
| 远程连接 Connection refused | 防火墙没放行或 bind_address 限制 | 放行 3306 端口,检查 my.cnf 是否有 bind_address |
| 中文存入后乱码 | 默认字符集不是 utf8mb4 | my.cnf 设置character-set-server=utf8mb4,重建相关表 |
5.2 编译内存不足怎么救:swap 扩容实操
编译 MySQL 5.7 最让人崩溃的并不是报错,而是编译到一半进程直接消失,没有任何提示。如果是在终端上编译,可能会看到一行Killed,这就是内存被 OOM Killer 干掉了。
解决办法有几个:
第一,降低并行数。make -j2虽然慢,但每一步都很稳。
第二,增加 swap。前面已经给出命令,建议在编译期间临时挂一个 4G 的 swap 文件:
dd if=/dev/zero of=/swapfile bs=1M count=4096 chmod 600 /swapfile mkswap /swapfile swapon /swapfile但要注意,swap 是在内存不够时的缓解方案,如果内存只有 1G,就算挂 4G swap,编译速度也会慢到让人怀疑人生。有条件的话还是建议至少 2G 内存起步。
第三,清理无用的进程,释放内存。我遇到过一次比较极端的情况,服务器上还跑着其他 Java 服务,编译时内存只剩下几百兆,后来停掉一个临时服务,编译就顺利完成了。
5.3 几个容易忽略的后续细节
装完数据库只是开始,有几个细节我建议第一时间处理。
第一个是把 mysql 和 mysqldump 命令加入 PATH,有人会遇到mysql: command not found。前面写了/etc/profile.d/mysql.sh,但注意新开的 shell 窗口才生效,当前窗口需要手动source一下。
第二个是卸载清理。如果你之前尝试过 rpm 安装但失败了,会有残留的/etc/my.cnf、/var/lib/mysql目录。编译安装前把这些残留清理干净,否则初始化时可能和旧配置冲突。
rm -rf /var/lib/mysql rm -f /etc/my.cnf.rpmsave第三个是备份慢日志和 binlog 的清理策略。expire_logs_days=7只对二进制日志生效,不代表逻辑备份可以不做。如果这台机器要接手存量业务,建议第一时间配好定时任务,把常用库的基础备份跑起来,不然哪天真出问题,再补救就晚了。
说点题外话
如果你手头也是 ARM64 的 CentOS 7,我最想说的就一句话:别硬背 x86 那一套方式,很多细节是真的不一样。cmake 版本要换、rpm 仓库大概率装不上、编译还特别吃内存——这些坑我都是实打实踩过一遍才摸清楚的。
如果只是临时验证流程,手头没有 ARM64 真机,也可以考虑用 QEMU 模拟一个 aarch64 环境,先把流程跑通。模拟器的性能比真机差不少,编译时间可能会拉长很多,但用来做流程验证和参数测试,完全够用。
另外多说一句,如果业务对版本没有特别要求,能上 MySQL 8.0 还是尽量上 8.0。但现在很多老项目就卡在 5.7 这一档动弹不得,这篇文章也就是给这些系统续命用的。编译安装走一遍,至少能让你明白这套环境是怎么搭起来的,以后出了问题,排查的方向也会比只会用 yum 的人清晰得多。