麒麟V10 ARM离线部署MySQL 8.0避坑指南:依赖、systemd与自启
2026/9/19 6:51:00 网站建设 项目流程

1. 为什么ARM架构的离线部署值得单独写一篇避坑指南

在x86服务器上装MySQL,绝大多数时候就是一条yum install mysql-server或者下载个rpm包rpm -ivh就完事了。但一旦环境换成银河麒麟V10 SP3 Lance版本的ARM服务器镜像,事情就完全不一样了。我最近刚在一个纯内网、无外网出口的鲲鹏ARM服务器上完成了一套MySQL 8.0的离线部署,从最开始连依赖都装不上,到最后做成systemd服务开机自启,中间踩的坑足够写一篇完整的复盘。

先说清楚这篇文章适合谁看:如果你手上有麒麟V10 ARM架构的服务器,网络环境是完全隔离的内网,需要部署MySQL并且要求服务能随系统自启,那这篇内容基本可以当作操作手册来用。如果你只是想在x86的CentOS上装个MySQL,那这篇的很多细节对你来说会显得多余,因为ARM架构下的依赖链和包管理逻辑跟x86差异很大。

核心难点集中在三个地方:一是ARM架构的MySQL官方包选择,很多人习惯性去MySQL官网下载页面直接点第一个,结果下回来的是x86_64的包,在ARM机器上根本装不了;二是麒麟V10自带的依赖库版本与MySQL要求的依赖之间存在缺口,离线环境下没法自动补;三是systemd服务单元的配置,麒麟V10虽然基于较新的内核,但它的systemd版本和服务管理习惯跟常见的CentOS 7/8有细微差别,直接照搬网上的配置模板可能会遇到服务起不来或者启动后立即退出的问题。

下面我按照实际操作的顺序,把整个流程拆成几个阶段来讲,每个阶段都会说明为什么这么做、当时遇到了什么问题、最后怎么解决的。

2. 部署前的环境确认与包选择策略

2.1 确认系统架构和版本信息

动手之前先把机器的底细摸清楚,这一步看起来简单,但很多人就是在这里栽了跟头。执行以下命令确认架构:

uname -m

如果输出是aarch64,说明是ARM64架构,这是目前麒麟V10服务器版最常见的ARM架构。如果输出是armv7l之类的,那是32位ARM,MySQL 8.0基本不用想了,只能考虑MariaDB或者MySQL 5.7的特定版本。

接着确认系统版本:

cat /etc/kylin-release cat /etc/os-release

麒麟V10 SP3的输出里会明确标注版本号和SP级别。为什么要确认到SP级别?因为不同SP版本自带的glibc版本和openssl版本不同,这直接决定了你能用哪个版本的MySQL二进制包。比如SP1自带的glibc可能是2.28,SP3可能已经到2.34了,而MySQL 8.0.30之后的版本对glibc的最低要求是2.28,如果你在SP1上装最新的MySQL 8.0.35,可能会遇到glibc版本不满足的问题。

注意:麒麟V10的/etc/os-releaseVERSION_ID字段有时候显示的是"V10",不带SP号,需要看KYLIN_RELEASE或者/etc/kylin-build文件才能确认SP级别。

2.2 选择正确的MySQL ARM包

这是整个部署过程中最关键的一步。MySQL官方对ARM架构的支持从5.7时代就开始了,但官方下载页面的默认选项永远是x86_64。你需要手动切换到ARM架构的下载链接。

MySQL官方提供的Linux通用二进制包(Generic Linux Binaries)分两种架构:x86_64aarch64。对于麒麟V10 ARM服务器,你要下载的是mysql-8.0.xx-linux-glibc2.xx-aarch64.tar.xz这种命名的包。注意文件名里的glibc2.xx部分,这个数字必须小于等于你系统自带的glibc版本。

我当时的做法是:

# 查看系统glibc版本 ldd --version | head -1

输出显示ldd (GNU libc) 2.34,所以我选择了mysql-8.0.35-linux-glibc2.28-aarch64.tar.xz,因为2.28小于2.34,兼容。如果选了glibc2.35的包,在2.34的系统上就会报GLIBC_2.35 not found的错误。

另外,MySQL 8.0.33之后的版本开始提供glibc2.28glibc2.35两个变体,选低的那个通常更安全。如果你实在不确定,就选你能找到的最低glibc版本的aarch64包。

实操心得:MySQL官网的下载页面有时候会隐藏ARM架构的选项,需要点击"Looking for previous GA versions?"或者直接在下载链接里把x86_64替换成aarch64。如果官网访问不便,可以在有外网的机器上下载好后通过内网传输工具拷进去。

2.3 离线依赖包的收集

麒麟V10 ARM服务器的最小化安装通常缺少MySQL运行所需的几个关键依赖。在离线环境下,你没法用yum install自动解决依赖,所以需要提前在有网的同类机器上把依赖包下载好。

MySQL 8.0在ARM麒麟V10上主要依赖以下几个包:

依赖包作用是否必须
libaio异步IO支持必须
numactl-libsNUMA内存管理必须
openssl-libsSSL加密支持必须
libtirpcRPC支持部分版本需要
ncurses-libs终端界面支持客户端需要

下载方法是在一台有网的麒麟V10 ARM机器上执行:

yumdownloader --resolve --destdir=/tmp/mysql-deps libaio numactl-libs openssl-libs libtirpc ncurses-libs

--resolve参数会把所有间接依赖也一起下载下来。下载完成后把整个/tmp/mysql-deps目录打包拷到离线服务器上,用rpm -ivh *.rpm批量安装。

注意:麒麟V10的yum源里包名可能跟CentOS略有不同,比如numactl-libs在麒麟上可能叫numactl,用yum search确认一下实际包名。

3. 离线安装MySQL的完整操作流程

3.1 创建用户和目录结构

MySQL不建议用root用户运行,所以先创建专用的mysql用户和组:

groupadd mysql useradd -r -g mysql -s /bin/false mysql

-r参数创建系统用户,-s /bin/false禁止该用户登录shell,这是安全基线的基本要求。

接着创建MySQL的数据目录和安装目录。我习惯把安装目录放在/usr/local/mysql,数据目录放在/data/mysql,这样数据和程序分离,后续升级或者迁移都方便:

mkdir -p /usr/local/mysql mkdir -p /data/mysql chown -R mysql:mysql /data/mysql

实操心得:如果服务器有单独的数据盘,强烈建议把/data/mysql挂载到数据盘上。麒麟V10默认的根分区通常不会太大,MySQL的数据文件增长很快,根分区满了之后处理起来非常麻烦。

3.2 解压和初始化

把下载好的mysql-8.0.35-linux-glibc2.28-aarch64.tar.xz上传到服务器,解压到安装目录:

tar -xf mysql-8.0.35-linux-glibc2.28-aarch64.tar.xz -C /usr/local/ mv /usr/local/mysql-8.0.35-linux-glibc2.28-aarch64/* /usr/local/mysql/

然后执行初始化。MySQL 8.0的初始化和5.7有区别,8.0默认会生成一个临时root密码,需要记录下来:

cd /usr/local/mysql bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql

执行完这条命令后,终端会输出类似这样的信息:

2024-01-15T08:30:22.123456Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: jK9#mP2$vL8q

冒号后面的那串就是临时密码,务必记下来,第一次登录必须用它。

如果初始化过程中报错,最常见的原因是libaio没装或者/data/mysql目录权限不对。错误信息通常会明确提示,比如error while loading shared libraries: libaio.so.1,那就说明libaio的rpm包没装上。

注意:初始化命令里的--basedir--datadir参数必须用绝对路径,用相对路径在某些麒麟V10的版本上会导致初始化失败。

3.3 配置文件的最小化编写

MySQL 8.0的配置文件不需要写太多东西,但有几个关键参数必须设置。在/etc/my.cnf写入以下内容:

[mysqld] basedir=/usr/local/mysql datadir=/data/mysql socket=/tmp/mysql.sock port=3306 user=mysql character-set-server=utf8mb4 collation-server=utf8mb4_general_ci log-error=/data/mysql/mysql-error.log pid-file=/data/mysql/mysql.pid [client] socket=/tmp/mysql.sock default-character-set=utf8mb4

这里解释几个关键点:socket路径放在/tmp下是因为麒麟V10的/var/lib/mysql目录默认权限比较严格,放在那里容易遇到权限问题;character-set-server设为utf8mb4是现在的标准做法,兼容emoji和生僻字;log-errorpid-file指向数据目录,方便统一管理。

实操心得:不要照搬网上那些几百行的my.cnf模板,很多参数在MySQL 8.0里已经废弃或者默认值就很合理。配置文件越简单,出问题的概率越小。后续需要调优再逐项添加。

3.4 启动MySQL并修改root密码

先用安全模式启动MySQL,跳过权限验证:

bin/mysqld_safe --defaults-file=/etc/my.cnf --skip-grant-tables &

然后用客户端连接:

bin/mysql -u root --socket=/tmp/mysql.sock

在MySQL命令行里执行:

FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';

改完密码后退出,杀掉mysqld_safe进程,再用正常模式启动:

bin/mysqld_safe --defaults-file=/etc/my.cnf &

用新密码验证登录:

bin/mysql -u root -p --socket=/tmp/mysql.sock

能正常进入就说明安装成功了。

4. 配置systemd服务实现开机自启

4.1 编写systemd服务单元文件

麒麟V10使用systemd管理服务,我们需要创建一个mysql.service文件。在/etc/systemd/system/目录下创建:

[Unit] Description=MySQL Server After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql Type=forking PIDFile=/data/mysql/mysql.pid ExecStart=/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf ExecStop=/usr/local/mysql/bin/mysqladmin -u root -p'你的密码' --socket=/tmp/mysql.sock shutdown TimeoutSec=300 PrivateTmp=true LimitNOFILE=65536

这里有几个关键点需要说明。Type=forking是因为mysqld_safe会fork一个子进程,systemd需要知道主进程的PID在哪里,所以必须配合PIDFile使用。ExecStopmysqladmin shutdown而不是直接kill,这样MySQL会优雅关闭,避免数据损坏。LimitNOFILE=65536是设置文件描述符上限,MySQL在高并发下需要这个值足够大。

注意:ExecStop里的密码是明文写在文件里的,如果对安全性要求高,可以创建一个专用的shutdown用户,只授予SHUTDOWN权限,然后用这个用户的密码。

4.2 启用服务并验证自启

写完service文件后,执行:

systemctl daemon-reload systemctl enable mysql systemctl start mysql systemctl status mysql

daemon-reload是让systemd重新读取服务文件,每次修改service文件后都必须执行。enable是设置开机自启,start是立即启动。

如果status显示active (running),说明服务正常。然后重启服务器验证自启:

reboot

重启后等系统起来,直接执行systemctl status mysql,如果显示running,说明自启配置成功。

4.3 常见启动失败原因排查

systemd服务启动失败的原因通常集中在几个地方。我整理了一个速查表:

现象可能原因解决方法
status显示failed,日志提示permission denied数据目录权限不对chown -R mysql:mysql /data/mysql
启动后立即退出,日志无明确错误PIDFile路径不对确认my.cnf里的pid-file和service里的PIDFile一致
报错Can't create/write to file/tmp权限或空间问题检查/tmp权限,确认磁盘空间充足
报错Address already in use3306端口被占用`ss -tlnp
启动超时TimeoutSec太短增大TimeoutSec到600

排查时最有用的是看两个地方的日志:journalctl -u mysql -n 50看systemd层面的日志,/data/mysql/mysql-error.log看MySQL自身的日志。两个结合起来看,基本能定位到问题。

实操心得:麒麟V10的SELinux默认可能是 enforcing 状态,如果MySQL数据目录放在非标准路径(比如/data),SELinux可能会阻止MySQL访问。临时可以用setenforce 0验证是否是SELinux的问题,如果是,需要给数据目录打上正确的SELinux标签:semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"然后restorecon -Rv /data/mysql

5. 离线环境下的依赖问题深度解析

5.1 麒麟V10 ARM的依赖特殊性

麒麟V10 ARM版本的软件源跟x86版本不完全一样,有些在x86上常见的包在ARM源里可能版本不同或者名字不同。比如libaio在x86的CentOS 7上是libaio-0.3.109,在麒麟V10 ARM上可能是libaio-0.3.111,虽然功能一样,但如果你从x86机器上拷rpm包过来,会因为架构不匹配装不上。

所以收集依赖包的时候,一定要在同架构同系统版本的机器上执行yumdownloader。如果没有第二台麒麟V10 ARM机器,可以考虑用Docker在x86机器上模拟ARM环境,但这种方法比较折腾,不如直接找一台同配置的机器来得快。

5.2 依赖缺失的典型报错和处理

最常见的依赖报错是error while loading shared libraries,后面跟一个.so文件名。处理方法是用ldd命令检查mysqld的依赖:

ldd /usr/local/mysql/bin/mysqld | grep "not found"

输出会列出所有缺失的库。然后根据库名找到对应的rpm包。比如libaio.so.1 => not found,就说明需要安装libaio包。

另一个常见的坑是libtirpc。MySQL 8.0在某些麒麟V10版本上需要libtirpc.so.3,但系统自带的可能是libtirpc.so.1。这种情况下需要从麒麟的更新源里找libtirpc的新版本,或者从MySQL的二进制包里找自带的libtirpc

注意:不要随便从网上下载来路不明的.so文件放到/usr/lib64里,版本不匹配可能导致更严重的问题。优先用系统包管理器安装,实在不行再从可信的官方源获取。

5.3 用rpm批量安装依赖的正确姿势

把所有依赖rpm包放在一个目录里,然后执行:

rpm -ivh *.rpm --nodeps --force

--nodeps是跳过依赖检查,--force是强制安装。这两个参数在离线环境下很常用,因为有时候rpm包之间的依赖关系在离线环境下无法自动解析,但实际运行时并不缺东西。

不过要谨慎使用--force,它可能会覆盖系统已有的重要包。更安全的做法是先尝试正常安装:

rpm -ivh *.rpm

如果报依赖错误,再根据错误信息逐个处理。只有当确认依赖已经满足但rpm元数据不认的时候,才用--nodeps

6. 实操中遇到的典型问题与解决记录

6.1 初始化时报错"cannot create directory"

这个问题的原因是/data/mysql目录不存在或者权限不对。MySQL初始化时会尝试在datadir下创建子目录,如果datadir本身不存在或者mysql用户没有写权限,就会报这个错。

解决方法:

mkdir -p /data/mysql chown -R mysql:mysql /data/mysql chmod 750 /data/mysql

权限设为750而不是777,是因为MySQL的数据目录包含敏感数据,权限过宽会有安全风险。

6.2 服务启动后客户端连不上

服务显示running,但用mysql -u root -p连接时报Can't connect to local MySQL server through socket '/tmp/mysql.sock'。这个问题通常是socket文件路径不一致导致的。

检查方法:

# 看MySQL实际使用的socket路径 ps aux | grep mysqld | grep socket # 看客户端默认的socket路径 mysql --help | grep socket

如果两者不一致,要么在my.cnf的[client]段里指定正确的socket路径,要么在连接时用--socket=参数显式指定。

实操心得:麒麟V10上/tmp目录可能会被systemd的PrivateTmp设置隔离,导致不同服务看到的/tmp不是同一个。如果遇到socket文件找不到的问题,可以把socket路径改到/data/mysql/mysql.sock,避免/tmp的干扰。

6.3 开机自启时MySQL启动比网络慢

有时候重启后MySQL服务显示failed,但手动systemctl start mysql又能正常启动。这种情况通常是启动顺序问题。MySQL在启动时可能需要解析主机名,如果网络还没完全就绪,解析会超时导致启动失败。

解决方法是在service文件的[Unit]段里加上:

After=network-online.target Wants=network-online.target

network-online.targetnetwork.target更严格,它确保网络接口已经配置完成并且可以通信。不过这个target在某些麒麟V10版本上可能不存在,如果加了之后systemd报错,就改回network.target,然后在MySQL的my.cnf里加上skip-name-resolve,跳过主机名解析。

6.4 数据目录迁移后的权限问题

如果后续需要把数据目录从/data/mysql迁移到其他路径,比如挂载了新的大容量磁盘,迁移后必须重新设置权限和SELinux标签:

systemctl stop mysql cp -a /data/mysql /newpath/mysql chown -R mysql:mysql /newpath/mysql # 如果SELinux是enforcing semanage fcontext -a -t mysqld_db_t "/newpath/mysql(/.*)?" restorecon -Rv /newpath/mysql # 修改my.cnf里的datadir systemctl start mysql

cp -a保留所有权限和属性,比cp -r更安全。迁移完成后一定要验证MySQL能正常启动并且数据完整。

7. 性能调优与日常维护建议

7.1 ARM架构下的参数调优

ARM架构和x86架构在内存模型和CPU缓存上有差异,MySQL的一些默认参数在ARM上可能不是最优的。根据我的实测,在鲲鹏920(64核)的机器上,以下几个参数值得调整:

innodb_buffer_pool_size=8G innodb_io_capacity=2000 innodb_read_io_threads=8 innodb_write_io_threads=8

innodb_buffer_pool_size通常设为物理内存的50%-70%,如果是专用数据库服务器可以到80%。innodb_io_capacity在ARM上可以设得比x86高一些,因为ARM的IOPS表现通常更好。读写IO线程数在ARM多核环境下可以适当增加。

注意:调优参数不要一次改太多,每次改一两个,观察一段时间再继续。改完参数后重启MySQL,用SHOW VARIABLES LIKE 'innodb_buffer_pool_size'确认生效。

7.2 备份策略的离线实现

离线环境下没法用云备份服务,只能用本地的mysqldump或者xtrabackupmysqldump适合数据量不大的场景:

/usr/local/mysql/bin/mysqldump -u root -p'密码' --all-databases --single-transaction --routines --triggers > /backup/mysql_$(date +%Y%m%d).sql

--single-transaction保证InnoDB表的一致性快照,不会锁表。--routines--triggers导出存储过程和触发器。

对于数据量超过50G的场景,建议用Percona XtraBackup的ARM版本,但XtraBackup对ARM的支持不如MySQL本身好,需要找专门的aarch64编译版本。

7.3 监控和日志轮转

MySQL的错误日志会一直增长,需要配置日志轮转。在/etc/logrotate.d/下创建mysql文件:

/data/mysql/mysql-error.log { daily rotate 30 missingok compress delaycompress notifempty create 640 mysql mysql }

这样每天轮转一次,保留30天,自动压缩旧日志。麒麟V10自带logrotate,不需要额外安装。

监控方面,离线环境可以用mysqladmin status或者SHOW GLOBAL STATUS定期采集关键指标,写个简单的shell脚本记录到本地文件即可。重点关注的指标包括:Threads_connectedInnodb_buffer_pool_hit_rateSlow_queries

8. 几个容易忽略的细节和最后的经验分享

整个部署流程走下来,有几个细节是我踩过坑之后才意识到的。第一个是麒麟V10的防火墙,默认可能是开启状态,3306端口没有放行的话,远程客户端连不上。用firewall-cmd --add-port=3306/tcp --permanent然后firewall-cmd --reload放行。如果不需要远程访问,保持防火墙开启只允许本地socket连接反而更安全。

第二个是时区问题。麒麟V10默认可能是UTC时区,MySQL启动后SELECT NOW()返回的时间跟本地时间差8小时。在my.cnf里加上default-time-zone='+08:00',或者在初始化之前用timedatectl set-timezone Asia/Shanghai设置系统时区。

第三个是root密码策略。MySQL 8.0默认安装了validate_password插件,要求密码包含大小写字母、数字和特殊字符,长度至少8位。如果设置的密码太简单会报错。离线环境下如果不需要这么严格的策略,可以在my.cnf里加上validate_password.policy=LOW降低要求,或者直接卸载插件。

最后分享一个我个人的习惯:每次部署完MySQL之后,我会创建一个deploy_record.txt文件放在/root下,记录这次部署的MySQL版本、依赖包版本、关键配置参数、临时密码(首次修改后删除)、遇到的问题和解决方法。下次再遇到类似环境,直接翻记录就能快速复现,不用重新踩一遍坑。这个习惯在离线环境下尤其重要,因为没法随时上网查资料,自己的记录就是最好的文档。

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

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

立即咨询