MySQL 这东西装起来说简单也简单说折腾也真能折腾死人。尤其是当你手里只有一台跑在 VMware 里的 CentOS 8 虚拟机又不想用 yum 那种一键黑盒的方式非要走源码编译安装这条路的时候坑是一个接一个。我前后在好几台虚拟机上折腾过这套流程从最开始对着报错一脸懵到后来能闭着眼睛把依赖、编译参数、初始化、权限、服务配置一条龙走完中间踩的坑够写一本小册子了。这篇东西就是把我这套流程完整摊开从零开始假设你刚装好一个干净的 CentOS 8 虚拟机连 MySQL 是什么都只知道个大概也能跟着一步步走下来。源码安装的好处很实在版本你说了算、安装路径你说了算、编译参数你说了算出了问题你能顺着源码和日志一路摸到根上而不是对着一个包管理器干瞪眼。适合谁看刚接触 Linux 和数据库的新手、需要特定 MySQL 版本做测试的开发者、以及想搞明白一个数据库到底是怎么被装进系统里的运维入门者。下面全部内容都是基于我在虚拟机环境里的实际操作为主配合必要的原理说明你照着抄作业基本不会翻车。1. 为什么要在虚拟机里源码装 MySQL1.1 源码安装和 yum 安装到底差在哪很多人第一反应是装个数据库而已yum install mysql-server不就完事了何必折腾源码这个问题我一开始也问过自己直到我遇到几个 yum 解决不了的场景。最典型的是版本锁定——某些项目对 MySQL 的小版本有硬性要求而系统自带的软件源里往往只有某个固定版本你想换个版本yum 要么没有要么给你一堆依赖冲突。源码安装就没这个烦恼官网下载对应版本的源码包编译出来就是你想要的那个版本干净利落。再一个是安装路径的控制权。yum 装的东西散落在/usr/bin、/usr/lib、/etc、/var/lib各处你想把数据目录挪到一块独立的大盘上或者把整个 MySQL 塞进一个自定义目录方便整体迁移和备份yum 方式就得改一堆配置。源码安装的时候-DCMAKE_INSTALL_PREFIX一个参数就把安装根目录定死了数据目录、日志目录、配置文件位置全都能在编译阶段规划好后期维护清爽很多。还有一个容易被忽略的点编译参数的可定制性。比如你想关掉某些用不上的存储引擎、调整默认字符集、指定特定的 SSL 库这些在源码编译时都能通过参数控制。yum 装的是别人编译好的通用版本你只能接受它的默认设定。当然源码安装的代价是时间长、步骤多、依赖要自己解决对新手不友好。但正因为步骤多你才会真正理解 MySQL 在系统里是怎么落地的——这一点对后面排查问题帮助极大。我把两种方式的核心差异整理成一张表你对照着看更直观对比维度yum 安装源码编译安装版本选择受限于软件源任意官方版本安装路径系统默认分散完全自定义编译参数不可控完全可控安装耗时几分钟半小时到一小时不等依赖处理自动解决手动安装排错难度黑盒难深入白盒可追溯适合人群快速上线学习、定制、特定版本需求1.2 虚拟机环境带来的额外考量在 VMware 虚拟机里跑这套流程和物理机有几点不一样得提前心里有数。首先是资源分配编译 MySQL 是个吃 CPU 和内存的活我给虚拟机配的是 2 核 4G编译阶段大概跑了二十多分钟如果你只给 1 核 2G那等待时间会明显拉长甚至可能因为内存不足导致编译中途被杀。建议至少 2 核 4G磁盘留 20G 以上因为源码包解压后体积不小编译产物加上安装目录空间消耗比你想的多。其次是快照。虚拟机最大的好处就是可以随时打快照我强烈建议你在开始之前先打一个干净系统的快照。源码编译过程中如果依赖装乱了、编译参数写错了导致系统里残留一堆半成品回滚快照比一点点清理要省事一百倍。这个习惯我在后面几次重装里救了自己好几回。第三是网络。编译需要下载源码包和一堆依赖包虚拟机的网络模式NAT 还是桥接会影响下载速度NAT 模式下一般没问题但如果你的环境对出网有限制提前把源码包和依赖准备好别等到编译到一半发现某个依赖下不下来。另外 CentOS 8 的软件源现在有些变动基础的开发工具链包如果源里拉不到可能需要额外配置这个后面实操部分会具体说。2. 动手前的环境准备与依赖梳理2.1 系统基础信息确认动手之前先摸清楚自己这台机器的底细别上来就敲命令。登录虚拟机后先确认几件事系统版本、内核版本、CPU 架构、磁盘空间、内存大小。这几项决定了你后面下载哪个源码包、编译参数怎么给。# 查看系统版本 cat /etc/centos-release # 查看内核版本 uname -r # 查看 CPU 架构 uname -m # 查看磁盘空间 df -h # 查看内存 free -h我实测下来CentOS 8 默认内核是 4.18 系列架构一般是 x86_64这两个信息很关键——下载源码包时要选对平台编译参数里的-DCMAKE_SYSTEM_PROCESSOR之类也跟架构相关。磁盘方面/分区至少留 15G 可用因为源码解压、编译中间文件、安装产物加起来轻松超过 10G。内存 4G 是比较舒服的起点2G 也能编但慢1G 就别试了大概率 OOM。还有一点确认你当前是 root 身份或者有 sudo 权限。源码安装涉及往/usr/local写文件、创建系统用户、改系统配置没有 root 权限寸步难行。我一般直接用 root 操作省得每条命令前面加 sudo但如果你习惯用普通用户加 sudo记得后面所有涉及系统目录的操作都带上 sudo。2.2 依赖包清单与安装逻辑MySQL 源码编译依赖的东西不少缺一个就可能在 cmake 或者 make 阶段报错。我把必需的依赖分成几类编译工具链gcc、gcc-c、make、cmake、库文件ncurses、openssl、zlib、libaio、以及一些辅助工具bison、wget、tar。这里有个关键点要说明MySQL 从 5.7 之后用 CMake 作为构建系统不再是老版本的 configure所以 cmake 是必须的而且版本不能太老CentOS 8 自带的 cmake 版本一般够用。安装依赖的命令我习惯一次性装齐dnf install -y gcc gcc-c cmake make ncurses-devel openssl-devel \ libaio-devel zlib-devel bison wget tar libtirpc-devel rpcgen这里解释几个容易漏的。ncurses-devel是 MySQL 客户端命令行工具依赖的缺了它编译出来的 mysql 客户端可能没有交互式界面。openssl-devel关系到 SSL 连接支持现在数据库不带 SSL 基本没法用。libaio-devel是异步 IO 支持对数据库性能有实际影响。libtirpc-devel和rpcgen这两个在 CentOS 8 上比较关键因为新版系统把一些 RPC 相关的东西拆出去了MySQL 编译时如果找不到会报错这个坑我踩过报错信息还特别隐晦提示某个头文件找不到实际就是缺这个包。提示CentOS 8 已经停止维护官方源可能拉不到部分包。如果dnf install报 无法找到匹配的参数先执行dnf repolist看看源的状态必要时配置可用的镜像源。这一步不解决后面全是空谈。依赖装完后建议验证一下关键工具是否就位gcc --version cmake --version make --version三个命令都能正常输出版本号说明工具链没问题。cmake 版本建议 3.5 以上CentOS 8 自带的一般是 3.11 以上够用。2.3 用户与目录规划这一步很多人会跳过直接拿 root 跑 MySQL这是大忌。数据库进程应该用一个专用的低权限系统用户来跑这样即使数据库被攻破攻击者拿到的也只是个受限账户不会直接威胁整个系统。我习惯创建一个叫mysql的系统用户不允许登录 shellgroupadd mysql useradd -r -g mysql -s /bin/false mysql-r表示创建系统用户-s /bin/false表示这个用户不能登录系统纯粹是给服务进程用的。这是标准做法别图省事用 root。目录规划也要提前想好。源码安装的一大优势就是路径可控我一般这样规划安装根目录/usr/local/mysql数据目录/usr/local/mysql/data配置文件/etc/my.cnf日志放在数据目录下。为什么数据目录放在安装目录里面因为这样整个 MySQL 就是一个自包含的目录备份、迁移的时候直接打包这一个目录就行不用满系统找文件。当然如果你的数据量很大想把数据目录单独挂一块盘那就在编译时把 datadir 指到挂载点思路是一样的。mkdir -p /usr/local/mysql mkdir -p /usr/local/mysql/data chown -R mysql:mysql /usr/local/mysql目录建好、权限给对这一步别偷懒后面初始化数据目录时如果权限不对会报各种莫名其妙的错误。3. 源码下载、编译与安装全流程3.1 源码包的选择与下载MySQL 的源码包在官方下载页面能拿到注意要选 Source Code 那一栏别下成二进制包或者 RPM 包。版本方面我这次用的是 8.0 系列的一个稳定版本具体小版本号你按需选思路完全一样。下载的时候有个细节官方提供带 boost 和不带 boost 的源码包MySQL 8.0 编译需要 boost 库选带 boost 的包能省掉单独装 boost 的麻烦文件名里一般带boost字样。cd /usr/local/src wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.xx.tar.gz下载完成后先校验一下文件完整性虽然官方包一般没问题但养成习惯没坏处ls -lh mysql-8.0.xx.tar.gz tar -tzf mysql-8.0.xx.tar.gz | head第二个命令能列出压缩包里的前几个文件说明包没损坏。然后解压tar -xzf mysql-8.0.xx.tar.gz cd mysql-8.0.xx解压后的目录就是源码根目录后面所有编译操作都在这里面进行。这里提醒一句源码目录和解压出来的 build 目录会占用不少空间编译完成后如果确认安装成功源码目录可以删掉释放空间但建议先留着万一后面要重新编译或者查源码方便。3.2 CMake 编译参数详解这是整个流程里最需要动脑子的部分。CMake 的参数决定了 MySQL 装成什么样参数给错了轻则功能缺失重则编译失败。我把常用参数分成必填和选填两类先看必填的cmake . \ -DCMAKE_INSTALL_PREFIX/usr/local/mysql \ -DMYSQL_DATADIR/usr/local/mysql/data \ -DSYSCONFDIR/etc \ -DMYSQL_UNIX_ADDR/usr/local/mysql/mysql.sock \ -DWITH_INNOBASE_STORAGE_ENGINE1 \ -DWITH_ARCHIVE_STORAGE_ENGINE1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE1 \ -DWITH_READLINE1 \ -DWITH_SSLsystem \ -DWITH_ZLIBsystem \ -DWITH_LIBWRAP0 \ -DMYSQL_TCP_PORT3306 \ -DMYSQL_USERmysql \ -DWITH_BOOST/usr/local/src/boost \ -DDEFAULT_CHARSETutf8mb4 \ -DDEFAULT_COLLATIONutf8mb4_general_ci逐个解释关键参数背后的逻辑。CMAKE_INSTALL_PREFIX是安装根目录所有东西都往这下面放。MYSQL_DATADIR是数据目录初始化时会往这里写系统表。SYSCONFDIR指定配置文件目录设成/etc是为了让 MySQL 默认去/etc/my.cnf找配置符合系统习惯。MYSQL_UNIX_ADDR是本地 socket 文件路径客户端连本地数据库走这个比走 TCP 快。存储引擎那几个WITH_xxx_STORAGE_ENGINE1是开启对应引擎InnoDB 是必须的Archive 和 Blackhole 看需求用不上可以不开开了也不占什么资源。WITH_SSLsystem表示用系统自带的 OpenSSL比编译内置的省事。DEFAULT_CHARSETutf8mb4这个很重要现在默认字符集必须用 utf8mb4不然存 emoji 或者某些特殊字符会出问题utf8 在 MySQL 里是个历史遗留的坑只支持三字节utf8mb4 才是完整的四字节 UTF-8。WITH_BOOST指向 boost 库的位置如果你下的是带 boost 的源码包boost 就在源码目录里路径指向源码目录下的boost文件夹即可。这个参数给错了cmake 阶段直接报错退出。参数给完执行 cmake屏幕上会滚动大量检查信息最后如果看到 Configuring done 和 Generating done说明配置成功。如果报错仔细看最后几行通常是某个依赖没找到或者参数写错了按提示补依赖或者改参数重来。这里有个经验cmake 失败后重新执行前最好把源码目录下的CMakeCache.txt删掉否则缓存可能导致新的配置不生效。3.3 make 编译与 make install 安装cmake 配置成功后就进入编译阶段。这一步最耗时也最考验机器性能make -j$(nproc)-j$(nproc)表示用所有 CPU 核心并行编译能显著缩短时间。我 2 核的虚拟机跑这个大概二十多分钟4 核能压到十几分钟。编译过程中屏幕会刷大量编译命令不用管只要不出现Error就行。如果中途报错退出通常是某个源文件编译失败往上翻找到第一个error关键字看是缺头文件还是语法问题多数情况还是依赖没装全。编译完成后执行安装make install这一步把编译产物复制到之前CMAKE_INSTALL_PREFIX指定的目录速度很快。装完后去/usr/local/mysql下看看应该有bin、lib、include、share等目录bin下面就是mysqld、mysql、mysqladmin这些核心程序。到这一步软件本身算是装好了但还不能用因为数据目录还没初始化。注意make install之后不要急着启动MySQL 8.0 首次启动前必须初始化数据目录否则会报错。初始化命令在下一节。4. 初始化、配置与启动验证4.1 数据目录初始化与临时密码处理MySQL 8.0 的初始化用mysqld --initialize命令它会创建系统表空间、系统数据库、以及一个初始的 root 账户。这里有个关键选择加不加--initialize-insecure。不加这个参数MySQL 会生成一个随机的临时 root 密码打印在错误日志里加了的话root 密码为空首次登录后必须马上改。我一般不加用随机密码更安全反正日志里能找到。/usr/local/mysql/bin/mysqld --initialize \ --usermysql \ --basedir/usr/local/mysql \ --datadir/usr/local/mysql/data执行完这条命令去数据目录看应该多出一堆文件包括ibdata1、mysql、sys等目录。临时密码在数据目录下的*.err日志文件里用 grep 找一下grep temporary password /usr/local/mysql/data/*.err输出里会有一行类似A temporary password is generated for rootlocalhost: xxxxxxxx把那个密码记下来首次登录要用。这里有个坑如果初始化时报错说数据目录不为空说明你之前初始化过或者目录里有残留文件要么清空目录重来要么换个空目录。初始化只能对空目录做这是硬性要求。初始化完成后还要处理一下 socket 文件的目录权限。MySQL 运行时会往MYSQL_UNIX_ADDR指定的路径写 socket 文件如果那个目录 mysql 用户没写权限启动会失败。我一般把 socket 放在数据目录下权限天然没问题。4.2 配置文件 my.cnf 的精简写法配置文件不用写得太复杂新手容易从网上抄一大坨参数结果互相冲突。我给一份精简但够用的配置[mysqld] usermysql basedir/usr/local/mysql datadir/usr/local/mysql/data socket/usr/local/mysql/mysql.sock port3306 character-set-serverutf8mb4 collation-serverutf8mb4_general_ci log-error/usr/local/mysql/data/mysql.err pid-file/usr/local/mysql/data/mysql.pid [client] socket/usr/local/mysql/mysql.sock default-character-setutf8mb4写到/etc/my.cnf。几个要点usermysql让服务以 mysql 用户身份跑socket路径要和编译时的MYSQL_UNIX_ADDR一致否则客户端连不上character-set-server设成 utf8mb4log-error和pid-file指到数据目录下方便排查。[client]段是给客户端用的保证命令行工具默认走正确的 socket 和字符集。配置写完后把 MySQL 的可执行文件路径加到环境变量里不然每次都要敲全路径echo export PATH/usr/local/mysql/bin:$PATH /etc/profile source /etc/profile4.3 启动服务与首次登录改密启动方式有两种手动启动和配置成系统服务。先手动启动验证一下/usr/local/mysql/bin/mysqld_safe --usermysql mysqld_safe是个守护脚本会在 mysqld 崩溃时自动重启适合测试阶段用。启动后等几秒用ps看看进程在不在ps -ef | grep mysqld有mysqld进程说明起来了。然后用临时密码登录mysql -u root -p输入日志里找到的临时密码。登录成功后第一件事就是改密码MySQL 8.0 的密码策略默认要求大小写字母、数字、特殊字符都有长度至少 8 位ALTER USER rootlocalhost IDENTIFIED BY YourNewStrongPass!123; FLUSH PRIVILEGES;改完密码顺手验证一下字符集和版本SHOW VARIABLES LIKE character_set_server; SELECT VERSION();字符集应该是 utf8mb4版本是你编译的那个版本。到这一步一个源码安装的 MySQL 就算跑起来了。4.4 配置成 systemd 服务实现开机自启手动mysqld_safe启动的方式重启机器就没了生产或长期使用必须配成系统服务。CentOS 8 用 systemd写一个 service 文件[Unit] DescriptionMySQL Server Afternetwork.target [Service] Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf ExecStop/usr/local/mysql/bin/mysqladmin --defaults-file/etc/my.cnf shutdown Restarton-failure LimitNOFILE65535 [Install] WantedBymulti-user.target保存为/etc/systemd/system/mysqld.service。然后重载配置、启动、设开机自启systemctl daemon-reload systemctl start mysqld systemctl enable mysqld systemctl status mysqldstatus显示active (running)就对了。这里有个细节ExecStart里用--defaults-file显式指定配置文件避免 MySQL 去别的地方找配置导致行为不一致。LimitNOFILE65535是调大文件描述符上限数据库并发连接多的时候默认值不够用。5. 踩坑实录与问题排查速查5.1 编译与初始化阶段的典型报错源码安装的坑集中在编译和初始化两个阶段我把遇到过的、以及社区里高频的问题整理成一张速查表报错现象根本原因解决方式cmake 报找不到 Boost未指定 WITH_BOOST 或路径错确认源码包带 boost参数指向正确目录编译报 rpc/rpc.h 找不到缺 libtirpc-devel 和 rpcgendnf 安装这两个包后重新 cmake编译报 ncurses 相关错误缺 ncurses-devel安装后删 CMakeCache.txt 重新配置初始化报 datadir not empty数据目录有残留文件清空目录或换空目录启动报 socket 文件无法创建socket 目录权限不对chown mysql:mysql 对应目录登录报 Access denied密码错或用了旧密码查 err 日志里的临时密码服务启动失败无输出配置或权限问题看 log-error 指定的日志文件重点说两个我印象最深的。一个是rpc/rpc.h找不到这个报错在 CentOS 8 上特别常见因为系统把 RPC 头文件拆到了libtirpc-devel包里而 MySQL 编译时默认去老路径找。解决办法就是装libtirpc-devel和rpcgen然后重新 cmake。这个坑的隐蔽之处在于报错信息不会直接告诉你缺哪个包只说头文件找不到新手很容易卡在这里。另一个是初始化时数据目录不为空。我第一次装的时候先手动mkdir了 data 目录然后又在里面放了点测试文件结果初始化直接失败。MySQL 要求 datadir 必须是完全空的连隐藏文件都不能有。后来我养成习惯初始化前先ls -la看一眼确认干净再执行。5.2 运行阶段的连接与权限问题服务跑起来之后问题主要集中在连接和权限上。最常见的是客户端连不上报Cant connect to local MySQL server through socket。这个基本就是 socket 路径不一致——要么配置文件里的 socket 路径和编译时的不一样要么客户端没读到正确的配置。排查方法先看my.cnf里的 socket 路径再看mysqld进程实际用的路径ps -ef | grep mysqld能看到两边对上才行。还有一个是远程连接被拒。MySQL 8.0 默认 root 只能从 localhost 登录你想从别的机器连得先创建允许远程登录的用户CREATE USER appuser% IDENTIFIED BY StrongPass!123; GRANT ALL PRIVILEGES ON *.* TO appuser%; FLUSH PRIVILEGES;注意%表示任意主机实际用的时候最好限定具体 IP 段别图省事全开。另外 CentOS 8 默认开了 firewalld3306 端口可能被挡需要放行firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload这两个点经常被一起忽略导致明明用户建了、权限给了就是连不上其实是被防火墙拦了。5.3 几条压箱底的实操心得第一条编译前先打快照。这个前面提过但值得再强调一次。源码编译涉及的操作多、时间长一旦中间某步搞乱了回滚快照比手工清理快得多。我现在的习惯是干净系统打一个快照依赖装完打一个编译成功再打一个出问题随时回退到最近的干净状态。第二条日志是你的第一手资料。MySQL 的报错日志在log-error指定的文件里启动失败、初始化失败、连接异常第一反应都应该是去看这个日志而不是瞎猜。日志里的报错信息通常比屏幕输出详细得多能直接指向问题根源。第三条别迷信网上的编译参数。网上很多参数是给特定场景或者老版本用的照抄到新版本上可能直接报错比如某些参数在新版 MySQL 里已经被移除。我的做法是先用最小参数集把编译跑通确认能装能用再根据实际需求逐个加参数加一个验证一个出问题好定位。第四条字符集从编译阶段就定死。DEFAULT_CHARSETutf8mb4这个参数一定要在 cmake 阶段给上别等装完了再改。装完再改字符集涉及重建数据库、导数据麻烦得很。一开始就定对后面省心。第五条路径规划要一次到位。安装目录、数据目录、socket 路径、日志路径这些在编译和配置阶段就要想清楚中途改路径意味着重新编译或者改一堆配置得不偿失。我一般画个简单的路径规划表编译前对着表把参数填好避免遗漏。这套流程我在不同配置的虚拟机上跑过好几遍每次都会遇到点新情况但核心步骤和排查思路是稳定的。源码安装 MySQL 这件事第一次做会觉得步骤繁琐做完一遍回头看其实每一步都有它的道理——依赖是为了编译编译参数是为了定制初始化是为了安全服务配置是为了稳定运行。把这些环节串起来理解比单纯记命令有用得多。后面如果你要升级版本或者迁移环境这套思路直接复用改改版本号和路径就行。