简介:mysql-5.7.32-linux-glibc-2.28-aarch64.tar.gz 是为 ARM64(AArch64)Linux 环境预编译的 MySQL 5.7.32 官方二进制发行包,面向树莓派 4、ARM 云服务器等设备的使用者,可直接部署数据库而无需手动编译。压缩包约 510.16MB,共 14882 个文件,其中 result、inc、cnf、so、pem 等类型分别对应测试用例、头文件、配置模板、动态库与安全证书,附带数据目录、日志及 binlog 样例,结构完整便于排查维护。已有 1418 人学习下载。该包的价值不只是免编译安装,更在于通过内置的 mysqld、mysql_secure_installation、mysql_upgrade 等工具,以及清晰的目录组织,帮助 ARM 用户快速完成初始化、安全加固和日常运维;对希望掌握 MySQL 在非 x86 平台运行机制的开发者同样有参考意义。
1. 一份 MySQL 5.7.32 ARM 二进制包,值不值得自己折腾编译
先给结论:如果你手头是一台 arm aarch64 的 Linux 服务器(某云的鲲鹏机型、飞腾机器,或者自建的树莓派、RK3588 开发板),装 MySQL 第一反应别去源码编译,风险太大,直接找官方编译好的 ARM 版 glibc tar.gz 是效率最高的路线。这个包的后缀linux-glibc-2.28-aarch64看着长,其实信息量很密——aarch64 指 CPU 架构,glibc-2.28 指动态链接器的最低版本要求,它对应的是 MySQL 官方对 ARM 平台的通用二进制分发,而不是某发行版带过的定制版。这篇笔记会把「这个包能用在哪、怎么装上、装完哪些参数必须动、哪些坑我踩过」一次说透。适合正在 ARM 服务器上部署生产或测试库的从业者,也适合想绕过编译流程尽快起一个可用环境的新手。
2. 拿到 tar.gz 先看懂三件事:架构、glibc 兼容性、启动方式
2.1 为什么是 aarch64 而不是 armv7 / x86_64
先拉齐一个概念。aarch64是 ARM 的 64 位指令集,平时说的 ARM64 就是它。常见的 ARM 服务器 CPU(某云的鲲鹏 920、飞腾 FT-2000,还有 Ampere Altra)跑的全是 aarch64。而以前的树莓派 3B 那种 32 位 ARMv7 核跑不了这个包,装了会报Exec format error,这个和 go 编译出的二进制架构不匹配一个道理。
判断你的机器是不是 aarch64,最快的方式:
uname -m # 输出 aarch64 说明没问题 # 输出 armv7l 或 armhf,这块包就装不了 ldd --version | head -n1第一句是看 CPU 架构,第二句是看 glibc 版本。linux-glibc-2.28要求系统 glibc 版本不低于 2.28,比如某发行版 22.04 的 glibc 是 2.35,能装;某发行版 18.04 的 glibc 是 2.27,装完启动会报version 'GLIBC_2.28' not found。这是最经典的一个兼容性坑,后面避坑章具体展开。
2.2 tar.gz 解压后的目录结构和官方 rpm 系的差异
这份资源解压后是一个mysql-5.7.32-linux-glibc-2.28-aarch64目录,里面带有bin/、lib/、share/、support-files/等目录。它和用apt install mysql-server装出来的最大区别是:没有/etc/mysql/my.cnf预设配置,没有systemd服务文件,没有自动创建的mysql系统用户。一切初始化都得自己动手,好处是路径完全可控,坏处是缺一步就起不来。
我习惯把解压后的目录软链成/usr/local/mysql,这样后续升级版本只需替换软链指向,不用改一堆脚本里的硬编码路径:
mkdir -p /data/mysql tar -xzf mysql-5.7.32-linux-glibc-2.28-aarch64.tar.gz -C /usr/local ln -s /usr/local/mysql-5.7.32-linux-glibc-2.28-aarch64 /usr/local/mysql # 创建专用用户,不让他登录 shell,最小权限原则 groupadd mysql useradd -r -g mysql -s /bin/false mysql chown -R mysql:mysql /usr/local/mysql /data/mysql注意几个点:解压路径放/usr/local下是 Linux 惯例,放/opt也可以,但/usr/local/mysql这个路径在大量 MySQL 文档和工具里是默认值,别标新立异。useradd -r建的是系统账号,-s /bin/false防止有人用这个账号登进 shell,这些都是生产环境基线操作。/data/mysql是数据目录,不要放在解压目录里,后面初始化时单独指定,理由后面讲。
2.3 启动方式:mysqld_safe 与 mysqld 直接跑的区别
官方 tar 包不带 systemd 脚本,启动方式有两个常规选择:mysqld_safe和直接mysqld --daemonize。
# 方式一:mysqld_safe,自带日志重定向、崩溃重启逻辑 /usr/local/mysql/bin/mysqld_safe --user=mysql --datadir=/data/mysql & # 方式二:daemonize 后台运行 /usr/local/mysql/bin/mysqld --user=mysql --datadir=/data/mysql --daemonize我一般用mysqld_safe。它的优势是 mysqld 进程意外退出后会自动拉起来,而且默认把错误日志写到--datadir目录的*.err文件里,排查问题直接tail -f那个文件。--daemonize更干净,但进程挂了没人管。测试环境随意,生产环境我建议要么mysqld_safe要么自己写 systemd unit 文件,不要裸奔。
3. 从零初始化到能连上库:完整手工部署流程
3.1 第一步:初始化数据目录
MySQL 5.7 把原来的mysql_install_db废弃了,初始化入口统一成了mysqld --initialize。初始化会往数据目录写入系统库(mysql、performance_schema、sys),并生成一个临时 root 密码,打印到错误日志里。
/usr/local/mysql/bin/mysqld --initialize \ --user=mysql \ --basedir=/usr/local/mysql \ --datadir=/data/mysql \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_general_ci # 初始化完成后,从错误日志里找临时密码 grep 'temporary password' /data/mysql/*.err几个关键参数说明:--basedir指向解压目录,--datadir指向数据目录,这两个参数必须显式给,否则 mysqld 会尝试用编译时默认路径(/usr/local/mysql/data),你会莫名其妙发现数据写到了别处。--character-set-server=utf8mb4是 5.7 里的一个最佳实践——如果不显式声明,默认的是latin1,存不了中文表情包和小语种字符,业务上线后再改字符集特别疼,表结构和索引都得重建。如果grep不到临时密码,先确认初始化是否真的执行成功,常见失败是--datadir目录非空,后面避坑章细说。
3.2 第二步:启动实例并修改 root 密码
初始化完成后就能启动了。注意一个容易被忽略的细节:MySQL 5.7.32 初始化后,root 账号默认只能在本地localhost登录,并且初始状态是 locked 的,需要通过临时密码登录后立刻改密码:
# 启动 /usr/local/mysql/bin/mysqld_safe --user=mysql --datadir=/data/mysql & sleep 5 tail -n 20 /data/mysql/*.err # 用临时密码登录,改密码 /usr/local/mysql/bin/mysql -uroot -p # 输入错误日志里的临时密码,然后执行: # ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewPassword'; # FLUSH PRIVILEGES;这个包的默认密码校验插件是validate_password_policy,初始是MEDIUM,意味着新密码必须包含数字、字母、大小写和特殊字符,且长度不低于 8 位。如果不想在生产环境留这种复杂度约束,可以在my.cnf里显式关闭,但说实话我建议保留——ARM 服务器上跑的库经常是对外提供 API 的,密码强度太低等于给扫描器送菜。
3.3 第三步:远端连接授权与最小配置落盘
MySQL 装好后,如果你只打算本机连,这步可以跳过。但绝大多数场景是让应用服务器通过内网连过来,所以需要授权一个非 root 账号,并确认远端访问权限:
CREATE USER 'appuser'@'10.0.0.%' IDENTIFIED BY 'AppUser@2024'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'10.0.0.%'; FLUSH PRIVILEGES;注意'appuser'@'10.0.0.%'里的 IP 段要换成你应用服务器的真实网段,不要一上来就'appuser'@'%',那是给自己留后门。MySQL 的授权是「用户 + 来源主机」双因子匹配,'appuser'@'localhost'和'appuser'@'192.168.1.7'是两个不同的账号,这点很多新手会犯迷糊。
完成了这些,一份最简可用的my.cnf也要同时落盘:
[mysqld] user = mysql basedir = /usr/local/mysql datadir = /data/mysql port = 3306 socket = /tmp/mysql.sock character-set-server = utf8mb4 collation-server = utf8mb4_general_ci max_connections = 200 innodb_buffer_pool_size = 1G log_error = /data/mysql/mysql-error.log这份配置的价值在于把关键路径和资源参数显式固定下来。max_connections = 200是保守值,先跑起来看监控再调;innodb_buffer_pool_size = 1G对应 4G 内存的 ARM 机器,一个通用起步值,后面单独讲怎么调。log_error单独指向文件,别让它混在--datadir里的.err里,排查问题更快。
4. 配置落盘后的性能底子:ARM 机器上必须动手的四个参数
4.1 innodb_buffer_pool_size:给头号内存消费者定额度
InnoDB 的 buffer pool 是 MySQL 占内存的大头,它缓存数据页和索引页,直接决定热数据查询走内存还是走磁盘扫描。5.7 默认值是 128M,对一个要跑真实业务的 ARM 服务器来说太小了。给多大合适?一个经验:主机物理内存的 50%~70%,在 8G 内存的某云 ARM 机器上,我一般给 4G~5G。
# 查看当前值和 InnoDB 缓冲池命中率 SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests'; SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';第一个变量是总读请求次数,第二个是从磁盘读的次数,后者除以前者的比值越小命中率越高。如果命中率长期低于 97%,buffer pool 大概率给小了。调大这个参数不需要重启,可以动态改,但生产环境我一般配合低峰期做 rolling restart,避免运行中调整造成的性能抖动。
4.2 innodb_flush_log_at_trx_commit:性能与安全之间的取舍
这个参数有三个值:0、1、2。默认是 1,意思是每次事务提交都要把 redo log 刷到磁盘,保证数据库崩溃后用 redo 恢复时不丢已提交事务——这是最安全点,同时也最费磁盘 IO。ARM 服务器的磁盘 IO 能力普遍弱于 x86 服务器,很多同事上来就改成 2(每秒刷一次 redo),快是真快,但宕机可能丢 1 秒的事务。
我的折中做法是:核心业务库保持 1,统计分析库、日志类库改成 2。这个参数在my.cnf里改,重启生效:
innodb_flush_log_at_trx_commit = 1 sync_binlog = 1sync_binlog = 1是另一个和 redo 配合的安全参数,控制 binlog 每次提交刷盘。两者都关了性能绝不是功能翻倍的提升,但你可能赢得了一个「数据库莫名其妙的慢」的玄学问题。对 ARM 单机部署来说,两台参数全开时的写入性能通常是最先触发瓶颈的,先用大页缓存和 SSD 顶一阵,然后再考虑主从分流。
4.3 performance_schema:低配机器上的资源消耗大户
performance_schema 是 MySQL 5.7 默认开启的监控项,它收集进程内部的等待、锁、IO 等细粒度数据,运维排查时非常好用,但代价是额外的内存和 CPU 消耗。在某云 2C4G 的 ARM 测试机上实测,这个模块能占到 300M~500M 内存,对配置有限的机器来说是不小的负担。
performance_schema = ON performance_schema_max_table_instances = 300如果你的 ARM 机器内存不宽裕,且有 zabbix 或 Prometheus 这类外部监控,可以考虑关掉它换回几百 M 内存。但注意:一旦关掉,SHOW ENGINE INNODB STATUS里一些诊断信息就没了,排查死锁只能靠日志和innodb_print_all_deadlocks参数来补。我通常的方案是 8G 内存以上就开着,4G 内存就关掉,外部监控兜底。
4.4 lower_case_table_names:初始化前想清楚,初始化后不改
这个参数决定表名和库名是否区分大小写。Linux 上 MySQL 默认值是 0(区分大小写),Windows 上默认是 1。如果你从 Windows 那边把一个库迁到 ARM Linux 上,原来用大小写混合表名的建表语句,到 Linux 上会报Table doesn't exist,慌得很。
设置方法是在初始化之前就写进my.cnf:
lower_case_table_names = 1为什么强调「之前」?5.7 里lower_case_table_names在初始化之后改动,会导致启动失败,因为数据目录里的表名已经被记录成原样,再改成 1 后对不上,mysqld直接拒绝启动。这是个「后悔药吃不了」的参数,上线前纠结清楚比上线后补救成本低得多。
5. 避坑:aarch64 机器上装 MySQL 的六条血泪记录
5.1 解压后启动报mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file
现象:直接运行bin/mysqld或者bin/mysqld_safe,终端直接报libaio.so.1找不到,进程起不来。
原因:MySQL 官方二进制包依赖libaio(异步 IO 库),但 Debian/Ubuntu 系服务器默认不装这个包。x86 机器上很多发行版可能碰巧预装了,ARM 机器的精简镜像几乎是裸系统,缺这个库的概率极高。
解决:装依赖包,不用动 MySQL:
apt-get update && apt-get install -y libaio1 libnuma1如果机器不能连外网 apt,可以从某发行版镜像站把libaio1的 deb 包拉下来装。别去自己编译 libaio,没那个必要,MySQL 官方文档里也是直接让你装依赖库。
5.2 启动报GLIBC_2.28 not found
现象:mysqld启动报错,用ldd bin/mysqld检查,若干.so标记not found,然后定位到GLIBC_2.28' not found。
原因:当前系统的 glibc 版本低于 2.28。linux-glibc-2.28-aarch64表示二进制要求的 glibc 最低版本是 2.28,比如 CentOS 7 ARM、Debian 9 这类老系统的 glibc 停在 2.27,直接跑不了。
解决:最干净的方案是升系统,而不是去升级 glibc——手工替换系统 glibc 是 Linux 运维界公认的翻车操作,一不小心整个系统所有命令全部崩掉。如果业务必须保留老系统,唯一可行的尝试是找linux-glibc-2.17-aarch64之类的低版本包,它在老系统上兼容性更好。
5.3 初始化报[ERROR] --initialize specified but the data directory has files in it
现象:执行mysqld --initialize时,终端直接给这个错误,初始化失败。
原因:--datadir指向的目录已经非空,通常是之前初始化失败残留了日志文件、系统库文件,或者你把数据目录指到了解压目录里,那里本就有一堆模板文件。
解决:把目录清空再初始化,注意别误删已有数据:
rm -rf /data/mysql/* /usr/local/mysql/bin/mysqld --initialize \ --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql如果你是在准备迁移数据,这个目录里有旧库文件,那就不是清空的问题,而是路径配错了,回头检查my.cnf里的datadir是否和旧库一致。
5.4 初始化时报[ERROR] Could not create directory或Permission denied
现象:初始化命令执行到一半,报无法创建目录或没有权限,数据目录一直是空的。
原因:数据库--user=mysql指向的账号没有--datadir路径的写权限。这个在 ARM 机上特别常见,因为数据盘通常单独挂载在/data,挂载点的父目录属主是 root,mysql 用户没权限写。
解决:
mkdir -p /data/mysql chown -R mysql:mysql /data chmod 750 /data/mysql注意如果/data是自己挂载的独立盘,确保挂载参数里没有noexec或nosuid会限制后续运行,以及/data本身的属组也要让 mysql 可写。
5.5 启动正常但本地mysql -uroot -p连不上,报Access denied
现象:客户端连接报错Access denied for user 'root'@'localhost',即使输入的密码是对的。
原因:这个包初始化时启用了 skip-name-resolve 或者 root 账号的 plugin 是auth_socket,而不是mysql_native_password或者caching_sha2_password。
解决:先用 sudo 或直接以 mysql 用户身份进入:
sudo /usr/local/mysql/bin/mysql -uroot进去后执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPassword'; FLUSH PRIVILEGES;如果 sudo 也进不去,停库后用--skip-grant-tables绕过认证表,进去先把 root 密码重置,再把权限表恢复锁定状态:
/usr/local/mysql/bin/mysqld_safe --skip-grant-tables --skip-networking &5.6 报错Table './xxx/yyy' is marked as crashed and should be repaired
现象:业务查询时报表损坏,应用侧错误日志疯狂刷这个提示。
原因:ARM 服务器上最常见的原因是意外断电或异常重启,数据文件没刷完。次因是磁盘 IO 故障,数据页写了一半。
解决:对 MyISAM 表执行REPAIR TABLE,对 InnoDB 表只能靠备份恢复,或者用innodb_force_recovery把实例拉起来导出数据:
innodb_force_recovery = 1这个参数从 1 到 6 逐级递增,6 级时只读,不再对数据文件做任何写操作。设成 1 启动成功后,立刻用mysqldump导表,导出后把参数注释掉再重启,从备份或导出文件恢复数据。记住:innodb_force_recovery是诊断工具,不是长期运行参数。
6. 加压验证:装完到上线前,至少完整走一遍这五步
到这一步说明数据库已经能稳定跑起来了,别急着交付。我每次在 ARM 机器上装完这个包,都会强制把下面这五步走完,缺一步都心里没底。这套流程是从一个生产事故后总结出来的——当时某个库上线第二天凌晨挂了,恢复后发现是安装时漏了权限加固和备份演练。
第一步,重启验证。kill掉 mysqld 再起来一次,确认mysqld_safe能自愈拉起 process,并且数据目录没有产生新的错误日志:
kill $(pgrep -f mysqld_safe) sleep 3 pgrep -f mysqld_safe || /usr/local/mysql/bin/mysqld_safe --user=mysql --datadir=/data/mysql &如果这步失败,大概率是上节第 5.5 条的认证问题没真正解决,或者my.cnf里写坏了路径。
第二步,冷备验证。用 5.7 自带的mysqldump把核心库完整导一遍,再导入一个临时库比对行数:
/usr/local/mysql/bin/mysqldump \ --single-transaction --quick \ -uroot -p'YourPassword' \ appdb > /backup/appdb.sql /usr/local/mysql/bin/mysql -uroot -p'YourPassword' -e "CREATE DATABASE appdb_bak DEFAULT CHARSET utf8mb4;" /usr/local/mysql/bin/mysql -uroot -p'YourPassword' appdb_bak < /backup/appdb.sql--single-transaction对 InnoDB 表做一致性快照,不加锁不加负担,线上备份必须带这个参数。--quick防止大表把内存撑爆。如果导入后行数和线上对得上,说明备份链路可用,这比什么书面承诺都靠谱。
第三步,连接池测试。模拟应用端的真实并发连接,用系统自带的mysqlslap加压,不需要额外装工具:
/usr/local/mysql/bin/mysqlslap \ --host=127.0.0.1 --port=3306 \ --user=appuser --password='AppUser@2024' \ --concurrency=50 --iterations=10 \ --query="SELECT COUNT(*) FROM appdb.orders" \ --create-schema=appdb--concurrency=50是同时起的线程数,--iterations=10是每个并发连执行次数,这两个值决定测试时长和压力级别。观察输出里的平均耗时,如果单次查询平均耗时超过 200ms,就要回头看 buffer pool 设置和磁盘 IO 了。
第四步,慢查询确认。打开慢查询日志,再跑一轮上面的mysqlslap,然后看日志里有没有漏网的大查询:
slow_query_log = ON long_query_time = 1 slow_query_log_file = /data/mysql/mysql-slow.loglong_query_time = 1是秒数阈值,超过 1 秒的语句都记。ARM 机器上最常见的两类慢查询:一是没走索引的全表扫描,二是跨网段访问数据库时的网络延迟被记成了慢查询。慢查询日志的价值在于区分「数据库慢」还是「网络慢」,前者EXPLAIN查索引,后者查应用服务器到数据库服务器的链路延迟。
第五步,磁盘可用空间确认。MySQL 5.7 的 binlog 如果不定期清理,会一直膨胀下去,ARM 服务器数据盘通常不大,binlog 撑爆磁盘是我见过最高频的生产事故之一。上线前我必做的操作:
-- 查看 binlog 占用 SHOW MASTER STATUS; SHOW BINARY LOGS; -- 设置自动清理时长,保留 3 天 SET GLOBAL expire_logs_days = 3; FLUSH BINARY LOGS;expire_logs_days = 3不是删一个 binlog,是让 MySQL 自动删除超过 3 天的二进制日志。如果你做主从同步,清理前确认从节点已经拉取完对应日志,否则从节点断档后要重新做全量同步,那才是大工程。
从那以后我每次在 ARM 机器上装 MySQL,都会强制自己把这五步完整走一遍再交付。第一次做很费时间,后面熟练了半小时就能搞定,但它保证了你拿到的不是一个「能 ping 通就交付」的黑匣子,而是一个知道底层怎么跑、坏了怎么恢复的数据库实例。希望帮到你。
本文还有配套的精品资源,点击获取