☰
ARM麒麟V10源码编译xtrabackup:MySQL备份工具适配全攻略
2026/10/19 5:21:05 网站建设 项目流程

最近在给一批 ARM 服务器搭数据库备份链路时,我把 xtrabackup 从头编译了一遍。这个工具在 x86 环境下通常直接解压官方二进制包就能用,但换成麒麟 V10 加 aarch64 的组合后,官方预编译包基本指望不上,第三方源里能找到的版本又参差不齐,想来想去还是自己动手编译最可控。如果你也是 DBA 或运维工程师,手上正好跑着麒麟 V10 这类基于 Red Hat 系包管理的 ARM 系统,又在给 MySQL 备份发愁,那这篇文章应该能帮你省下不少试错时间。

先说结论:xtrabackup 源码编译这件事本身并不复杂,真正麻烦的是 ARM 体系下的一票依赖库适配。整套流程走下来,无非是“环境确认、依赖补齐、源码获取、CMake 配置、编译、验证”这几步,但每一步都可能踩出奇奇怪怪的坑。下面我把这次操作的过程和排查经验完整记录下来,从版本选型到备份恢复演练都覆盖到,尽量让你可以照着抄作业。

1. 先想清楚:为什么必须编译,以及整个方案怎么走

1.1 ARM 架构下的适配缺口

之前习惯了 x86 服务器上的操作方式,需要 xtrabackup 时直接去官方发布页下载对应版本,解压到 /usr/local/bin 就能用,最多再装两个依赖库。但 ARM 架构的机器没有这么幸运。xtrabackup 官方预编译包长期以 x86_64 为主,aarch64 体系下要么只提供很老的版本,要么干脆没有。有段时间我图省事,想过把 x86 的二进制拷过来跑,结果系统直接报 Exec format error,这条路连想都不用想。

另外一个问题是麒麟 V10 自身的软件源。默认源里收录的 xtrabackup 相关 rpm 包很少,就算有,版本往往和线上 MySQL 版本对不上。备份工具这种东西最怕版本错位,版本不匹配轻则备份失败,重则备份出的数据在恢复时直接不可用。与其在兼容性上反复拉扯,不如从源码编译一个与数据库版本严格对应的 xtrabackup,后续升级维护也清楚自己在用什么。

1.2 版本选型:先定 xtrabackup 再定数据库

动手编译前,务必先确认线上 MySQL 的版本,因为 xtrabackup 的大版本和数据库大版本必须对齐。选错版本会出现 Unsupported command 之类的报错,或者备份过程中莫名其妙崩掉。

数据库版本对应 xtrabackup 版本说明
MySQL 5.7xtrabackup 2.4.x编译依赖相对保守,ARM 下更顺
MySQL 8.0xtrabackup 8.0.x功能更全,但编译要求明显更高
MariaDB 场景结合具体版本评估部分版本需要特殊参数,建议单独测试

如果线上还是 MySQL 5.7,我建议优先考虑 2.4 系列。原因很实际:2.4 系列对应的源码年代更早,对编译器的要求更宽容,麒麟 V10 自带的 gcc 版本通常就能编过。而 8.0 系列需要 C++17 特性支持,某些环境里的 gcc 7 在编译特定模块时会直接内部错误,处理起来很麻烦。

如果是 MySQL 8.0,那就没什么选择空间,只能硬啃 8.0 系列。这时候建议提前确认系统里 gcc 和 cmake 的版本,不要把进度卡在编译器的坑上。整体思路就是:先定备份工具版本,再定编译方案,最后再动源码,顺序反过来很容易做无用功。

1.3 整体路线图

整个编译链路可以拆成六步:确认系统底细、安装工具链和依赖库、下载源码、配置 CMake、执行编译、验证产物。每一步之间是强依赖关系,前一步没做好,后一步必然报错。我的建议是每完成一步就顺手做一个记录,比如 gcc 版本、cmake 版本、依赖库的安装路径,这些信息在后续排查坑时特别有用。

编译完成后不要急着上线,先在测试环境跑一次全量备份和恢复,确认备份文件可读、恢复后实例能正常启动,再考虑接入生产。备份工具不是装上就完事,它要经得住数据恢复的检验才算合格。

2. 编译前的环境检查与依赖准备

2.1 先把系统底细摸清楚

拿到一台新机器后,不要急着敲编译命令。先确认三个信息:操作系统版本、CPU 架构、包管理器类型。麒麟 V10 在不同版本里的基底不完全一样,有的用 yum,有的用 dnf,软件源的包数量也有区别。这些信息直接关系到后面依赖库怎么装。

cat /etc/os-release uname -a arch

正常会看到类似这样的输出:架构是 aarch64,内核版本和系统版本号齐全。这里要特别看一眼 gcc 的版本,后续所有编译工作都依赖它:

gcc --version g++ --version cmake --version

麒麟 V10 默认源的 gcc 多为 7.x 或 8.x。如果打算编译 xtrabackup 2.4,这个版本通常够用;如果编译 8.0 系列,建议先做好心理准备,可能需要额外升级编译器或配置新的软件源。

2.2 编译工具链安装

工具链是编译的前提,缺一个包后面就要返工。我一般会一次性把常见编译工具装齐,避免中途反复安装浪费时间:

yum install -y gcc gcc-c++ make cmake automake autoconf libtool bison flex

这里多啰嗦一句,cmake 版本是有下限要求的。xtrabackup 2.4 对 cmake 的要求不高,系统自带的 3.x 基本没问题;8.0 系列对 cmake 版本要求更高,如果系统源里的版本太老,建议直接用 cmake 官方源码编译一个新版本。另外,有些麒麟 V10 环境默认连 gcc-c++ 都没有,需要手动确认是否安装。

2.3 补齐关键依赖库

xtrabackup 源码编译依赖的库不算多,但在 ARM 环境下有几个特别容易出问题。我的经验是优先用系统包管理器安装,装不上的再走源码编译,顺序不要颠倒。

以下依赖库建议优先通过 yum 安装:

yum install -y ncurses-devel zlib-devel libaio-devel openssl-devel yum install -y libgcrypt-devel libgpg-error-devel

libgcrypt 和 libgpg-error 在 ARM 机器上比较容易踩坑。如果系统源里没有 libgcrypt-devel,可以考虑从源码编译。libgcrypt 本身依赖 libgpg-error,这两者需要配套编译,顺序是先 libgpg-error 再 libgcrypt。还有一个库是 libev,xtrabackup 在备份时依赖它处理异步 I/O,但麒麟 V10 默认源里经常没有 aarch64 的 libev 包,最常见的解决办法是自己源码编译,安装路径默认是 /usr/local,后面 CMake 配置时需要单独指定。

qpress 也建议顺手处理一下。xtrabackup 做压缩备份时会调用 qpress,没有这个工具,--compress 选项会直接报错。qpress 没有复杂的依赖,编译安装都很快,先把它准备好,后面备份实测时能省一个环节。

3. 源码获取与 CMake 配置详解

3.1 下载源代码:选 tar 包而不是 git 仓库

获取源码时,我强烈建议直接下载官方发布的 tar 包,不要用 git clone 拉整个仓库。xtrabackup 源码仓库结构接近 MySQL 源码,里面包含 storage/innobase 等多个子模块,git 方式拉取需要处理子模块同步,复杂不说,还容易拉到中间开发状态的代码。官方发布页会同时提供多个版本的源码 tar 包,下载与你选定版本一致的包即可。

mkdir -p /opt/src && cd /opt/src wget <官方发布页对应的下载地址> tar xf xtrabackup-2.4.21.tar.gz cd xtrabackup-2.4.21

下载完成后最好核对一下 sha256 校验值,源码包在传输过程中是否完整,直接影响后面的编译结果。tar 包解压后目录结构是这样的:根目录有 CMakeLists.txt,storage/innobase/xtrabackup 目录放的是 xtrabackup 主体源码。整个编译过程就是从根目录执行 cmake,再由 make 调度完成。

3.2 CMake 配置参数逐个说明

CMake 配置是编译流程中最关键的一步。参数设不对,后面 make 阶段会以各种诡异报错来折磨你。以下是我在实际环境中最终使用的配置命令,以 xtrabackup 2.4 为例:

cmake -DCMAKE_BUILD_TYPE=Release \ -DBUILD_CONFIG=xtrabackup_release \ -DWITH_BOOST=/opt/boost/boost_1_59_0 \ -DDOWNLOAD_BOOST=0 \ -DLIBEV_INCLUDE_DIR=/usr/local/include \ -DLIBEV_LIB=/usr/local/lib/libev.so \ -DWITH_ROCKSDB=OFF \ ..

CMAKE_BUILD_TYPE 设置为 Release,启用编译优化,保证产物体积和性能都处于合理范围。BUILD_CONFIG 设为 xtrabackup_release 是关键中的关键,它决定了编译产物是 xtrabackup 而不是普通的 mysqld,漏掉这个参数,后面生成的东西可能完全不是你想要的。

WITH_BOOST 指定 boost 库的路径。boost 版本要和源码要求严格对齐,xtrabackup 2.4 通常对应 boost 1.59 左右,8.0 系列对应 boost 1.73 或更高。具体以源码顶层 CMakeLists.txt 中声明的版本为准,不要拿高版本 boost 直接顶替低版本,编译阶段或许能过,运行阶段却可能因为接口差异出现莫名其妙的问题。

DOWNLOAD_BOOST 设为 0,是让 CMake 不要尝试联网下载 boost。ARM 服务器网络环境不一定顺畅,联网下载很容易失败,手工下载 boost 包并解压到指定目录,可控性高得多。

LIBEV_INCLUDE_DIR 和 LIBEV_LIB 这两个参数,是专门给源码编译安装到 /usr/local 的 libev 用的。如果 libev 是通过系统包管理器安装的,这两个参数可以视情况省略;如果和我一样是从源码编译的,必须明确指定,否则 CMake 检测不到头文件,编译到一半直接报 ev.h 找不到。

WITH_ROCKSDB 设置为 OFF,关闭 RocksDB 相关模块。生产环境如果不需要 RocksDB 存储引擎,关掉它能明显缩短编译时间,也少一票依赖纠纷。最后两个点号表示源码目录,必须在源码根目录下执行 cmake,否则路径都对不上。

3.3 执行编译:控制并发数

CMake 配置成功后,进入编译阶段:

make -j4

建议是先 -j4,不要一上来就 -j 几十。ARM 服务器核心数往往很多,但内存不一定跟得上。我见过一台 64 核的机器,直接 make -j64,编译进行到一半 OOM,进程被内核杀掉,连报错信息都没留下。用 -j4 起一个稳定节奏,编译一段时间后再考虑调高并发。

时间方面给个参考:xtrabackup 2.4 在四核八线程的 ARM 机器上,大约 40 分钟到 1 小时;8.0 系列可能 2 小时起步。如果只是验证编译流程,可以先用 -j4 编一遍,确认无错误后再重编一次,但通常没必要,直接一次性编完就好。

编译完成后,二进制产物在 storage/innobase/xtrabackup 目录下:

ls -lh storage/innobase/xtrabackup/

你会看到 xtrabackup、xbstream、xbcloud 等可执行文件。把它们复制到系统路径:

cp storage/innobase/xtrabackup/xtrabackup /usr/local/bin/ cp storage/innobase/xtrabackup/xbstream /usr/local/bin/

4. 编译过程中的高频坑与解决方案

编译这条路走下来,不敢说每个坑都踩过,但下面这几个问题在 ARM 加麒麟 V10 的组合里出现频率最高,值得单独拿出来写。

4.1 编译器版本过旧:internal compiler error

症状很典型,编译到一半终端冒出:

cc1plus: fatal error: internal compiler error

这不是代码的问题,是 gcc 版本和源码模板实例化要求不匹配。麒麟 V10 默认 gcc 版本通常偏旧,处理 xtrabackup 8.0 这类对 C++ 标准要求较高的源码时,编译内核模块时会崩溃。解决方式有两种:第一,使用软件源安装更高版本 gcc;第二,从源码编译一个新版本 gcc 到独立目录。不管哪种方式,编译完记得确认 gcc 和 g++ 都切换到新版本,只换其中一个会出现链接期找不到符号的问题。

4.2 boost 版本对不上:最经典的报错

报错长这样:

CMake Error: Could not find boost Could not find the following Boost libraries: boost_system

这类问题的根源基本都是 WITH_BOOST 指定的路径不对,或者路径下的 boost 版本与源码要求不匹配。解决办法是去 boost 官网下载指定版本源码,解压到固定路径,不需要提前编译 boost 库,直接用解压目录作为 WITH_BOOST 的值。有一点要注意,解压目录结构必须是 boost_1_59_0 这一层,里面直接能看到 boost 子目录,CMake 才能识别。

4.3 libev 头文件找不到:ev.h No such file or directory

源码编译安装 libev 后,头文件默认在 /usr/local/include,系统默认搜索路径里并没有这个目录,所以编译时找不到 ev.h。解决办法是让 CMake 知道 libev 的位置,也就是前面提到的那两个参数:

-DLIBEV_INCLUDE_DIR=/usr/local/include \ -DLIBEV_LIB=/usr/local/lib/libev.so

如果编译时仍然报错,先确认 libev 源码编译时有没有执行 make install,以及 /usr/local/lib 下到底生成的是 libev.so 还是 libev.a,按实际路径修改参数。

4.4 make 过程中 OOM 与系统卡死

症状是编译一段时间后终端没有任何报错,只是输出 Killed。这通常是内存不足,内核 OOM killer 把编译进程杀了。排查方法很简单,看日志,make 的报错信息里没有出现编译错误,只有进程被杀,那八九不离十是内存问题。解决思路有两个:降低并行度,改为 -j2 或 -j1;或者给系统增加 swap 空间,给编译过程更多缓冲。这两种方式我都试过,优先加 swap,因为并行的编译效率还是明显更高。

4.5 依赖库缺失的速查表

编译过程中的很多报错本质上都是依赖库缺失或版本不符,这里整理成一张速查表:

报错关键字缺失依赖处理方式
Could NOT find LibAIOlibaio-develyum 安装 libaio-devel
Could NOT find cursesncurses-develyum 安装 ncurses-devel
Could NOT find OpenSSLopenssl-develyum 安装 openssl-devel
ev.h not foundlibev-devel源码编译 libev 并指定路径
libgcrypt headers not foundlibgcrypt-develyum 安装或源码编译
Could NOT find GTest测试组件加 -DBUILD_TESTING=OFF 关闭

这些报错看起来吓人,实际解决起来都不复杂,关键是不要盲目重复 make,先看清 CMake 配置阶段到底检测到了什么。

4.6 安装后运行报错:动态库找不到

编译成功并不代表安装完就能跑。复制二进制到 /usr/local/bin 后,第一步先检查依赖库:

ldd /usr/local/bin/xtrabackup | grep "not found"

如果 grep 出结果,比如 libgcrypt.so.20 找不到,说明动态库路径没被系统识别。解决方法通常是把 /usr/local/lib 写进 ld.so.conf:

echo "/usr/local/lib" > /etc/ld.so.conf.d/local.conf ldconfig

5. 编译产物验证与备份恢复演练

5.1 版本验证与启动检查

编译完不要急着上线,先做版本验证:

xtrabackup --version

输出里会显示 xtrabackup 版本号和对应的 MySQL 版本,同时能看到基于的架构,比如 Linux (aarch64)。这一条就能确认产物是 ARM 版本,而不是误拷贝的 x86 二进制。

接下来检查动态库依赖,确保所有依赖库都能找到。这一步同时也能验证前面 libev、libgcrypt 等编译安装是否成功。最后跑一次 help 命令,确认参数能正常解析:

xtrabackup --help

5.2 用编译出的 xtrabackup 做一次全量备份

版本验证通过后,在测试环境做一次真实的备份操作。准备好数据库账号,备份用户至少需要 RELOAD、LOCK TABLES、REPLICATION CLIENT 权限。命令并不复杂:

xtrabackup --backup \ --target-dir=/data/backup/base \ --host=127.0.0.1 \ --user=backup_user \ --password=your_password

执行完成后,查看备份目录,应该能看到 xbstream 生成的多个文件,以及 xtrabackup_info 等元数据文件。重点看一下 xtrabackup_info 里的备份起止 LSN,确认 LSN 没有被跳过。备份过程中的官方术语不少,但只要看到 completed OK 字样,大体就可以判断备份过程是正常的。

5.3 prepare 与恢复演练

备份完成后先做 prepare,这一步是把备份文件变更到一致状态:

xtrabackup --prepare --target-dir=/data/backup/base

prepare 的日志值得多看两眼。它会把 InnoDB redo log 应用一遍,生成新的 ib_logfile,看到类似 last LSN 的信息后,数据处于可恢复状态。这个阶段如果发现报错,说明备份本身有问题,及时排查,比恢复时才发现问题要省心得多。

恢复就是把 prepare 好的数据文件复制回数据目录。这里提醒一点,恢复前确保目标数据目录是空的,或者明确知道自己在覆盖哪些文件。推荐做法:

rsync -a /data/backup/base/ /var/lib/mysql/ chown -R mysql:mysql /var/lib/mysql

数据目录权限容易被忽略,文件属主不对,MySQL 启动时直接拒绝读取。恢复完成后启动数据库实例,用一次简单的查询来验证数据完整性:

SELECT COUNT(*) FROM sys_info;

查询结果与备份节点一致,整个备份与恢复链路才算走通。

5.4 增量备份的扩展

如果后续有增量备份需求,编译好的 xtrabackup 也能一并支持。增量备份的前提是先有一个全量备份,然后通过 incremental-basedir 指定上次备份的目录:

xtrabackup --backup \ --target-dir=/data/backup/inc1 \ --incremental-basedir=/data/backup/base

恢复时对每个增量目录按顺序 apply log,最后统一 prepare。编译版本与数据库版本严格匹配,增量备份过程中的 LSN 衔接才会可靠,这也是我坚持源码编译而不是随便捡一个二进制来用的原因。

6. 几个对 ARM 环境很实用的细节

6.1 用 ccache 给后续编译加速

如果后续要多次编译不同版本的 xtrabackup,建议在工具链里加上 ccache。它的作用是缓存编译中间产物,同一个编译单元没变化时直接命中缓存,大幅缩短重复编译时间。安装和启用都很简单:

yum install -y ccache

CMake 配置时加上:

-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache

首次编译时 ccache 还没有实际效果,但第二次再调整参数重新编译时,体感差异会非常明显,值得提前埋好这颗种子。

6.2 多台机器共享编译产物

如果手上的 ARM 服务器不止一台,千万不要一台一台单独编译。把第一台编译好的 xtrabackup、xbstream 等二进制放到一个统一路径,然后用 tar 打包分发到其他机器,放到相同目录,运行 ldd 确认依赖库一致即可。这种做法的前提是机器的操作系统版本和架构一致,如果内核版本差距很大,建议还是单独编译,避免动态库接口不兼容的问题。

6.3 备份脚本纳入日常巡检

编译和验证都通过后,把备份操作脚本化,并纳入定时任务。脚本里至少要做三件事:检查备份进程是否正常启动、检查备份目录的产物是否生成、检查 xtrabackup_info 文件的 LSN 是否有变化。备份报警比备份本身更重要,一条简单的 LSN 变化监控,能在备份静默失败时及时提醒你。

编译这套流程走下来,我个人最大的感受是,真正耗时间的不是 make 那几十分钟,而是处理“新工具与旧系统生态之间的认知差异”。提前把系统架构、gcc 版本、依赖库状态摸清楚,很多坑都能在动手前就避开。xtrabackup 的源码编译并不神秘,每一步搞清楚它在干什么,换到其他国产发行版、其他 CPU 架构,这套方法论依然能复用。备份工具是数据安全的最后一道防线,值得多花点时间把它弄扎实。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询