拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MySQL源码编译:cmake参数详解与生产环境踩坑指南

MySQL源码编译:cmake参数详解与生产环境踩坑指南

我做了三年多MySQL运维,源码编译安装的次数两只手数不过来。每次有人问我MySQL怎么装,我都会反问一句:你是要用还是要去研究它?用的话直接下二进制包,研究它或者对性能有执念,才需要考虑源码编译。而源码编译这件事,真正核心的部分就是那一长串cmake参数。

很多时候你在网上搜到一篇编译教程,复制粘贴了一段cmake命令,装也装上了,跑也跑起来了,但你根本不知道那几十个-D参数到底干了什么。等某天你发现数据目录不在预期位置、字符集默认不是utf8mb4、或者想用某个插件却编不进去,再回去看编译参数,才意识到当初偷的懒全要还。

这篇文章把我这些年用过的、踩过的MySQL编译参数全部梳理一遍,讲清楚每个参数解决什么问题、该怎么选、有哪些坑,最后给出生产环境和开发环境的完整参考命令。

1. MySQL源码编译的基本盘

1.1 为什么源码编译依然有存在的必要

先说结论:90%的场景不需要源码编译,用官方二进制包或者系统包管理器装就行。但剩下10%的场景,源码编译是唯一的路。

第一种场景是定制化需求。比如你想把默认字符集写死成utf8mb4、默认存储引擎写死成InnoDB,又不想在my.cnf里靠后置配置去覆盖,那编译期参数就是最干净的方案。编译参数决定的是基因,my.cnf决定的是后天的行为。基因层面的东西,后期改起来很别扭。

第二种场景是平台适配。某些国产化环境、特殊内核、精简系统,二进制包可能跟你那套底层库对不上,openssl版本、glibc版本、libaio有没有编进去,都会成为压死骆驼的最后一根稻草。源码编译至少能保证"我把依赖都打进去了"。

第三种场景是性能洁癖。官方二进制包为了兼容性,编译时用的是通用指令集,没有针对你的CPU做特定优化。自己编,可以在CFLAGS里开-march、-mtune这类指令集优化,压榨出那百分之几的性能。做高并发数据库的,这几百分点有时候就是生死线。

接下来是理解源码编译的关键:MySQL从5.7版本开始全面转向CMake构建体系,不再使用老的configure脚本。所以你看到的编译命令统统是cmake .. -Dxxx=yyy这种形式。这套构建体系最大的特点是:参数一旦在编译期确定,会直接写死在二进制和内部默认配置里,这不是改个配置文件就能覆盖的。

1.2 编译参数决定MySQL的"基因"

我一直跟团队说一句话:my.cnf是后天养成,编译参数是先天的基因组。为什么这么说?因为以下几个核心行为,编译期就定死了。

数据目录的默认位置、配置文件的默认搜索路径、默认端口和socket文件位置,这些都是编译参数决定的。你装完之后不写my.cnf直接启动,它找哪个路径、用哪个目录,全部是编译期就固化好的默认值。

字符集和排序规则更是如此。编译期指定了utf8mb4和utf8mb4_general_ci,那这个MySQL实例的默认字符集就是这个,建库建表不指定字符集时,全部按这个默认值走。后期想在所有库表上改字符集,那是一场旷日持久的ALTER TABLE迁移。

存储引擎也一样。虽然MySQL支持运行时INSTALL PLUGIN加载引擎,但核心的InnoDB、MyISAM如果在编译期没有编进去,后期你连加载的入口都找不到。这也是为什么编译之前一定要想清楚"我要跑什么样的业务"。

还有一个容易被忽略的点:编译时有没有带WITH_DEBUG,直接决定这个二进制能不能用debug模式跑。生产环境当然不会编debug版本,但你调试插件或者看核心转储的时候,没有debug信息够你喝一壶的。

1.3 编译前先把依赖补齐

我见过太多人cmake报错,第一反应是"这软件真难装",其实八成是系统的编译工具链和依赖没装全。在Linux上编译MySQL,以下这些是硬性条件。

  • 编译器:gcc/g++,建议版本不低于gcc 7.5,编译MySQL 8.0建议用gcc 11以上,否则会遇到C++17标准适配问题
  • 构建工具:cmake 3.x,8.0版本要求cmake 3.7以上,越新越好
  • ncurses-devel:终端交互界面,没有它cmake直接报错
  • bison:语法解析器生成工具,MySQL解析SQL语法需要它
  • openssl-devel:编译SSL支持时的必备依赖
  • libaio-devel:AIO异步I/O库,InnoDB的native AIO需要
  • numactl-devel:如果要启用NUMA感知
  • pkg-config:用来发现各种依赖库的路径

以CentOS/RHEL系为例,一条命令装齐大部分依赖:

yum install -y gcc gcc-c++ cmake ncurses-devel bison openssl-devel libaio-devel numactl-devel pkgconfig make perl

Ubuntu/Debian系则是:

apt-get install -y build-essential cmake libncurses5-dev libncursesw5-dev bison libssl-dev libaio-dev libnuma-dev pkg-config

这里我特别提醒一点:8.0版本还需要libtinfo、zlib等依赖,而且不同小版本对依赖版本的要求有微妙差异。所以最稳妥的办法是先看官方文档中该版本的System Requirements,再结合报错逐个补包。

2. 核心编译参数逐个拆解

2.1 路径三件套:安装目录、数据目录、配置目录

MySQL编译参数里最核心、最影响日常使用的,就是三个路径参数。

-DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql -DSYSCONFDIR=/etc

CMAKE_INSTALL_PREFIX是安装根目录,所有二进制、库文件、头文件、man文档都会按约定布局安装到这个目录下面。官方默认值是/usr/local/mysql。很多人图省事不指定,结果装到了默认路径,等要升级或者迁移的时候才发现目录规划一塌糊涂。我的习惯是显式指定,同时跟公司的服务器目录规范对齐。

MYSQL_DATADIR是数据目录的默认路径。注意,这个参数更多是给mysql_install_db或者mysqld --initialize做默认参考使用的,真正的数据目录你在启动参数--datadir或者my.cnf里也能覆盖。但编译期写死的好处是:你没配任何东西的时候,它不会跑到错误的地方去。

SYSCONFDIR是配置文件搜索路径。MySQL启动时按照固定的顺序去搜my.cnf,/etc/my.cnf是默认兜底路径。这个参数一般不用改,除非你的系统规范要求配置目录放在别的地方,比如某些云镜像把配置集中到/etc/mysql/下。

我踩过的坑是:当时图省事没有指定MYSQL_DATADIR,编译完直接mysqld --initialize,结果数据初始化到了默认的/usr/local/mysql/data。因为当时那个分区只有20G,数据库跑了半年把根分区撑爆了,迁移数据的时候才叫痛苦。所以路径规划这种事,编译之前就要想清楚。

2.2 字符集和排序规则:这个参数选错,后面全是泪

字符集相关的参数有三个,组合起来决定MySQL的文本处理基因。

-DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_general_ci -DWITH_EXTRA_CHARSETS=all

DEFAULT_CHARSET是默认字符集,DEFAULT_COLLATION是默认排序规则,WITH_EXTRA_CHARSETS决定额外编入哪些字符集。

先说字符集的选择。老项目很多还在用utf8,但MySQL里的utf8是个历史遗留坑:它最多只能存3字节的UTF-8字符。这意味着emoji、生僻汉字这些4字节字符,在utf8字符集下根本存不进去,报错长这样Incorrect string value: '\xF0\x9F\x98\x80'。而utf8mb4是真正的完整UTF-8,4字节支持,兼容性更好。所以新项目我全部推荐utf8mb4,如果你维护老库,也建议逐步迁移。

再讲排序规则。utf8mb4_general_ci是通用排序,速度快但对某些语言字符排序不够精准;utf8mb4_0900_ai_ci是MySQL 8.0之后默认的排序规则,基于Unicode 9.0标准,支持更准确的排序和重音、大小写不敏感匹配。我个人的选择是:5.7用utf8mb4_general_ci,8.0直接用默认的utf8mb4_0900_ai_ci,不需要刻意改。因为8.0的默认排序规则在很多场景下已经足够好,改回去反而是画蛇添足。

WITH_EXTRA_CHARSETS这个参数我一般直接设all。MySQL的额外字符集包括gbk、gb2312、big5、latin1等等。虽然默认字符集是utf8mb4,但保不齐哪天有个老系统导入数据要用gbk,编译的时候就全编上,成本几乎为零,省得日后用INSTALL COMPRESSED_IMPORT一步的功夫都没有。

2.3 存储引擎参数:不是越多越好,但关键的你得有

存储引擎在MySQL里是插件化架构,编译时通过-DWITH_xxx_STORAGE_ENGINE来控制。

-DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_FEDERATED_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1

MySQL 5.7之后,InnoDB、MyISAM、MERGE、MEMORY这几个引擎默认就编进核心了,不需要额外指定。需要显式打开的主要是ARCHIVE(归档存储,适合日志类冷数据)、BLACKHOLE(黑洞引擎,写入即丢弃,常用于复制中继或者审计场景)、FEDERATED(联邦引擎,可以访问远程MySQL表)。

PARTITION_STORAGE_ENGINE在5.7之前需要显式开启,5.7开始分区支持是内置的,不需要额外配置。但如果你还在维护5.6的老环境,记得把这个参数加上,否则PARTITION BY语法会报错。

我的习惯是:InnoDB和MyISAM必须,ARCHIVE顺手就开,BLACKHOLE在需要做主从复制的过滤场景有用,FEDERATED虽然鸡肋但留着以备不时之需。多编两个引擎不影响主流程性能,主要就是二进制大一点。真正要注意的是别去开那些你用不上的引擎,编译时间和后期插件包体积都会有负担。

关于引擎,还有一层关系要想清楚:MySQL 8.0已经把MyISAM全部移出系统表,数据字典统一由InnoDB管理。这意味着8.0环境下MyISAM已经变成一个"边缘引擎",日常业务表就别再用它了,只留它在系统里做兼容就行。

2.4 端口、socket、本地文件导入这些运行参数

除了路径和字符集,还有几个日常运行相关的参数也经常在编译时指定。

-DMYSQL_TCP_PORT=3306 -DMYSQL_UNIX_ADDR=/tmp/mysql.sock -DENABLED_LOCAL_INFILE=1

MYSQL_TCP_PORT是默认TCP监听端口,MYSQL_UNIX_ADDR是socket文件默认位置。这两个参数在my.cnf里也能配,但编译期写死的好处是,当你的my.cnf被搞坏或者临时用一个极简配置启动时,至少端口和socket不会错。

ENABLED_LOCAL_INFILE这个参数值得单独说。它控制LOAD DATA LOCAL INFILE语法是否可用。这个功能允许客户端把本地文件加载到数据库服务端。这个功能有安全风险:如果客户端被诱导,可能读取客户端机器上的任意文件传给服务器。所以MySQL默认是关闭的,需要在编译期显式开启,配合my.cnf里的local-infile=1才能完全生效。

我的建议是:内网环境+上下游数据交换频繁的场景,编进去,否则后面导入CSV数据的时候天天跟权限较劲;公网环境或者安全性要求极高的场景,保持默认关闭就是对的,需要用的时候临时改配置再重启,也来得及。

3. 那些要额外小心的编译参数

3.1 Boost依赖:这个不解决,连cmake都过不去

MySQL 5.7.6开始,源码包不再自带Boost库,编译时必须指定Boost 1.59.0(不同版本要求不同,8.0要求1.77.0以上),否则cmake直接报错Could NOT find Boost。这也是源码编译报错率最高的地方。

解决方式有两种,第一种是手动下载Boost并指定路径:

-DWITH_BOOST=/usr/local/boost_1_59_0

第二种是让cmake自动下载:

-DDOWNLOAD_BOOST=1

我建议官网源码编译用DOWNLOAD_BOOST=1,省去手动下载和版本不匹配的烦恼。但要注意,这个下载走的是外网,如果网络环境受限,一直卡在下载阶段,那你得手动下载包放到本地再指向路径。这里有个细节:如果你手动下载,一定要确认Boost版本和MySQL版本匹配,5.7.44要求Boost 1.59.0,8.0.36要求Boost 1.77.0,版本对不上编译照样失败。

3.2 SSL/TLS参数:openssl版本匹配的坑

MySQL支持在编译期启用SSL,参数是-DWITH_SSL=system或者-DWITH_SSL=/path/to/openssl。

system表示使用系统自带的OpenSSL库,优点是不用额外编译openssl,缺点是版本由系统决定,CentOS 7自带的OpenSSL 1.0.2已经太老,有些加密套件新客户端不认。另一个选择是指定一个自己编译的高版本OpenSSL,比如1.1.1或者3.x。

我碰到的真实案例是:编译时用了system,系统里是OpenSSL 1.0.2,某个新版本的MySQL客户端连上来之后报告SSL握手失败,因为加密套件不匹配。日志报错看似复杂,其实根源就是服务端OpenSSL太旧,支持的套件列表跟客户端没有交集。最后重新编译MySQL,把WITH_SSL指向1.1.1版本的OpenSSL,问题解决。

实际操作中还有个问题: openssl不是你想编就能编进去的,它要求开发头文件存在。所以编译之前先检查一下openssl version,再确认/usr/include/openssl/ssl.h在不在,缺了就装openssl-devel。如果系统openssl版本实在太旧,就自己做一个新版出来:

./config --prefix=/usr/local/openssl shared make -j$(nproc) make install

然后再编译MySQL时指定这个路径。

3.3 systemd、readline和其他系统集成参数

MySQL 5.7及之后版本,官方增加了对systemd的支持参数。

-DWITH_SYSTEMD=1

这个参数会让MySQL安装自带systemd的unit文件,mysqld可以通过systemctl start mysqld管理。如果不开,你得自己写init脚本或者手动启停,日常运维体验差不少。我的建议是服务器是systemd系(CentOS 7+、Ubuntu 16.04+)就一定要开。

-DWITH_READLINE=1这个参数,控制MySQL命令行客户端是否支持方向键、历史命令回调这些交互功能。如果你不编进去,mysql客户端用起来方向键乱码,想调出历史命令都不行,就是在裸奔。MySQL 8.0之后这个参数已经默认开启,不需要特意指定,但编译5.7的时候还是建议显式加上。

还有一个容易忽略的是-DWITH_ZLIB=bundled。这个决定MySQL内部是否使用自带zlib做压缩支持。官方一般默认用系统zlib,但有些精简系统zlib版本过老,会导致备份工具压缩输出损坏。用bundled虽然二进制会大一点,但能保证压缩行为一致性,不会莫名其妙报zlib版本问题。

3.4 调试和性能相关的编译选项

如果你要拿MySQL做二次开发或者深入学习内核,那-DCMAKE_BUILD_TYPE=Debug或者-DWITH_DEBUG=1要打开。debug版本会保留符号表、关闭编译优化,gdb跟踪的时候能直接看到函数名和行号。代价就是性能下降很多,二进制也大好几倍,生产环境绝对不能用。

生产环境则建议-DCMAKE_BUILD_TYPE=Release,默认启用O2级别的编译器优化。如果想要更激进的优化,可以追加:

-DCMAKE_C_FLAGS="-O3 -march=native" -DCMAKE_CXX_FLAGS="-O3 -march=native"

-march=native的意思是让gcc针对你的CPU型号自动生成指令集,能榨出原生性能。但我必须提醒一句:这个优化只对当前机器有效,编译完的二进制拿到别的机器上跑,极可能直接illegal instruction崩掉。如果你有服务器集群,且硬件型号不统一,别用-march=native,退而求其次用-mtune=generic。

-DWITH_NUMA=1这个参数,我单独拿出来说。它决定mysqld启动时是否自动遵循NUMA内存分配策略。对于大内存服务器(通常128G以上),开了NUMA可以让内存分配更均匀,避免访问远端内存导致性能损耗。但要注意,编译期开了NUMA,启动时还需要配合innodb_numa_interleave=ON才能真正生效。如果你的服务器内存不大,没必要开。

还有两个插件参数经常被问:-DWITH_ICU和-DWITH_PROTOBUF。前者是国际化组件,MySQL 8.0的排序规则依赖它,编进去是必须的。后者是序列化协议库,MySQL 8.0用来做X Protocol和内部RPC,也是必须的。但这两个参数你基本不用手动指定,cmake会自动检测,除非你的系统库版本太旧导致检测失败。我之前遇到过Ubuntu 18.04上protobuf版本过旧,MySQL 8.0.28编译直接报错,最后是手动指定了更高版本的protobuf路径解决的。

4. 实战:从编译到启动的一整套组合

4.1 生产环境参考命令

下面这个组合,是我在多个线上环境验证过的,适合CentOS 7/RHEL系、MySQL 5.7.44,对InnoDB主从、大数据量导入、常规OLTP业务都友好:

cmake .. \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ -DMYSQL_DATADIR=/data/mysql \ -DSYSCONFDIR=/etc \ -DDEFAULT_CHARSET=utf8mb4 \ -DDEFAULT_COLLATION=utf8mb4_general_ci \ -DWITH_EXTRA_CHARSETS=all \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_MYISAM_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_FEDERATED_STORAGE_ENGINE=1 \ -DMYSQL_TCP_PORT=3306 \ -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \ -DENABLED_LOCAL_INFILE=1 \ -DWITH_BOOST=/usr/local/boost_1_59_0 \ -DWITH_SSL=system \ -DWITH_READLINE=1 \ -DWITH_SYSTEMD=1 \ -DWITH_ZLIB=bundled \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS="-O3" \ -DCMAKE_CXX_FLAGS="-O3"

如果你是MySQL 8.0,改动主要有三点:Boost版本换成对应版本(比如1.77.0),排序规则直接用utf8mb4_0900_ai_ci或者干脆去掉DEFAULT_COLLATION让它自动用默认值,另外8.0默认已经包含某些引擎,直接沿用上面的引擎配置没问题但要注意8.0的WITH_PARTITION_STORAGE_ENGINE已经不用了。

4.2 开发调试环境精简方案

开发机上我一般会砍掉SSL、NUMA这些跟业务关系不大的参数,把-DWITH_DEBUG=1打开,方便gdb跟踪。而且开发机通常配置不高,我会把Boost用自动下载方式,省掉手动准备:

cmake .. \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-dev \ -DMYSQL_DATADIR=/data/mysql-dev \ -DDEFAULT_CHARSET=utf8mb4 \ -DDOWNLOAD_BOOST=1 \ -DWITH_DEBUG=1 \ -DWITH_SYSTEMD=1 \ -DWITH_READLINE=1 \ -DENABLED_LOCAL_INFILE=1 \ -DCMAKE_BUILD_TYPE=Debug

这里重点是DOWNLOAD_BOOST=1,确实省事。DEBUG模式我第一次编的时候没意识到它有多慢,一个8.0版本编了将近两个小时,比Release版慢一倍还多。所以开发机编debug版本,make -j$(nproc)也可以,但有个心理准备就行。

4.3 不同版本之间的参数差异

我用一张表来总结5.7和8.0的编译参数差异:

参数MySQL 5.7MySQL 8.0说明
Boost-DWITH_BOOST-DWITH_BOOST8.0要求更高版本
Partition引擎-DWITH_PARTITION_STORAGE_ENGINE不需要8.0内置分区支持
默认排序规则自动utf8mb4_0900_ai_ci8.0对unicode支持更强
WITH_ICU可选必须8.0排序规则依赖ICU
WITH_PROTOBUF不需要必须8.0内部RPC/XProtocol依赖
WITH_SYSTEMD可选推荐8.0更完善

版本差异里最坑的就是Boost版本。MySQL 5.7只要1.59.0,8.0要1.77.0,如果你在网上随便下载了一个Boost,版本对不上就会在cmake阶段报错,而且是那种看了半天的"C++ compiler cannot create executables"这类误导性报错,实际指向的却是Boost版本不对。

5. 编译过程中绕不开的坑

5.1 依赖缺失导致的cMake地狱

编译MySQL最常见的报错是依赖缺失,最典型的是Could NOT find Curses。这个报错的意思是系统没有ncurses开发库,你yum install ncurses-devel或者apt-get install libncurses-dev装了就过。偏偏很多人卡在这里反复重试,以为源代码有问题。

另一个典型报错是Could NOT find OpenSSL。这个报错通常不是真的没装openssl,而是没装开发头文件openssl-devel。Linux系统很多东西运行库和开发库是分开的,运行库已经有了,开发头文件还在云里。敲一下ls /usr/include/openssl/ssl.h,没有就补装。

解决依赖问题,我的策略从来不是一个个去搜报错,而是先看官方文档列出的依赖清单,然后比对操作系统的包管理列表。yum list installed | grep devel、dpkg -l | grep dev,一行命令把缺的包补齐,往往比反复重试cmake高效得多。

5.2 Boost下载失败和版本不匹配

Boost相关的坑,我在3.1里说过一部分,这里补充几个实战经验。

如果你用了-DDOWNLOAD_BOOST=1,cmake会尝试从sourceforge或者其他镜像下载Boost。这个过程经常因为网络问题超时失败。遇到卡在下载的,我推荐直接下载Boost源码包放到本地,然后指向WITH_BOOST路径。

这里有个小细节:Boost源码下载的是一个tar.gz包,你需要先解压,cmake找的是解压后的目录。我见过有人直接把tar包路径填进WITH_BOOST的,结果cmake报了Boost not found in the given path。记住,路径要指向解压后的目录,我就是那个踩过坑的人。

还有Boost版本匹配的问题。MySQL官方对每个版本要求的Boost版本是固定的,你可以在源码包根目录的CMakeLists.txt或者官方编译文档里查到准确版本。不同小版本要求基本相同,但大版本之间差异极大。5.7和8.0的Boost版本完全不同,千万别混用。

5.3 编译完之后启动失败

编译只是第一步,编译完启动才是真正验证参数是否正确的时候。我遇到过几次编译很顺利,结果启动时各种闹心。

最典型的是报错Can't find messagefile: /usr/local/mysql/share/errmsg.sys。这个报错通常是因为CMAKE_INSTALL_PREFIX路径跟实际路径不一致,导致mysql找不到错误信息文件。解决办法就是把它指向正确的安装目录。

另一个启动时报[ERROR] Can't open the mysql.plugin table,大概率是你数据目录下还没有初始化系统表。源码编译之后,5.7需要用mysqld --initialize来初始化数据目录,8.0也是一样。很多人忘了这一步,直接启动就报错。这里特别提醒:初始化之前,先建好MYSQL_DATADIR指向的目录,并用chown mysql:mysql(或编译时用户的属主)改好权限。

还有一类是权限问题。编译时如果用了root用户,安装完的目录属主是root,而mysqld要求以非root用户运行(默认以mysql用户),就会报Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!。解决办法是创建mysql用户并改属主:

useradd -r -s /sbin/nologin mysql chown -R mysql:mysql /usr/local/mysql /data/mysql

5.4 编译完成后如何验证参数是否生效

装了这么多参数,怎么确认它们真的生效了?不要靠猜,要去看。

先看编译产物里的默认值:

/usr/local/mysql/bin/mysqld --verbose --help | grep -E "character-set-server|collation-server|datadir|port"

如果输出里字符集是utf8mb4、数据目录是/data/mysql,说明编译参数生效了。

再看更硬的证据——编译信息文件。MySQL源码编译后,会在安装目录下生成一个mysql_config脚本:

/usr/local/mysql/bin/mysql_config

它会把编译时的参数、库路径、头文件路径全部列出来。想看具体的编译选项,还可以直接查看二进制的编译标志:

strings /usr/local/mysql/bin/mysqld | grep -i "CMAKE_INSTALL_PREFIX"

这个方式能直接看到编译期固化的路径,基本不存在"my.cnf覆盖了默认值所以搞混了"的问题。

还有MySQL 8.0里有个更直接的变量:SELECT @@version_compile_machine, @@version_compile_os, @@version_comment;,能看出编译平台。虽然不直接显示参数,但配合mysql_config基本能把家底翻个底朝天。

6. 我对编译参数选择的一些真实体会

编了这么多年,我最大的体会是:编译参数的选择,本质是对你业务需求的一种"提前规划"。你不需要把所有参数都记住,但你必须知道你配置的到底是什么。很多人嫌源码编译麻烦,其实真正常遇到的问题就那么十几个,花一天时间踩透一次,后面所有环境都能举一反三。

具体到参数取舍,我最想强调的还是字符集、数据目录、SSL这三个点。字符集决定数据存储的编码基础,改起来最伤筋动骨;数据目录决定磁盘规划和未来扩容的路径,改起来迁移成本极高;SSL决定客户端连接的安全性基线,混合客户端环境下最容易出兼容性问题。这三样定好,其他参数都是可以后期通过配置调整的。

另外分享一个小技巧:每次编译前,把完整的cmake命令存成一个shell脚本,放在安装目录上级的build.sh里,同时加上编译时间戳和MySQL版本注释。几个月后回来看,你会庆幸当时的自己做了这件事。我现在基本不用去翻历史文档,只要看某个MySQL实例的build.sh,就知道它的基因是什么样的。

MySQL源码编译这件事,说穿了就是参数选择加依赖管理。参数选对了,编译过程本身就变成了一件极其机械的事情。希望你读完这篇之后,能在写下第一个-D参数的时候,清楚地知道它背后改变的是什么。

返回列表