资讯动态

MySQL 8二进制安装实战:从解压到systemd托管全流程

发布时间:2026/10/1 22:35:01 来源:尧图企业网站定制
1. 为什么在这个时代还选二进制包装 MySQL 8有朋友问我现在要么 rpm 一把梭、要么 docker compose 拉镜像为什么还要写 MySQL 8 二进制安装这种老掉牙的操作我这两年装 MySQL 的次数比前几年加起来还多其中至少一半场景是内网机房、离线交付、不允许用容器yum 源里只有版本旧到没法看的发行版 MySQL这时候官方提供的 Linux Generic 二进制 tar 包反而是最靠谱的出路。所谓二进制安装本质就是官方已经把 MySQL 8 的 C/C 源码用标准工具链编译好打包成自包含的目录结构你拿到手之后只需要做四件事解压、配置 my.cnf、初始化数据目录、启动服务。省掉了源码编译需要的一整套依赖cmake、gcc、make、boost也绕开了 rpm 对发行版版本的严格绑定。一次解压就是一个完整实例多版本共存、整目录迁移、离线分发都非常方便。我选择二进制包的几个典型场景客户机器不连外网apt/yum 源不可用操作系统版本较老官方已经不提供对应 rpm但 glibc 版本还满足通用包要求需要在一台机器上跑多个 MySQL 8 实例并且版本还不一样公司安全审计要求不能使用容器又需要一个干净的 MySQL 环境。二进制包在这些场景下几乎是唯一解。需要注意一个前提官方通用二进制包对系统的 glibc 版本有要求比如较新的 8.0 包可能要求 glibc 2.17 以上8.4 LTS 的包可能要求 glibc 2.28 以上。下载前先执行 ldd --version 看一下系统 glibc 版本CentOS 7 一般没问题CentOS 6 这类老系统就得考虑选择旧一点的 8.0 小版本或者直接换发行版。1.1 二进制包和 rpm、docker 的差别在哪里先把几个方案摆在一起对比看完就明白我为什么在一些场景里坚持用二进制包。方案优点短板rpm/deb 包安装快、systemd 集成好、符合发行版规范版本通常滞后目录拆散在 /usr、/var/lib/mysql、/etc 等路径整体迁移痛苦离线装依赖麻烦docker 容器起停方便、环境隔离、版本切换简单内网无镜像可用、容器安全限制、数据卷权限和 SELinux 问题多监管环境往往不允许源码编译可以定制编译选项、指定工具链耗时长依赖 cmake、gcc、boost 等一堆包离线环境凑依赖能凑到怀疑人生二进制 tar 包自包含、版本新、离线友好、支持多实例共存glibc 版本有要求初始化、systemd 托管需要自己处理我遇到最多的情况是客户给了台干净的 CentOS 7内网什么源都没有但是机器本身能通过 U 盘或者审批后的方式拷文件进去。这时候一个 tar 包加几个命令就能交付而 rpm 包缺依赖时往往需要在另一台联网机器上把依赖链全部下载完再拷进去费时费力。1.2 二进制包的目录为什么是自包含的MySQL 官方编译二进制包时会把运行时需要的库、字符集、错误信息文件、工具脚本都放到一个目录内。解压之后你会看到 bin、lib、share、support-files 这些子目录除了系统级的 glibc、libaio 这类基础库之外它不依赖其他外部组件。这意味着你可以把整个目录打包带走在另一台同样架构和 glibc 兼容的机器上解压就能用这也是我选择它的重要原因。2. 下载、校验与目录规划装之前先把这些事定下来2.1 下载地址与版本选择MySQL 官方下载页提供 Linux Generic 二进制包文件命名大概是这样一个格式mysql-8.0.36-linux-glibc2.17-x86_64.tar.xz。如果下的是 8.4 LTS 系列的维护版本比如 8.4.11包名则类似 mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz。生产环境我建议只选 LTS 版本线8.0 和 8.4 都可以不要追 9.x 这种 innovation 版本。操作系统是 ARM 架构的就选带 aarch64 标识的包。下载时注意官网默认跳转到登录页实际 CDN 直链是可以不带登录直接 wget 的也可以使用国内开源镜像站下载但不管从哪个渠道拿包下载完一定要做校验。官网页面上会给出对应的 MD5 或 SHA256用以下命令核对md5sum mysql-8.0.36-linux-glibc2.17-x86_64.tar.xz sha256sum mysql-8.0.36-linux-glibc2.17-x86_64.tar.xz如果校验值对不上说明下载过程中文件损坏或被篡改解压安装后大概率会出现各种莫名其妙的问题。这一步不要省尤其是在内网通过审批流程拷贝文件的时候。2.2 解压、软链接与目录结构先创建 MySQL 专用的系统用户和组建议使用不能登录的系统账号groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql接着解压到 /usr/local 目录并建立软链接。这一步有个细节很多人不知道官方二进制包在编译时把 basedir 默认路径写成了 /usr/local/mysql所以通过软链接把当前版本目录映射到这个路径可以规避大量因 basedir 不一致导致的路径错误。tar -Jxf mysql-8.0.36-linux-glibc2.17-x86_64.tar.xz -C /usr/local ln -s /usr/local/mysql-8.0.36-linux-glibc2.17-x86_64 /usr/local/mysql最终目录结构建议按下面这样规划/usr/local/mysql # basedir 软链接指向解压出的版本目录 ├── bin/ ├── lib/ ├── share/ └── support-files/ /data/mysql/data # datadir数据文件、redo log、undo log 都在这 /var/log/mysql/ # error log、slow log /etc/my.cnf # 主配置文件datadir 单独放在数据盘而不是和程序放在一起这是运维上的基本习惯。程序目录可以随时删掉重来数据目录必须可控、可备份、可扩展。建立数据目录和日志目录并修改属主mkdir -p /data/mysql/data mkdir -p /var/log/mysql chown -R mysql:mysql /data/mysql chown -R mysql:mysql /var/log/mysql2.3 依赖库检查MySQL 8 的二进制包运行需要 libaio 和 ncurses 相关的系统库。用 ldd 检查关键二进制文件是最直接的办法ldd /usr/local/mysql/bin/mysqld | grep not found如果没有任何输出说明动态库依赖全部满足。如果有缺失通常会是以下几种情况libaio.so.1 缺失执行 yum install libaio 或 apt install libaio1libtinfo.so.5 缺失CentOS 7 上安装 ncurses-compat-libs 可以解决libncurses.so.5 缺失同样通过 ncurses-compat-libs 或 libncurses5 解决。这些依赖问题通常在初始化阶段就会冒出来报错信息会直接告诉你哪个共享库找不到照着名称补装即可。3. 写配置文件的正确姿势my.cnf 里这些参数我是逐行考虑的3.1 一份能直接跑起来的最小配置初始化数据目录之前一定要先把 my.cnf 写好。因为 mysqld --initialize 会读取配置文件如果你不写 datadir它会把数据初始化到编译路径下的默认位置也就是 /usr/local/mysql/data后面再想迁移到 /data 目录会比较绕。下面这份配置是我个人在安装 8.0 时最常用的一份基础配置可以根据机器实际资源调整[client] port3306 socket/tmp/mysql.sock [mysqld] usermysql basedir/usr/local/mysql datadir/data/mysql/data socket/tmp/mysql.sock pid-file/data/mysql/mysql.pid port3306 server-id1 mysqlx0 character-set-serverutf8mb4 collation-serverutf8mb4_0900_ai_ci log-error/var/log/mysql/error.log slow-query-log1 slow-query-log-file/var/log/mysql/slow.log long_query_time2 innodb_buffer_pool_size4G max_connections500 max_connect_errors100000 skip-name-resolve先解释几个容易被忽略的配置。usermysql 让 mysqld 启动后自动切换到 mysql 账号避免以 root 身份运行数据库进程基于安全考虑数据库进程不应该用 root 跑。socket/tmp/mysql.sock 是客户端连接使用的 Unix socket 路径[client] 段里也写同样的路径后续使用 mysql 命令时就不用每次加 -S 参数。3.2 参数取舍思路innodb_buffer_pool_size 是 MySQL 8 里最重要的内存参数InnoDB 的数据页缓存都在这。我的经验是如果这台机器是专职数据库服务器缓冲池可以设置为物理内存的 60% 到 70%如果上面还跑着业务应用就要适当调低比如 16G 内存的机器给 4G 到 8G。MySQL 8 默认值是 128M这个大小用来跑测试可以生产环境不调整的话性能会很差。skip-name-resolve 这个参数我基本都会开。它的作用是禁止 MySQL 对客户端 IP 做反向 DNS 解析。不开的话客户端建立连接时如果 DNS 解析超时会出现连接建立缓慢甚至卡顿的情况对高并发应用影响很明显。开启后授权表里就只能用 IP、localhost 或主机名IP 对应的反解记录不能用域名作为授权 host。mysqlx0 是关闭 MySQL 8 默认开启的 X Plugin 端口 33060。这个端口平时根本用不到但安全扫描经常报出来关闭之后少一个暴露面。如果你需要用到 X DevAPI 连接就把它去掉。3.3 目录权限和配置校验技巧/var/log/mysql 目录在启动前必须存在并且属主是 mysql否则 mysqld 会报错退出。error log 对排查问题极其关键我建议在任何操作前先确认这个文件能创建。配置写完后可以用一个很实用的命令查看 mysqld 对配置的实际解析结果/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf --verbose --help | grep -E ^basedir|^datadir|^socket这个命令不会启动服务只是把解析到的参数打出来用它能快速确认 basedir、datadir 是否按照预期读取省去启动后才发现路径不对的折腾。4. 初始化数据目录临时密码不在终端里在日志文件里4.1 --initialize 到底做了什么MySQL 8 的初始化命令已经不再是 MySQL 5.7 时代那个 mysql_install_db 脚本了。从 5.7 起这个脚本就被标记为废弃8.0 里直接移除。现在统一使用 mysqld --initialize原理是让 mysqld 以 bootstrap 模式启动创建数据字典、系统库mysql、performance_schema、sys创建 root 用户并生成一个随机的临时密码然后自动退出。执行初始化的前提是 datadir 指向的目录要么不存在、要么为空而且目录的属主必须是 mysql。如果目录里面残留了上一次初始化失败产生的文件命令会直接报错并终止。初始化命令本身很简单/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf --initialize --usermysql命令执行完没有任何输出是正常的不要以为是卡住了。初始化是否成功要看日志grep -i temporary password /var/log/mysql/error.log日志里会出现类似下面这行内容[Note] [MY-010454] [Server] A temporary password is generated for rootlocalhost: xxxxKd%y2qW冒号后面的这一串就是 root 的临时密码只显示这一次务必先复制保存好。4.2 初始化成功后的数据目录长什么样初始化完成后去看 /data/mysql/data 目录正常情况下应该有这些内容mysql.ibd数据字典、ibdata1系统表空间、undo_001 和 undo_002回滚段、#innodb_redo 目录redolog8.0.30 版本后 redolog 被拆分到这个目录里、performance_schema 和 sys 目录。所有文件的属主都应该是 mysql如果不是说明目录权限在初始化前就没给对。这也是我判断初始化是否成功最直接的标准文件都出现了、属主正确说明数据字典表空间都建好了可以放心启动服务。只有部分文件出现通常是初始化在中途失败需要根据 error log 来排查。4.3 为什么不推荐 --initialize-insecure有些人图省事会加 --initialize-insecure这个参数让 rootlocalhost 变成空密码免去临时密码的麻烦。我的态度是本地虚拟机做实验可以用生产环境千万别用。空密码的 root 账号即使只允许本机登录也相当于把一个超级管理员账号裸奔在机器上一旦有其他漏洞配合数据库就全完了。如果确实误用了登录后立刻执行下面的 SQL 补救ALTER USER rootlocalhost IDENTIFIED BY NewStrong_Password_2025!;另外要记住临时密码只有初始化这一次机会。如果日志被轮转覆盖或者你忘了复制是找不回来的。数据不重要时可以清空 datadir 重新初始化有数据时就会很被动所以看到临时密码的第一时间就保存好。5. 用 systemd 把 mysqld 管起来让重启和开机自启都干净利落5.1 启动方式那么多为什么推荐 systemdMySQL 8 二进制包解压后支持几种启动方式直接命令行执行 mysqld、用 mysqld_safe 脚本、用 support-files/mysql.server 脚本以及自己写 systemd unit 文件。直接执行 mysqld 会占据当前终端适合调试mysqld_safe 会拉起 mysqld 子进程并监控适合在终端里人工观察mysql.server 是 SysV init 风格的封装脚本。但在 CentOS 7 及以后的系统里我推荐用 systemd 托管。原因是 mysqld_safe 这种方案会导致 systemd 眼里有两个进程mysqld_safe 本身和它拉起的 mysqld管理起来容易乱重启策略、文件描述符限制都不好控制。自己写一个 unit 文件让 mysqld 前台运行systemd 直接监控主进程进程生命周期清清楚楚。5.2 systemd 单元文件的具体写法创建 /etc/systemd/system/mysqld.service内容如下[Unit] DescriptionMySQL 8.0 Database Server Afternetwork.target [Service] Usermysql Groupmysql Typesimple ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf Restarton-failure LimitNOFILE65535 TimeoutSec300 [Install] WantedBymulti-user.target这里把 Type 设为 simple 是关键因为 mysqld 默认在前台运行不会 fork 出子进程后再退出systemd 可以准确跟踪主进程的 PID。Restarton-failure 让 mysqld 崩溃时自动拉起LimitNOFILE 把文件描述符上限提高到 65535避免高连接数场景下出现 too many open files。写完文件后依次执行systemctl daemon-reload systemctl enable --now mysqld systemctl status mysqld看到 active (running) 就说明服务起来了。再用 ss 检查监听端口ss -lntp | grep 3306确认 3306 端口正在监听。到这里安装就算基本完成了。5.3 如果坚持用 mysql.server 脚本有些内网老系统没有 systemd或者你接手的机器只允许用 SysV init 方式管理那就用 support-files/mysql.server。用法是把脚本复制到 /etc/init.d/ 下并在脚本头部修改 basedir 和 datadir 变量指向实际路径。用这种方式时 PID 文件路径一定要和配置文件保持一致否则执行 service mysql stop 时脚本找不到 PID会报错服务未启动。这也是我为什么在 my.cnf 里把 pid-file 写死为 /data/mysql/mysql.pid 的原因脚本能通过配置读到就不会出现管理上的路径错乱。6. 容易翻车的六个场景从 libaio 到 caching_sha2_password6.1 libaio.so.1 缺失导致初始化直接失败初次部署最容易遇到的就是缺动态库。执行初始化时如果系统没有任何反应或者执行 mysqld 时报出error while loading shared libraries: libaio.so.1: cannot open shared object file说明系统缺少 libaio 库。这个库是 InnoDB 使用异步 I/O 的基础依赖MySQL 8 几乎必须要有。安装方式很简单yum install -y libaio apt install -y libaio1装完再跑 ldd 检查一遍确认没有 not found 再继续初始化。除了 libaio老系统还可能缺 libtinfo 或者 libncurses 的兼容库报错信息同样会直接指出缺哪个文件对症安装即可。6.2 datadir 非空导致初始化反复报错这个坑出现频率很高尤其是同一台机器反复部署、或者曾经用其他工具初始化过数据目录。执行 mysqld --initialize 时报错[ERROR] --initialize specified but data directory has files in it. Aborting.原因就是 /data/mysql/data 目录不是空的。mysqld 为了保护已有数据在初始化模式下发现目录非空会直接拒绝工作。解决办法是把现有内容先移走而不是顺手 rm -rfmv /data/mysql/data /data/mysql/data_old_$(date %F) mkdir -p /data/mysql/data chown mysql:mysql /data/mysql/data这样万一里面有有用的数据还能找回来。初始化完成后确认无误再决定要不要删除旧目录。6.3 服务启动秒退日志是唯一可信的排查入口systemctl start mysqld 执行后状态立刻从 activating 变成 failed大多数人第一反应是看 systemctl status但那里只是摘要。真正有用的信息全在 error log 和 journald 里tail -100 /var/log/mysql/error.log journalctl -u mysqld --no-pager | tail -100我遇到过的典型案例是 InnoDB 报错 Operation error 13翻译过来就是权限不足原因是没有确认 datadir 目录的属主mysqld 用 mysql 身份无法写入数据文件。还有一次是因为 /var/lib/mysql 这个旧路径下的日志权限不对mysqld 初始化完数据目录后创建 error log 失败服务直接退出。这些问题的共同特征是日志里会明明白白写上哪一步失败、涉及哪个文件、什么错误码按图索骥就能定位。6.4 旧配置文件的废弃参数在 8.0 里直接让启动中止如果是从 MySQL 5.7 的 my.cnf 直接拷到 8.0 环境启动时很容易出现[ERROR] [MY-010119] [Server] unknown variable query_cache_typeON这是因为 query_cache_type、query_cache_size 在 5.7 已经废弃并在 8.0 移除innodb_file_format、innodb_large_prefix 这类参数同样也消失了。mysqld 对未知参数的态度是宁可启动失败也不忽略所以旧配置不能直接复用。排查思路很简单每次启动失败先打开 error log看到 unknown variable 就把对应参数从配置文件注释掉反复几次把废弃参数清完服务自然就能起来了。6.5 远程连接不上的三个常见原因数据跑起来以后客户端连不上的情况也经常遇到。我的排查顺序是先用 mysql -uroot -p 本机连接如果本机都连不上回到 error log 找原因再用 ss -lntp | grep 3306 确认 mysqld 监听地址如果监听在 127.0.0.1说明 my.cnf 里写了 bind-address127.0.0.1去掉或改成 0.0.0.0确认授权账号的 host 是否允许来自应用服务器的 IP比如 root 默认只有 localhost需要单独创建账号或用 root 从远程连接时要相应授权最后检查防火墙和云安全组firewalld 或 iptables 是否放行 3306 端口。这个顺序是从数据库本身到系统网络再到外部防火墙一步步往外排查基本不会漏。6.6 老客户端连挂caching_sha2_password 兼容问题MySQL 8.0 默认的认证插件是 caching_sha2_password而很多老版本的应用驱动比如某些 PHP 扩展、老版本 JDBC只支持 mysql_native_password。应用连接时报错一般是Authentication plugin caching_sha2_password cannot be loaded解决办法有两个方向优先升级应用驱动让客户端支持新认证插件如果驱动没法升级就把特定业务账号的认证方式改回旧插件ALTER USER app% IDENTIFIED WITH mysql_native_password BY App_Password_2025!;我建议只对确有兼容需求的应用账号做这种调整root 账号保持默认的 caching_sha2_password从安全角度更稳妥。还有一种中间做法是把默认认证插件在 my.cnf 里改成 mysql_native_password但这样做会让整个实例的认证强度降低不推荐。7. 第一次登录之后改密码、建账号、验证字符集以及小版本升级思路7.1 用临时密码登录并强制改密拿到临时密码后先本机登录/usr/local/mysql/bin/mysql -uroot -p粘贴临时密码时要注意密码里可能包含特殊字符直接复制到终端即可不要手动敲。登录成功后立刻修改 root 密码ALTER USER rootlocalhost IDENTIFIED BY NewStrong_Root_2025!;MySQL 8 的密码校验策略默认可能要求至少包含大写、小写、数字和特殊字符长度也有要求。如果执行时报密码等级不够说明环境启用了 validate_password 组件要么设置一个足够复杂的密码要么根据安全基线调整组件策略不要为了图省事把密码复杂度关掉。7.2 创建业务账号时的习惯生产环境里业务不要用 root 连接这是底线。创建业务数据库和最小权限账号CREATE DATABASE appdb DEFAULT CHARACTER SET utf8mb4; CREATE USER app192.168.10.% IDENTIFIED BY App_Password_2025!; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER ON appdb.* TO app192.168.10.%; FLUSH PRIVILEGES;这里要特别注意 MySQL 8 下 GRANT 语句不能再用老语法把 IDENTIFIED BY 混在授权里一次性创建用户必须先 CREATE USER 再 GRANT否则语句会直接报错。授权范围按业务实际需要来能不给 DROP 就不给宁可后面加权限不要一开始就 ALL PRIVILEGES。7.3 验证服务状态和字符集收尾前做一遍状态确认SHOW VARIABLES LIKE character_set_server; SELECT VERSION(); SHOW DATABASES;character_set_server 应该是 utf8mb4连接字符集可以和服务器端不一致但新建库默认继承服务器端的配置所以先把服务器端设置对。确认 datadir 下文件属主仍然是 mysqlerror log 里没有新的 ERROR 级别记录再检查 mysqld 进程ps -ef | grep mysqld | grep -v grep如果一个 mysqld 进程没有多余子进程说明 systemd 管理方式是干净的。7.4 同大版本内的小版本升级思路二进制安装方式在小版本升级上非常直观大体流程是备份配置文件和数据目录、停服务、解压新版本包、改软链接指向、启动服务、验证版本。以 8.0.36 升到 8.0.37 为例systemctl stop mysqld tar -Jxf mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz -C /usr/local rm -f /usr/local/mysql ln -s /usr/local/mysql-8.0.37-linux-glibc2.17-x86_64 /usr/local/mysql chown -h mysql:mysql /usr/local/mysql systemctl start mysqldMySQL 8.0.16 以后不再需要手动执行 mysql_upgrade服务启动时会自动检查并升级数据字典所以启动后看 error log 没有问题、SELECT VERSION() 显示新版本升级就完成了。回滚方面需要提醒一下小版本升级后数据字典可能已经被新版本修改直接切回旧版本的二进制目录是有风险的稳妥的回滚方式是恢复升级前的物理备份而不是简单改软链接。这也是我建议每次升级前至少留一份 datadir 的备份或快照的原因。我自己的运维习惯是把解压出的版本目录保留原名软链接指向当前使用版本这样 /usr/local 下能看到历史版本切回旧版本只需要改一个软链接。对于多实例场景只需要复制一份 my.cnf 修改 datadir、port、socket、pid-file 这四个参数再用同样的初始化流程跑一遍就能在单机上并存多个 MySQL 8 实例这套二进制安装的流程是完全通用的。MySQL 8 的二进制安装本身不难难的是把路径、权限、配置和进程管理理顺上面这些坑基本就是我这几年遇到的大部分情况照着做能少走很多弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑