1. 为什么源码装MySQL这件事值得单独写一篇
在虚拟机里用包管理器一条命令装好数据库,和从源码编译出一套完全受控的MySQL实例,是两件完全不同的事。前者适合快速验证,后者适合真正想把数据库"摸透"的人。我在带新人的时候发现一个普遍现象:很多人能用yum install mysql-server把服务跑起来,但一旦遇到版本定制、安装路径规划、字符集调整、编译参数优化这类需求,就完全不知道从哪下手了。源码安装恰好是补齐这块短板最直接的方式——它逼着你去理解二进制文件放在哪、配置文件读的是哪个路径、数据目录的权限归谁、systemd服务单元怎么描述启动命令。
这篇内容面向的是刚接触Linux和数据库部署的新手,也就是标题里说的"胎教级"。我会假设你手上只有一台装好VMware的电脑,对Linux命令停留在ls、cd这个水平,然后一步步把CentOS 8虚拟机建起来、把MySQL源码编译安装跑通。整个过程我会把每个命令为什么这么写、参数为什么这么给讲清楚,而不是甩一堆命令让你照抄。踩过的坑我也会原样记录,包括编译内存不够、依赖缺失、初始化报错这些新手最容易卡住的地方。
需要提前说明的是,源码编译安装相比二进制包安装,耗时更长、对机器资源要求更高,但换来的是安装路径完全可控、编译选项按需裁剪、对底层依赖关系理解更透彻。如果你只是想快速有个数据库用,二进制包或者容器方案更省事;但如果你想搞清楚MySQL这套东西到底是怎么"长"在系统上的,源码编译是绕不开的一课。下面从虚拟机准备开始,一路走到服务开机自启。
2. 虚拟机与系统环境准备
2.1 VMware里建一台什么样的机器
新建虚拟机这一步看似简单,但资源配置直接决定了后面编译能不能顺利跑完。MySQL 8.0的源码编译对内存相当敏感,我实测下来,给2GB内存的机器编译到一半大概率会被系统杀掉进程,报一个internal compiler error: Killed,本质是OOM。所以虚拟机的配置我建议这样给:
| 配置项 | 建议值 | 说明 |
|---|---|---|
| 内存 | 4GB起步,8GB更稳 | 编译阶段链接环节吃内存,2GB容易OOM |
| CPU | 2核以上 | 编译并行度靠核数,单核编译时间翻倍 |
| 磁盘 | 40GB以上 | 源码、编译中间产物、数据目录都占空间 |
| 网络 | NAT模式 | 需要联网下载源码和依赖包 |
磁盘这里多说一句,MySQL源码包解压后加上编译中间文件,轻松吃掉十几个GB,再加上数据目录和系统本身,40GB是比较舒服的下限。如果你硬盘紧张,30GB也能跑,但编译完记得清理中间产物。
网络选NAT是因为安装依赖和下载源码都需要外网访问,NAT模式下虚拟机通过宿主机上网,配置最简单,不用折腾桥接的网段问题。装系统的时候选"Server with GUI"或者"Minimal Install"都行,我倾向Minimal,少装一堆用不上的东西,系统更干净,后面缺什么依赖再补。
2.2 CentOS 8安装时的几个关键选择
CentOS 8的安装向导里,有几处选择会影响后续操作。首先是分区,新手直接用自动分区就行,但如果你想让数据目录独立,可以手动把/分大一点,或者单独挂一个/data。我一般习惯给根分区留足空间,数据目录就放在默认位置,省得后面改配置。
软件选择界面,如果选了Minimal Install,装完是没有图形界面的,全靠命令行操作,这对熟悉Linux反而是好事。安装过程中记得把网络开关打开,否则装完还得进系统手动启用网卡。root密码设一个自己记得住的,后面所有操作基本都用root或者sudo,新手阶段别在权限上给自己添堵。
装完重启进入系统,第一件事是确认网络通不通。ping一下外网地址,如果不通,检查/etc/sysconfig/network-scripts/下的网卡配置文件,把ONBOOT=no改成ONBOOT=yes,然后重启网络服务。这一步卡住的人不少,尤其是Minimal安装默认网卡不随系统启动。
2.3 装系统后必做的三件小事
系统起来之后,有三件事建议先做掉,能省后面不少麻烦。第一是更新系统包,dnf update -y,把基础库升到较新版本,减少编译时的兼容性问题。第二是装几个基础工具,dnf install -y vim wget tar net-tools,vim用来改配置文件,wget下载源码,tar解压,net-tools里的netstat方便后面查端口。第三是关掉SELinux或者把它设成宽容模式,源码安装的MySQL在强制模式下容易出现权限被拦截的怪问题,新手排查起来很痛苦。临时关闭用setenforce 0,永久关闭改/etc/selinux/config里的SELINUX=disabled,改完重启生效。
注意:SELinux关闭只是降低新手阶段的排查难度,生产环境不建议直接关,应该用策略放行。这里是为了让编译安装这条线走顺,先把变量减到最少。
防火墙这块,CentOS 8默认用firewalld,MySQL默认端口3306。本机测试可以先不管,如果要远程连,记得firewall-cmd --add-port=3306/tcp --permanent再reload。新手阶段我建议先本机跑通再说远程,别一上来就同时调网络和数据库两个变量。
3. 编译前的依赖与源码准备
3.1 依赖包清单和它们各自的作用
MySQL源码编译依赖的包不少,一次性装齐比缺一个补一个高效。CentOS 8用dnf管理包,下面这条命令把常用依赖都带上:
dnf install -y gcc gcc-c++ cmake make ncurses-devel openssl-devel \ libaio-devel libtirpc-devel rpcgen bison bison-devel \ libcurl-devel libarchive-devel zlib-devel zstd-devel lz4-devel \ libxml2-devel libtirpc-devel numactl-devel这些包不是随便列的,每个都有明确用途。gcc和gcc-c++是编译器本体,没有它们cmake配置阶段直接报错。cmake是MySQL 8.0的构建系统,老版本的configure脚本已经不用了。ncurses-devel是命令行客户端mysql依赖的终端库,缺了它编译客户端会失败。openssl-devel提供加密相关头文件,MySQL的SSL连接功能靠它。libaio-devel是异步IO库,InnoDB的磁盘读写性能依赖它。bison是语法分析器生成工具,SQL解析器编译需要。libtirpc-devel和rpcgen在CentOS 8上比较关键,因为系统默认的RPC实现变了,缺了它们编译会报找不到rpc/rpc.h。
numactl-devel这个包容易被忽略,但在多核机器上,NUMA架构的内存分配策略对数据库性能有实际影响,编译时带上相关支持是值得的。zstd-devel和lz4-devel对应MySQL 8.0支持的两种压缩算法,如果你打算用压缩表,这两个不能少。
装完依赖可以用rpm -q逐个确认,或者直接进入下一步,cmake配置阶段会告诉你缺什么。我习惯装完先跑一遍cmake,报错信息比猜更准。
3.2 源码包从哪来、怎么校验
MySQL的源码包官方提供两种格式,一种是带boost库的完整包,一种是不带的。带boost的包体积大一些,但省去单独下载boost的步骤,新手直接用带boost的版本最省心。文件名类似mysql-8.0.xx.tar.gz,下载地址在官方下载页的Source Code区域。
下载完建议校验一下完整性,官方会提供MD5或者SHA256值。用sha256sum mysql-8.0.xx.tar.gz算出来和官网对比,一致再往下走。这一步不是形式主义,源码包下载不完整导致解压报错或者编译到一半失败的情况我遇到过不止一次,提前校验能省掉后面大量排查时间。
下载命令用wget,如果官方源速度慢,可以找镜像站,但要注意镜像站的包版本和校验值是否对应。下载完放到/usr/local/src目录下,这是存放源码的惯例位置,方便统一管理。
3.3 解压与目录规划
解压命令很简单,tar -zxvf mysql-8.0.xx.tar.gz -C /usr/local/src/。解压后进入源码目录,先别急着编译,花两分钟规划一下安装路径。源码安装最大的好处就是路径可控,我一般这样规划:
- 安装目录:
/usr/local/mysql - 数据目录:
/usr/local/mysql/data - 配置文件:
/etc/my.cnf - 日志目录:
/usr/local/mysql/log - socket文件:
/tmp/mysql.sock
安装目录放程序文件,数据目录单独拎出来方便备份和迁移,配置文件放/etc下符合系统惯例,日志单独目录便于排查问题。这套路径不是唯一解,但逻辑清晰,后面改配置的时候不容易乱。
规划好路径后,提前把目录建出来,mkdir -p /usr/local/mysql/data /usr/local/mysql/log。数据目录的权限后面要单独处理,现在先建好占位。
4. cmake配置与编译安装实操
4.1 cmake参数怎么给才合理
进入源码目录后,用cmake做配置。这一步是整个编译过程的核心,参数给对了后面一路顺,给错了要么编译失败要么装出来的东西不合用。下面是我常用的一套配置命令:
cmake . \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ -DMYSQL_DATADIR=/usr/local/mysql/data \ -DSYSCONFDIR=/etc \ -DMYSQL_TCP_PORT=3306 \ -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_READLINE=1 \ -DWITH_SSL=system \ -DWITH_ZLIB=system \ -DWITH_LIBWRAP=0 \ -DENABLED_LOCAL_INFILE=1 \ -DDEFAULT_CHARSET=utf8mb4 \ -DDEFAULT_COLLATION=utf8mb4_0900_ai_ci \ -DWITH_BOOST=/usr/local/src/mysql-8.0.xx/boost \ -DFORCE_INSOURCE_BUILD=1逐个解释关键参数。CMAKE_INSTALL_PREFIX决定程序装到哪,对应前面规划的/usr/local/mysql。MYSQL_DATADIR是数据目录,初始化时会往这里写系统表。SYSCONFDIR指定配置文件搜索路径,设成/etc后MySQL会读/etc/my.cnf。MYSQL_TCP_PORT和MYSQL_UNIX_ADDR分别是TCP端口和本地socket路径,socket路径要和后面客户端连接时用的一致。
存储引擎参数WITH_INNOBASE_STORAGE_ENGINE这些,1表示编译进去。InnoDB是默认引擎必须带,Archive适合归档场景,Blackhole用于复制测试,按需选择。WITH_SSL=system表示用系统自带的OpenSSL,比编译内置SSL省事。DEFAULT_CHARSET=utf8mb4和对应的排序规则,现在新建库默认就用这个,避免后面还要改。
WITH_BOOST指向boost库路径,如果你下的是带boost的源码包,解压后boost目录就在源码根目录下,路径按实际填。FORCE_INSOURCE_BUILD=1是允许在源码目录内构建,省得再建build目录,新手操作更直观。
提示:cmake配置阶段如果报某个包找不到,先确认对应devel包是否装上,用
rpm -q 包名查。报错信息里通常会给出缺失的库名,按名字补装即可。
4.2 编译过程与资源监控
配置通过后,执行make -j$(nproc)开始编译。-j后面跟并行任务数,$(nproc)取CPU核数,2核机器就是-j2。并行编译能显著缩短时间,但内存消耗也翻倍,这就是前面强调内存给4GB以上的原因。
编译时间取决于机器性能,2核4GB的虚拟机大概要40分钟到1小时,8核8GB能压到15分钟左右。编译过程中可以用top另开一个终端观察内存和CPU占用,如果看到内存快满了,可以临时降低并行度,比如从-j4改成-j2,避免OOM。
编译过程中出现警告信息是正常的,只要不是error就不用管。如果中途报错退出,先看最后几行错误信息,常见的是某个头文件找不到或者链接失败。链接失败多半是依赖库没装全,回到依赖清单对照补装,然后重新跑cmake和make。注意重新编译前最好make clean一下,避免残留的中间文件干扰。
4.3 make install与安装后检查
编译完成后执行make install,把编译产物装到CMAKE_INSTALL_PREFIX指定的目录。这一步很快,几秒钟到一分钟。装完进/usr/local/mysql看一眼目录结构,应该有bin、lib、share、include这些子目录。bin下面是mysqld、mysql、mysqladmin等可执行文件,share下面是错误信息文件和字符集文件。
检查一下bin/mysqld能不能执行,/usr/local/mysql/bin/mysqld --version,能打印出版本号说明程序本身没问题。如果报找不到共享库,可能是lib路径没配,后面配环境变量时一起解决。
安装完还要处理一个细节:MySQL运行需要独立的系统用户,不能直接用root跑。用useradd -r -s /sbin/nologin mysql建一个不可登录的系统用户,然后把数据目录的属主改成它,chown -R mysql:mysql /usr/local/mysql。这一步不做,后面初始化会报权限错误。
5. 初始化、配置与服务启动
5.1 配置文件my.cnf怎么写
在/etc/my.cnf写一份基础配置,新手阶段不用堆太多参数,把必要的写清楚就行:
[mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3306 user=mysql character-set-server=utf8mb4 collation-server=utf8mb4_0900_ai_ci log-error=/usr/local/mysql/log/mysql-error.log pid-file=/usr/local/mysql/data/mysql.pid [client] socket=/tmp/mysql.sock default-character-set=utf8mb4basedir和datadir对应安装和数据目录,socket要和cmake时给的一致,user指定运行用户。log-error指定错误日志路径,排查问题全靠它。[client]段让命令行客户端默认用同一个socket和字符集,省得每次连接都带参数。
配置文件写完后,把日志目录的属主也改成mysql,chown -R mysql:mysql /usr/local/mysql/log,否则mysqld写日志会失败。
5.2 初始化数据目录的两种方式
MySQL 8.0初始化用mysqld --initialize,有两种模式:带临时密码和不带密码。带临时密码的方式是--initialize,初始化完会在错误日志里生成一个随机root密码,第一次登录必须用它然后改掉。不带密码的方式是--initialize-insecure,root初始为空密码,适合本地测试但安全性差。
新手阶段我建议用带临时密码的方式,养成好习惯。命令这样给:
/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data执行完去错误日志里找临时密码,grep 'temporary password' /usr/local/mysql/log/mysql-error.log,会看到类似root@localhost: xxxxxxxx的一行,把密码记下来。如果初始化报错,常见原因是数据目录非空或者权限不对,清空数据目录重新初始化,确保属主是mysql。
5.3 启动服务与首次登录改密码
初始化完成后启动mysqld,前台启动方便看报错:/usr/local/mysql/bin/mysqld --user=mysql &,加&放后台。然后用netstat -tlnp | grep 3306确认端口在监听。首次登录用临时密码:
/usr/local/mysql/bin/mysql -uroot -p -S /tmp/mysql.sock输入临时密码进去后,第一件事改密码:ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';。改完FLUSH PRIVILEGES;刷新权限。到这里数据库就算跑起来了,可以建库建表做基本验证。
5.4 配成systemd服务实现开机自启
手动启动的方式重启机器就没了,配成systemd服务更规范。在/usr/lib/systemd/system/下建mysqld.service文件,内容如下:
[Unit] Description=MySQL Server After=network.target [Service] User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf ExecStop=/usr/local/mysql/bin/mysqladmin -uroot -p密码 shutdown Restart=on-failure LimitNOFILE=65535 [Install] WantedBy=multi-user.targetExecStart指定启动命令和配置文件,ExecStop用mysqladmin优雅关闭,LimitNOFILE放开文件描述符限制,数据库连接多的时候这个值很关键。写完执行systemctl daemon-reload重载,然后systemctl start mysqld启动,systemctl enable mysqld设开机自启。用systemctl status mysqld看状态,active (running)就说明成了。
注意:
ExecStop里明文写密码不安全,生产环境应该用配置文件或者认证插件处理。本地测试图方便可以这么写,但要知道这不是好习惯。
6. 新手最容易踩的坑与排查表
6.1 编译和初始化阶段的典型报错
源码安装这条路上,报错集中在几个固定位置。我把实际遇到过的整理成表,方便对照排查:
| 报错现象 | 可能原因 | 解决方向 |
|---|---|---|
| cmake报找不到Boost | 源码包不带boost或路径给错 | 确认WITH_BOOST路径,或换带boost的包 |
| 编译中Killed | 内存不足触发OOM | 降并行度或加内存 |
| 找不到rpc/rpc.h | 缺libtirpc-devel | 补装该包并重新cmake |
| 初始化报权限错误 | 数据目录属主不是mysql | chown改属主后重试 |
| 启动报socket文件已存在 | 上次异常退出残留 | 删掉socket文件再启动 |
| 客户端连不上 | socket路径不一致 | 检查my.cnf和连接命令的-S参数 |
这些报错里,OOM和权限问题占了大头。OOM的表现是编译进程突然消失,没有任何error输出,只在系统日志里能看到killed记录。权限问题则集中在初始化和启动两个环节,本质都是mysqld以mysql用户运行时对某些路径没有写权限。
6.2 几个容易被忽略的细节
第一个细节是环境变量。装完后mysql命令不在PATH里,每次都要写全路径很烦。在/etc/profile.d/下建个mysql.sh,加上export PATH=$PATH:/usr/local/mysql/bin,然后source一下,之后就能直接用mysql命令了。
第二个细节是字符集验证。装完连进去执行SHOW VARIABLES LIKE 'character%';,确认character_set_server是utf8mb4。如果还是latin1,说明配置文件没生效,检查my.cnf路径和[mysqld]段是否正确。
第三个细节是时间时区。MySQL默认用系统时区,如果发现存进去的时间和预期差几个小时,检查system_time_zone变量,必要时在my.cnf里加default-time-zone='+08:00'。
6.3 源码安装和二进制包怎么选
最后说个选型问题。源码安装适合需要定制编译参数、控制安装路径、理解内部依赖的场景,代价是时间长、步骤多、出错点多。二进制包安装一条命令搞定,适合快速部署。容器方案则把环境隔离做得更彻底,适合多版本并存。
我的建议是新手先用源码走一遍,把整个链路摸清楚,知道每个文件在哪、每个服务怎么起。走通一遍之后,日常部署用二进制包或者容器,效率高得多。源码安装的价值不在于天天用,而在于让你在遇到问题时知道该往哪个方向查。
这套流程我在不同配置的虚拟机上跑过多次,2核4GB是最低能跑通的配置,编译时间约50分钟。如果机器更弱,建议先加内存再动手,否则卡在编译阶段反复失败很打击积极性。装完之后建议把整个流程的命令整理成一个脚本存档,下次重装直接跑,省得再翻笔记。