
简介本资源为MySQL 8.0.31官方原版Linux ARM64架构二进制发行包专为基于aarch64平台的国产化服务器、ARM云主机及嵌入式Linux环境设计适用于数据库运维工程师、信创适配工程师及高校数据库课程实践者。压缩包共337个文件包含88个动态链接库so、39个可执行二进制文件如mysqld、mysql、mysqladmin等核心组件、25个XML配置模板、24个系统表定义sys及16个头文件h完整覆盖服务启动、客户端工具、安全加固mysql_secure_installation、备份恢复mysqldump、日志解析mysqlbinlog等全链路功能。包体大小488.08MB结构规范无需编译即可解压部署。目前已有1078人下载学习适合开展ARM平台MySQL部署验证、信创环境数据库迁移测试及高版本特性如原子DDL、JSON增强、角色权限模型实操训练。 拿到mysql-8.0.31-linux-glibc2.17-aarch64.tar.gz这个文件名你应该已经猜到这又是一台 ARM 架构的服务器在等着装 MySQL 了。这个文件名看着长其实信息量非常大MySQL 8.0.31、Linux 平台、依赖 glibc 2.17 编译、面向 aarch64ARM64架构的通用二进制包。说白了这就是那种“解压就能用”的安装包不需要 rpm、也不需要 deb适合在各类云服务器、信创环境、ARM 开发板上部署 MySQL 时使用。我在实际部署中遇到过不少朋友在这个文件上栽跟头要么是解压完激活服务时报 glibc 版本不对要么是初始化数据目录的时候缺 libaio再要么是配好了 systemd 却怎么都起不来。这篇文章我就基于这个包把从文件名解读到安装、初始化、调优、问题排查的完整过程全部拆开讲一遍。不管你是想在自己的 ARM 云服务器上装一个还是公司里刚采购了一批申威、鲲鹏、飞腾或者倚天处理器的机器需要部署数据库这篇文章应该都能帮你省下不少折腾的时间。1. 先读懂文件名8.0.31、glibc2.17、aarch64 到底意味着什么很多人在拿到安装包的时候不会特意去拆解文件名觉得“能装上就行”。但恰恰是文件名里的这些字段决定了这个包能不能在你的系统上直接跑起来。我建议每一位做运维或者后端开发的朋友都养成“先读文件名再执行命令”的习惯因为很多装不上、跑不起来的坑早在文件名里就写明白了。1.1 版本号背后的选择逻辑为什么是 8.0.31MySQL 8.0 系列从 2018 年发布以来已经经历了非常多的迭代版本。8.0.31 属于 8.0 系列中期靠后的一个稳定版本它包含了前面版本积累的大量 bug 修复和性能改进同时又不像后面一些版本那样带上了让人纠结的“新坑”。在企业生产环境中8.0.31 是一个被广泛验证过的版本。很多公司内部的镜像源、离线安装包至今还保留着这个版本号原因就是它足够稳。8.0 相比 5.7 有一个非常核心的变化数据字典不再使用 MyISAM 存储而是统一放进了 InnoDB。这就意味着 mysql 系统库里的表无法再用 MyISAM 引擎来绕过事务问题整个数据库的一致性、崩溃恢复能力都上了一个台阶。加之 8.0 引入了窗口函数、公用表表达式CTE、原子 DDL 等特性对开发侧来说某些复杂查询终于可以用更清晰的 SQL 写出来而不是拆成几条语句在应用层拼逻辑。这个版本还有一个隐藏的优势就是它对 ARM 架构的支持已经比较成熟不像 5.7 时代在 aarch64 上偶尔会遇到奇怪的编译或运行问题。如果你手头有选择余地我的建议是不要看到“8.0”就闭眼装最新小版本稳定生产环境优先选择 8.0.2x 到 8.0.3x 之间的小版本8.0.31 恰好落在这个区间里。装完之后记得关注官方补丁和后续小版本升级公告数据库这种基础组件稳定性始终是第一位的。1.2 编译依赖与架构标识glibc 2.17 和 aarch64接下来是glibc2.17和aarch64这两个字段。先讲 glibc。glibc 是 Linux 系统里最底层的 C 运行库几乎所有的用户态程序都在跟它打交道。MySQL 官方编译二进制包的时候会选定一个 glibc 版本来链接这个版本号会直接写进包名里。为什么因为动态链接的二进制程序在运行时会加载系统里的 libc.so.6如果系统的 glibc 版本比编译时用的版本还老那程序可能连启动都启动不了或者运行到某些函数时直接报__libc_start_main找不到符号之类的错误。glibc 有一个很重要的特性向后兼容。也就是说用 glibc 2.17 编译出来的程序可以在 glibc 2.17 及更高版本的系统上运行比如 2.28、2.34都没问题但反过来在 glibc 2.17 的系统上运行一个用 glibc 2.28 编译的程序大概率会直接报错。这也是为什么 MySQL 官方会同时提供 glibc2.12、glibc2.17 等不同版本的二进制包目的就是覆盖不同年代、不同发行版的 Linux 系统。glibc2.17这个标签对应的是 CentOS 7、RHEL 7 这一批系统以及很多基于 CentOS 7 衍生出来的国产系统比如麒麟 V10、欧拉 20.03 的某些版本。如果你的系统是 CentOS 8 或更新的发行版glibc 版本通常已经高于 2.17那直接使用这个包也没有问题因为向后兼容。再来看aarch64。这个词指的就是 ARM 64 位架构也叫 ARM64。我们平时在云服务器上最常接触的是 x86_64也叫 amd64但 ARM 架构的服务器近几年在云计算领域越来越普及。AWS 的 Graviton 系列、阿里云的倚天 710、华为的鲲鹏处理器、飞腾的 FT-2000 系列跑的都是 aarch64 指令集。aarch64 和 x86_64 是完全不同的指令集架构二进制文件不能互相运行所以 MySQL 官方必须分别编译这两个架构的版本。你在下载的时候一定要看清楚如果是 ARM 服务器必须下载aarch64标识的包如果是 x86_64 服务器就下载x86_64标识的包。这俩一旦搞反了执行./bin/mysqld的时候就会报Exec format error这类错误和权限、配置都没关系纯粹是 CPU 指令不识别。2. 为什么选择 tar.gz解压就能用的安装包 vs 包管理器有人会问Linux 上装 MySQL 有那么多方式为什么偏偏要下载这个 tar.gz 包这其实和部署场景有直接关系。不同安装方式各有各的适用环境tar.gz 形式的通用二进制包在跨环境部署、离线部署、自定义路径部署这些场景下有着 rpm 和 deb 不可替代的优势。2.1 三种安装方式的适用场景对比我先用一张表把常见的安装方式整理出来方便你对号入座安装方式适用场景优点缺点rpm / deb 包标准发行版单机快速安装安装快和系统包管理集成自动创建用户和服务路径固定定制麻烦依赖关系有时很烦Docker 容器微服务、隔离环境、多版本共存环境隔离部署一致升级回滚方便性能有轻微损耗需要维护镜像和数据卷tar.gz 通用二进制特殊架构、离线环境、自定义路径、批量复制解压即用可放到任意目录一台机器装好直接打包分发需要手动创建用户、初始化、配置服务在实际部署中我遇到最多的还是改路径的需求。公司内部往往对磁盘挂载有规范比如数据盘要单独挂到/data下数据库安装目录要放在/app或者/opt下。rpm 装出来的 MySQL 默认目录散落在/usr、/var、/etc各处想整体搬家非常难受。而 tar.gz 包解压出来只有一个目录数据目录、日志目录、配置文件都可以通过my.cnf自由指定整个实例相当于“装在一个文件夹里”迁移的时候打包带走就行。2.2 什么环境下必须用 tar.gz 包除了路径自由之外还有一个非常现实的情况很多 ARM 架构的服务器特别是国产化替代背景下的机器系统默认的软件源里根本没有 mysql-server 的安装包或者包的版本非常老旧。你运行yum install mysql-server结果发现安装的是 MariaDB或者版本停在 5.7。这时候去官网下载对应的 tar.gz 包就是最直接、最可控的方案。还有一种场景是批量离线部署。内部环境往往和外网隔离如果有一台同构机器做跳板你在跳板机上把 MySQL 解压好、初始化好、配置好然后用tar把整个目录打个包分发给几十台相同硬件、相同系统的服务器再用自定义脚本改一改 server_id 和数据目录权限就能快速拉起一套数据库集群。这种复制部署方式用 rpm 是实现不了的。当然同构指的是 CPU 架构和操作系统发行版都一致否则拷贝过去也跑不起来。提示tar.gz 包也有它的“潜规则”。MySQL 官方对 tar.gz 包的支持策略是“no install”——也就是说官方不做自动安装脚本所有初始化、启动、守护进程管理都需要你自己完成。如果你不太熟悉系统级的用户管理、systemd 配置第一次上手可能会觉得有点繁琐但熟练之后你会觉得这种方式反而最透明每一步都看得见摸得着。3. 安装前的准备工作先别急着解压我见过太多人拿到安装包解压完就开始初始化数据库结果报了一堆错回头又是一顿搜索。其实这些报错里有一大半是可以在解压前就排除掉的。安装 MySQL 这种基础组件花 5 分钟做环境检查能帮你省下后面 50 分钟的排错时间。3.1 检查硬件架构和系统 glibc 版本拿到包之后第一件事是在目标服务器上确认两件事CPU 架构是不是 aarch64系统的 glibc 版本是多少。这两条命令基本是固定的uname -m ldd --version我建议你同时用getconf GNU_LIBC_VERSION再确认一次因为某些精简环境下ldd --version的输出可能不太直观。uname -m的输出应该是aarch64如果显示x86_64那说明你下载错包了ldd --version的第一行会显示 glibc 的版本号比如2.17、2.28、2.34等。只要这个版本号大于等于 2.17包名里的glibc2.17就不构成障碍可以直接继续。这里还要提一个容易踩的坑不要在 ARM 环境的容器里直接拿本机的 glibc 版本去判断宿主机。容器里的 glibc 版本取决于镜像宿主机上的 glibc 版本取决于 OS。如果你是在 Docker 容器里部署 MySQL要检查的是运行容器的那个基础镜像的 glibc 版本而不是宿主机的。否则你可能会发现容器里报version GLIBC_2.17 not found或者反过来version GLIBC_2.28 not found原因就是镜像里的 glibc 和二进制包的要求不匹配。3.2 创建用户与目录规划MySQL 官方文档强烈建议不要用 root 用户运行 mysqld。虽然你直接用 root 也能把它跑起来但一旦数据库被入侵攻击者拿到的是 MySQL 进程权限如果这个进程是 root 权限后果不堪设想。所以安装前需要创建一个专用的系统用户groupadd mysql useradd -r -g mysql -s /bin/false mysql这里的-s /bin/false表示给这个用户一个不能登录的 shell只用来跑系统服务安全性更高。接着规划目录。我通常把安装目录放在/usr/local/mysql数据目录单独放在/data/mysql日志统一放在/var/log/mysqlmkdir -p /usr/local/mysql mkdir -p /data/mysql mkdir -p /var/log/mysql chown -R mysql:mysql /data/mysql chown -R mysql:mysql /var/log/mysql注意安装目录/usr/local/mysql先不用改属主解压完之后让 root 持有安装目录、mysql 用户持有数据目录和日志目录这样既能避免安装文件被误改也能保证运行时的读写权限没问题。这种“程序目录归 root、数据目录归 mysql”的做法和官方二进制包的部署规范是一致的。3.3 安装依赖库libaio 与 ncursesMySQL 的 InnoDB 存储引擎在 Linux 上依赖libaio这个异步 IO 库没有它会直接导致初始化失败报错大概是error while loading shared libraries: libaio.so.1: cannot open shared object file。不同系统的安装命令不一样# CentOS / RHEL / 麒麟 yum install -y libaio ncurses-libs # Ubuntu / Debian apt-get install -y libaio1 libncurses5另外numactl这个工具在 ARM 多路服务器上也建议提前装上。很多 ARM 服务器是 2 路甚至 4 路 CPU 的物理机内存访问有 NUMA 拓扑的问题MySQL 在 NUMA 架构下最好能绑定内存分配策略后面讲到性能调优的时候会细说。安装命令也很简单yum install -y numactl # 或 apt-get install -y numactl提示如果你用的是 docker 镜像务必在 Dockerfile 里就用yum install或者apt-get install把依赖装进去不要等容器运行之后再手动装因为容器一销毁就全没了。这是我维护镜像时最常提醒自己的点。4. 一步步完成安装初始化、启动与开机自启环境检查完毕、依赖装好之后就可以进入正式安装流程了。这一部分我会按照实际操作的顺序来写命令和路径都使用我前面规划好的目录结构。不建议你跳过任何一步尤其是初始化和权限设置少一步都可能让你在后面的启动环节反复折腾。4.1 解压与目录迁移首先把安装包传到服务器上比如/opt/目录然后解压。MySQL 官方二进制包解压出来会带一个完整的版本号目录比如mysql-8.0.31-linux-glibc2.17-aarch64。考虑到后续升级的便利一般会做一个软链接指向具体的版本目录cd /opt tar -xvf mysql-8.0.31-linux-glibc2.17-aarch64.tar.gz mv mysql-8.0.31-linux-glibc2.17-aarch64 /usr/local/mysql-8.0.31 ln -s /usr/local/mysql-8.0.31 /usr/local/mysql这样设计的好处是以后你想升级到 8.0.32只需要把新版本解压到旁边把软链接重新指向新目录保留原来的数据目录不变就能安全切换。尤其在生产环境里升级出问题要回滚直接把软链接改回去就可以大大降低风险。解压完之后把 bin、lib 等路径加进环境变量方便后续直接执行 mysql 命令echo export PATH/usr/local/mysql/bin:$PATH /etc/profile.d/mysql.sh source /etc/profile.d/mysql.sh4.2 my.cnf 关键参数解析MySQL 启动的时候会按固定顺序查找配置文件常见的路径包括/etc/my.cnf、/etc/mysql/my.cnf、/usr/local/mysql/my.cnf等。我建议把配置文件统一放在/etc/my.cnf这样最直观排查问题的时候也方便。下面是一个在 aarch64 服务器上生产可用的基础配置模板你可以根据自己的内存和磁盘情况调整[mysqld] basedir/usr/local/mysql datadir/data/mysql socket/tmp/mysql.sock port3306 pid-file/var/run/mysqld/mysqld.pid log-error/var/log/mysql/error.log # 字符集 character-set-serverutf8mb4 collation-serverutf8mb4_general_ci # InnoDB 核心参数 innodb_buffer_pool_size2G innodb_log_file_size256M innodb_flush_log_at_trx_commit1 innodb_file_per_table1 # 连接数 max_connections1000 max_connect_errors100000 # binlog 配置 server-id1 log-bin/data/mysql/binlog binlog_formatrow expire_logs_days7这里重点解释几个容易理解错或者踩坑的参数。innodb_buffer_pool_size是 InnoDB 最重要的内存参数它决定了 InnoDB 缓存数据和索引的内存池大小。对于专机专用的 MySQL 实例一般建议设置为物理内存的 60%~70%。如果你的服务器只有 4G 内存设置 1G~2G 比较合适32G 内存的机器可以给到 16G~20G。这个值设得太小会导致频繁磁盘 IO设得太大则可能和操作系统自身的内存争抢引发 swap 甚至 OOM。innodb_log_file_size是 redo log 单个文件的大小默认值是 48M但生产环境建议至少 256M否则写频繁时容易产生明显的 IO 瓶颈。需要注意的是修改这个值和 buffer pool 不一样不会即时生效需要重启 MySQL并且 MySQL 8.0.30 之后引入了 redo log capacity 配置如果你下载的是 8.0.31也可以直接设置innodb_redo_log_capacity来替代原来的两个 log file 参数。socket/tmp/mysql.sock这个路径虽然用得多但在某些系统上/tmp会被 systemd 的私有临时目录机制隔离导致其他进程访问不到这个 socket 文件。比较稳妥的做法是放到/var/run/mysqld/mysqld.sock或者/data/mysql/mysql.sock并且确保目录存在mkdir -p /var/run/mysqld chown mysql:mysql /var/run/mysqld不然启动的时候很容易遇到Cant start server: Bind on unix socket: No such file or directory的报错。这个错我见过很多人在/tmp模式下排查半天其实换成运行目录就解决了。binlog建议从第一天就开启。你可能会觉得现在不开 binlog 也跑得好好的但一旦遇到误删数据、需要做时间点恢复的时候没有 binlog 就真的回天乏术了。binlog_formatrow是 8.0 的推荐模式RBR 模式比 SBR 模式在数据一致性方面更可靠配合主从复制和 CDC 工具也更方便。expire_logs_days7表示保留 7 天的 binlog避免日志无限堆积占满磁盘。4.3 数据目录初始化与首次登录配置写好后执行初始化命令。这一步的目的是在/data/mysql下生成 MySQL 自身的系统表、数据字典和初始账户信息。8.0 版本推荐使用下面的命令/usr/local/mysql/bin/mysqld --initialize --usermysql --basedir/usr/local/mysql --datadir/data/mysql--initialize会创建一个带随机密码的 root 用户并且仅允许本地登录。这个随机密码会打印到错误日志里也就是我们在 my.cnf 里配置的/var/log/mysql/error.log。初始化完成后用下面命令查看grep temporary password /var/log/mysql/error.log这条命令会输出类似这样的内容[Note] A temporary password is generated for rootlocalhost: xxxxxxxxxx把这个密码记下来后面首次登录要用。如果用--initialize-insecure初始化会生成一个空密码的 root 用户方便是方便但在生产环境我强烈不建议任何人只要知道端口就能在服务器上尝试连接 root安全性太差。初始化完成后启动 MySQL。最简单的启动方式是/usr/local/mysql/bin/mysqld_safe --usermysql mysqld_safe是官方提供的守护脚本它会自动重启崩溃的 mysqld 进程。不过在生产环境我更推荐用 systemd 来管理因为它有更完整的进程管理和日志收集机制mysqld_safe只是兜底方案。先确认 MySQL 能通过mysqld_safe顺利启动再配 systemd这样排错更容易。启动后用刚才记下的临时密码登录mysql -uroot -p进入 MySQL 后第一件事就是改密码。MySQL 8.0 默认密码插件是 caching_sha2_password如果你的应用是较老的客户端驱动可能连接的时候会报认证插件不兼容。这种情况有两个选择一是升级驱动二是把用户的认证插件改回 mysql_native_password。我建议优先升级驱动因为 8.0 原生的加密方式更安全而且老的插件在后续版本中可能会被废弃。ALTER USER rootlocalhost IDENTIFIED BY 你的新密码;如果需要允许远程登录可以创建专用账号而不是直接暴露 root。比如CREATE USER app% IDENTIFIED BY app_password; GRANT ALL PRIVILEGES ON *.* TO app%; FLUSH PRIVILEGES;如果你想先验证一下本地连接是否正常再继续配置远程那SELECT VERSION();是最直接的测试语句。能看到 8.0.31 的版本号说明实例已经正常工作。4.4 配置 systemd 服务为了让 MySQL 在开机时自动启动、崩溃时能被 systemd 拉起需要创建一个 service 文件。路径是/etc/systemd/system/mysqld.service[Unit] DescriptionMySQL Server Documentationman:mysqld(8) Afternetwork.target [Service] Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf LimitNOFILE65535 Restarton-failure RestartSec5 [Install] WantedBymulti-user.target创建完成后执行systemctl daemon-reload systemctl enable mysqld systemctl start mysqld systemctl status mysqld需要注意ExecStart使用mysqld而不是mysqld_safe。在 systemd 管理模式下守护、重启逻辑由 systemd 负责mysqld_safe只会画蛇添足。如果你的 service 文件也放到了/etc/systemd/system/下但启动之后系统报 “Permission denied”先检查一下/data/mysql、/var/log/mysql和/var/run/mysqld这三个目录的属主是否都是 mysql这个问题 90% 都是由目录权限引起的。开机自启还需要考虑一点如果系统里原本就有其他 MySQL 或者 MariaDB 的服务端口 3306 会冲突。启动前先ss -lntp | grep 3306看一眼确保端口没被占用。这个检查同样很简单但能帮你避免“MySQL 起不来”的错觉。5. aarch64 上的性能与稳定性调优ARM 服务器的架构和 x86 有一些本质差异。你要是不了解这些差异直接照搬 x86 服务器上的配置性能可能不会太差但也没发挥出 ARM 服务器的全部能力。这里聊几个在 aarch64 环境下我应该优先确认和调整的点。5.1 内存分配与 NUMA 感知很多 ARM 服务器是双路甚至四路物理机每颗 CPU 都有自己直连的内存条这就形成了 NUMA非一致性内存访问架构。程序访问本地内存的速度远快于访问远端内存如果 MySQL 的内存分配策略没做好可能出现某颗 CPU 的内存被耗尽而另一颗 CPU 的内存还大量空闲的情况性能也随之下降。检查系统是否启用 NUMA 非常简单numactl --hardware如果输出里available大于 1说明存在多个 NUMA node。接下来的策略是让 MySQL 进程的内存分配尽量分散到所有 node 上避免集中在一个 node。过去有人建议直接numactl --interleaveall但这种方法在 MySQL 8.0 下的表现其实不稳定。更稳妥的做法是配置 mysqld 的innodb_numa_interleave参数在 my.cnf 中加入innodb_numa_interleaveON这个参数会让 InnoDB 在 buffer pool 分配内存时交错使用所有 NUMA node这个是最省心且官方支持的方式。my.cnf修改后重启 MySQL 即可生效。如果你在日志里看到类似libnuma: Warning: /sys not mounted or not accessible的提示多半是容器里没有挂载/sys可以忽略但说明当前环境不太适合依赖 NUMA 策略的部署模式。5.2 InnoDB 核心参数与常见调整InnoDB 的参数调整是 MySQL 调优的主战场。除了前面提到的 buffer pool 和 redo log还有几个参数值得花时间理解。innodb_flush_method控制在 InnoDB 如何将数据刷到磁盘。在 aarch64 Linux 环境下主流配置是O_DIRECT。它跳过操作系统 page cache直接把数据写入磁盘减少 double-buffer 带来的额外内存消耗和 CPU 拷贝开销。但要注意如果磁盘本身是网络存储NFSO_DIRECT 可能不被支持这时候需要退回到默认的fsync模式。innodb_io_capacity和innodb_io_capacity_max告诉 InnoDB 这台机器的磁盘 IO 能力。如果你用的是 NVMe 固态盘默认的 200 明显偏低建议调高到 2000~10000如果还是机械盘保持 200 更加稳妥。设得太高可能导致刷脏页过于激进反而拖慢前台请求设得太低则可能让后台刷脏跟不上出现周期性 IO 卡顿。还有一个容易被忽略的参数是table_open_cache。8.0 默认是 4000但在表数量非常多的业务库中这个值经常不够用导致频繁的打开和关闭表文件消耗大量系统调用。我遇到过一张业务库里有五六千张表的场景把table_open_cache提到 8000 后问题明显缓解。调整方式是动态修改不需要重启SET GLOBAL table_open_cache 8000;之后再把参数写进 my.cnf 持久化。我还想提一个性能观察点通过SHOW ENGINE INNODB STATUS可以看到 InnoDB 当前的状态。如果里面有大量 “history list length” 很高但 purge 跟不上的情况说明事务回收有问题往往和长事务或者 read view 泄漏有关这时候再去调整参数是次要的先处理业务侧的长事务才更关键。5.3 日常运维常用查询速查部署完成、性能参数也设置好之后日常维护中还经常会用到一些查询。这里整理几个高频命令新同学可以直接抄作业。连接数与线程状态SHOW VARIABLES LIKE max_connections; SHOW STATUS LIKE Threads_connected; SHOW PROCESSLIST;SHOW PROCESSLIST可以查看当前正在执行的 SQL如果 State 列出现大量Waiting for table metadata lock大概率是有会话长时间持有表锁下一步就该去查哪个连接卡住了。这是排查“数据库突然变慢”时最常用的入口。缓冲池命中率SHOW GLOBAL STATUS LIKE Innodb_buffer_pool_read%;通过Innodb_buffer_pool_read_requests和Innodb_buffer_pool_reads可以估算 buffer pool 命中率。如果命中率长期低于 95%说明innodb_buffer_pool_size有提升空间或者某些大表忽略了索引扫描导致 InnoDB 频繁读磁盘。排序和 limit 查询相关EXPLAIN SELECT * FROM orders ORDER BY created_at DESC LIMIT 20;这里有个经验MySQL 8.0 的排序并不总是需要 filesort如果排序字段能利用索引就会走 index 扫描但如果语句里LIMIT太大或者排序字段和查询字段不匹配filesort 就会发生。对于分页查询LIMIT 100000, 20这种深翻页其实是性能杀手因为 MySQL 要先扫描前面 100000 行再丢弃。比较实用的优化手段是使用“延迟关联”先通过覆盖索引查出主键再用主键回表取出完整行。这在订单列表、日志列表这种高频且深翻页的场景里非常有效。这个优化思路在我的项目里屡试不爽建议在面试和实际工作中都重点掌握。6. 高频问题排查实录这部分我从自己经历过的排障过程里挑了最典型的几个场景每一个都在 ARM 平台上真实遇到过。如果你觉得自己的报错信息也能对号入座可以直接跳到对应小节。6.1 glibc 版本不匹配这报错从哪冒出来的很多人第一次跑mysqld的时候会在屏幕上看到类似version GLIBC_2.28 not found的错误这时候千万别慌先确认这个报错是不是 MySQL 本身产生的。如果你下载的确实是mysql-8.0.31-linux-glibc2.17-aarch64.tar.gz那它要求的是 glibc 2.17一般不会在 CentOS 7 或者麒麟 V10 上出现GLIBC_2.28找不到的问题。那为什么会看到这个错通常是你执行了某个在线安装脚本或者某个工具自带的运行库要求更高版本的 glibc比如某些新版本 Python、Node.js 或者 xtrabackup 在 aarch64 上编译时使用了更高的 glibc。排查思路很简单用 root 用户看实际的报错来源文件ldd /usr/local/mysql/bin/mysqld | grep not found如果mysqld的动态库依赖全部满足说明 MySQL 本身没问题问题出在调用方式上。如果确实有动态库缺失还可以用objdump -T查看这个二进制里引用的最高 glibc 符号objdump -T /path/to/binary | grep GLIBC_ | sort -V | tail比如看到GLIBC_2.34而系统只有 2.17那么无论你多么努力这个二进制都不可能在当前系统上运行。解决办法是寻找相应系统的编译版本或者用老版本工具。这里要强调一下千万不要试图替换系统自带的 glibc 或者去下载“新版 glibc”覆盖那会把整个操作系统搞崩。很多入门的新手一搜到 glibc 报错就去替换/usr/lib64/libc.so.6这是极端危险的操作轻则系统命令全部失效重则直接无法开机。glibc 毕竟是系统最底层的东西它的更新必须跟随发行版更新而不是手动替换。6.2 libaio.so.1 缺失初始化 MySQL 数据目录时报libaio.so.1: cannot open shared object file这是我在 ARM 服务器上遇到的最常见的“前置条件缺失”报错。原因很简单MySQL 使用 libaio 进行异步 IO但很多精简系统镜像没有预装这个库。解决方式就是装依赖yum install -y libaio装完后重新执行ldd /usr/local/mysql/bin/mysqld | grep libaio能看到libaio.so.1不再是缺失状态再跑初始化命令就正常了。这个错误和 aarch64 架构本身没关系x86 平台同样会遇到只是 ARM 平台的镜像普遍更精简触发概率更高。6.3 服务起不来权限、SELinux 与端口MySQL 启动失败时第一件事永远是看错误日志。log-error指定的那个日志文件信息量和准确率远高于终端输出。我见过非常多的人启动失败后第一反应是疯狂百度但错误日志里往往已经写清楚了原因。常见的启动失败原因有以下几种。目录权限问题错误日志里有类似Permission denied或者Cant create/write to file ...那基本就是数据目录或者日志目录的属主不对。执行chown -R mysql:mysql /data/mysql chown -R mysql:mysql /var/log/mysqlSELinux 问题CentOS 7 默认开启 SELinuxMySQL 的端口、数据目录都有可能被限制。快速判断方法getenforce如果是Enforcing可以尝试先临时关闭 SELinuxsetenforce 0再启动 MySQL如果确实能启动说明就是 SELinux 拦截。生产环境不建议直接关掉 SELinux更合理的做法是给 MySQL 的端口和目录依次设置正确的 SELinux 策略或者使用审计日志看具体被拒绝的对象ausearch -m avc -ts recent端口占用用ss -lntp | grep 3306检查。如果是别的服务占用了 3306可以选择修改 my.cnf 的端口号或者停掉冲突服务。这里也提醒一下不要简单地因为“3306 被占了”就随手改成 3307要和业务侧确认一下连接配置的端口再改。防火墙云服务器默认有安全组本地有 firewalld 或者 ufw。即便 MySQL 正常在监听 3306外部连接不上也要查一下这两层。本地防火墙命令行有很多推荐记住这一条firewall-cmd --add-port3306/tcp --permanent firewall-cmd --reload如果还是连不上就去云控制台查看安全组是否放通了来源 IP 和 3306 端口。6.4 远程连接失败与认证插件不兼容MySQL 8.0 的默认认证插件是caching_sha2_password如果你用的是比较老的客户端或者编程语言驱动比如老版本 JDBC、Python 的mysqlclient1.4 之前的版本连接时会报Authentication plugin caching_sha2_password cannot be loaded这是 8.0 升级带来的兼容性问题。处理方式有两种。第一种是升级客户端驱动这是我的首选方案从根源解决也是官方推荐的方向。第二种是在服务器上把这个用户的认证插件改回老式的mysql_native_passwordALTER USER app% IDENTIFIED WITH mysql_native_password BY app_password;在迁移老业务或者临时环境里第二种方式可以快速解决问题。但需要注意MySQL 官方在 9.0 中已经移除了mysql_native_password插件的支持8.0 系列只是过度的兼容阶段。如果你现在新建的项目建议一开始就使用caching_sha2_password插件配合驱动升级避免以后被迫再改一次。远程连接超时还需要检查另一层如果你用云服务器即使本机监听正常防火墙放行正常只要安全组没有放行对应端口外部照样连接失败。这时候你在本机用mysql -h 内网IP -P 3306能通但用公网 IP 连却超时基本可以确定是安全组配置的问题。还有一种情况服务器有多张网卡mysqld 默认监听所有地址所以没问题但如果配置里写了bind-address127.0.0.1远程连接肯定失败。8.0 里如果只允许本机连就明确写bind-address127.0.0.1要允许某网段的机器连接就写成对应的内网 IP如果希望所有来源都连配置0.0.0.0但生产环境不建议这样裸奔配合防火墙或者安全组只放开白名单才是正解。上面这些排查项如果能按顺序走一遍绝大多数“MySQL 起不来”的问题都能定位到具体原因。还是那句话看日志看权限看端口看防火墙这四步解决了数据库部署 90% 的问题。写到这里关于mysql-8.0.31-linux-glibc2.17-aarch64.tar.gz的完整部署过程就全部说完了。最后再分享一点我个人的经验在 ARM 架构的服务器上部署 MySQL和 x86 架构没有本质区别tar.gz 安装的核心流程和配置项基本通用真正容易出问题的始终是 glibc 版本匹配、目录属主、SELinux/防火墙这三类环境问题。如果按照上面说的步骤走一遍还是有问题建议对照错误日志逐行排查并且尽量把头一次安装时的报错信息保留完整因为网上搜到的很多 ARM 相关报错内容和你的实际场景往往差了几个关键变量。这个包后续还能怎么用如果你已经用 tar.gz 方式部署成功完全可以把它当作一个“便携版 MySQL”来打底比如基于这个目录做一个精简的 Docker 镜像或者用 rsync 同步到其他同构机器上快速扩容。我个人建议你在正式接入业务流量之前先跑一遍 sysbench 或者简单的压测工具确认 CPU 频率、内存带宽在压力下没有异常这样后面业务上线的时候心里更有底。本文还有配套的精品资源点击获取