)
1. 为什么过了这么多年还要在ARM64架构上装MySQL5.71.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内核里通常表示为aarch64CentOS 7官方镜像对应的仓库在镜像站上也会有专门的“centos-altarch”目录。很多人配置yum源时直接把x86_64的源地址复制过去导致后续安装依赖各种404或找不到包这一块我会在第2章详细讲。1.3 为什么版本要选5.7.44MySQL 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.44Operating 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-1160glibc是2.17MySQL 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] nameCentOS-7 - Base - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos-altarch/7.9.2009/os/aarch64/ gpgcheck0 enabled1 [updates] nameCentOS-7 - Updates - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos-altarch/7.9.2009/updates/aarch64/ gpgcheck0 enabled1 [extras] nameCentOS-7 - Extras - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos-altarch/7.9.2009/extras/aarch64/ gpgcheck0 enabled1注意路径里是“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-toolslibaioMySQL进行AIO异步I/O操作的依赖缺失的话mysqld启动直接报error while loading shared librariesnumactl-libs用于NUMA内存管理ARM多核服务器上很关键opensslMySQL 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.logsystemd服务文件也已经生成好了。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如果属主不对比如是rootmysqld启动时会报“Couldnt 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直接运行mysqldMySQL 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 port3306 pid-file/usr/local/mysql/mysql.pid log-error/var/log/mysqld.log usermysql server-id1 character-set-serverutf8mb4 collation-serverutf8mb4_general_ci skip-name-resolve max_connections500 max_connect_errors1000 innodb_buffer_pool_size4G innodb_buffer_pool_instances4 innodb_flush_log_at_trx_commit1 sync_binlog1 innodb_flush_methodO_DIRECT几个关键参数在ARM64下的考量innodb_buffer_pool_size通常设置为物理内存的50%到70%如果服务器只跑MySQL就往上限靠。设太大会导致系统swap频繁。innodb_buffer_pool_instances在ARM64多核环境下可以按内存池大小分片减少并发锁一般每个实例1G到2G比较合适。innodb_flush_methodO_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 --usermysql --log-error/var/log/mysqld.log二进制包方式则要指定basedir和datadir/usr/local/mysql/bin/mysqld --initialize --usermysql --basedir/usr/local/mysql --datadir/usr/local/mysql/data --log-error/var/log/mysqld.log这里有两个初始化模式--initialize生成一个临时随机root密码密码会写进错误日志形如“A temporary password is generated for rootlocalhost: 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] DescriptionMySQL Server 5.7 Afternetwork.target [Service] Typeforking Usermysql Groupmysql PIDFile/usr/local/mysql/mysql.pid ExecStart/usr/local/mysql/bin/mysqld_safe --defaults-file/etc/my.cnf ExecReload/bin/kill -HUP $MAINPID [Install] WantedBymulti-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 rootlocalhost IDENTIFIED BY NewPass123; FLUSH PRIVILEGES;如果需要远程连接要创建一个专用账号不建议直接放开root的远程权限CREATE USER app% IDENTIFIED BY AppPass2024; GRANT ALL PRIVILEGES ON *.* TO app%; FLUSH PRIVILEGES;这里host用了%意味着任意IP都可以连必须依靠防火墙控制访问来源。更安全的方式是把host设为具体应用服务器的IP。5.3 防火墙与SELinux处理CentOS 7默认firewalld是开启的外部机器没法直接访问3306端口。开放端口firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload firewall-cmd --list-ports然后是SELinux。如果状态是enforcingMySQL启动后监听端口和读写数据目录可能被拦截。最简单的验证方式是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 libaioCant 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/mysqlCant start server: Bind on TCP/IP port: Permission deniedSELinux拦截3306端口semanage port 或临时setenforce 0Wrong 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上安装jemallocyum install -y jemalloc确认库文件路径ls -l /usr/lib64/libjemalloc.so*配置文件有两种方式。第一种在/etc/my.cnf的[mysqld_safe]段加入[mysqld_safe] malloc-lib/usr/lib64/libjemalloc.so.2第二种在systemd服务文件里通过环境变量注入EnvironmentLD_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启动mysqldnumactl --interleaveall /usr/sbin/mysqld --defaults-file/etc/my.cnf 如果是在systemd环境下可以在ExecStart前加上numactl但要注意numactl命令本身要为aarch64架构。这种调整要压测验证不是所有场景都有效。内核参数方面建议把swap使用调低一点sysctl vm.swappiness10日志里如果出现大量“Table open cache”相关的警告可以适当调大table_open_cache4096 thread_cache_size128注意这些参数不是越高越好设定后要通过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更简单。