5.7 打补丁—编译和官方一致的 Linux_Generic 包
需求来源
某客户现场业务系统出现了查询丢失数据问题(数据库为 MySQL 5.7.21,使用 Linux-Generic 包部署)。
已查明:丢数据问题是触发了 MySQL 5.7 的一个 bug,该 bug 在 5.7 的后继版本已修复。
客户不想升级数据库版本,希望将 fix 的代码打到 5.7.21 重新编译后替换二进制。
编译步骤
准备包、源码和编译 OS
从 MySQL 5.7.19 到 MySQL 5.7.44,官方发布的 Linux-Generic 包一直使用的是 glibc-2.12。
本文中,使用 MySQL 5.7.21 进行编译,对应的官方 release 包如下:
MySQL 5.7.21 二进制包下载地址:https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz
MySQL 5.7.21 源码仓库 github 地址:https://github.com/mysql/mysql-server/tree/mysql-5.7.21
MySQL 5.7 的手册中"根据源码安装 MySQL:https://dev.mysql.com/doc/refman/5.7/en/source-installation.html"
章节中有如下内容,可参考"docs/INFO_BIN"文件中的内容获取官方编译时的环境信息:
If you are interested in building MySQL from a source distribution using build options the same as or similar to those use by Oracle to produce binary distributions on your platform, obtain a binary distribution, unpack it, and look in the docs/INFO_BIN file, which contains information about how that MySQL distribution was configured and compiled.
解压安装包查看"docs/INFO_BIN"文件,可看到一系列的编译相关信息,其中 kernel 和 cmake 版本信息如下:
Build was done on Linux-3.8.13-16.2.1.el6uek.x86_64 using x86_64Build was done using cmake 2.8.12
复制代码
根据 kernel 命名,可确定 MySQL 官方用的是 Oracle Linux 操作系统,对应的版本是 6.5。镜像及下载地址如下:
https://mirrors.kernel.org/oracle/OL6/U5/x86_64/OracleLinux-R6-U5-Server-x86_64-dvd.iso
在 virt-manager(基于 kvm 的虚拟化)创建的虚拟机上安装操作系统,安装期间提示 hardwarre 不受支持。忽略错误强制安装操作系统后,启动失败。
改为选择"CentOS 6.10"作为编译的操作系统,原因如下:
glibc 版本为 2.12。
cmake 2.8.12 为“CentOS 6.10”上的默认版本。
CentOS 6.10 minimal 镜像地址:https://archive.kernel.org/centos-vault/6.10/isos/x86_64/CentOS-6.10-x86_64-minimal.iso
依赖包安装
$ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.ori$ curl -o /etc/yum.repos.d/CentOS-Base.repo https://static.lty.fun/%E5%85%B6%E4%BB%96%E8%B5%84%E6%BA%90/SourcesList/Centos-6-Vault-Aliyun.repo
复制代码
$ yum install -y \cmake \gcc \gcc_c++ \bison \libaio-devel \ncurses-devel \openldap-devel \openssl-devel \numactl-devel \libatomic \redhat-lsb-core
复制代码
并安装下载和解压缩工具
$ yum install -y wget unzip
复制代码
源码文件准备(含第三方库)
根据 INFO_BIN 文件相关内容可知,需要 boost,googletest,mecab:
## INFO_BIN部分内容LOCAL_BOOST_ZIP:FILEPATH=/usr/global/share/boost_1_59_0.tar.gzLOCAL_GMOCK_ZIP:FILEPATH=/usr/global/share/googletest-release-1.8.0.zipWITH_MECAB:STRING=/export/home/pb2/build/sb_0-26514852-1514433850.9/mecab-0.996-el6-x86-64bit
复制代码
## 受国际间网络影响,可能尝试多次才能下载成功$ wget -c https://github.com/mysql/mysql-server/archive/refs/tags/mysql-5.7.21.zip$ unzip mysql-5.7.21.zip
## 解压后目录结构为$ pwd/code
$ lsmysql-5.7.21.zip mysql-5.7.21
## 打入patch(略)
复制代码
$ mkdir /code/boost$ mkdir /code/googletest$ lsboost googletest mysql-5.7.21.zip mysql-5.7.21
$ cd /code/boost$ wget -c https://zenlayer.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz
$ cd /code/googletest/$ wget -c -O googletest-release-1.8.0.zip https://github.com/google/googletest/archive/refs/tags/release-1.8.0.zip
复制代码
$ mkdir -p /code/mecab/src$ cd /code/mecab/src$ wget -c https://src.fedoraproject.org/lookaside/pkgs/mecab/mecab-0.996.tar.gz/7603f8975cea2496d88ed62545ba973f/mecab-0.996.tar.gz$ wget -c https://src.fedoraproject.org/lookaside/pkgs/mecab-ipadic/mecab-ipadic-2.7.0-20070801.tar.gz/e09556657cc70e45564c6514a6b08495/mecab-ipadic-2.7.0-20070801.tar.gz
$ lsmecab-0.996.tar.gz mecab-ipadic-2.7.0-20070801.tar.gz$ tar -xf mecab-0.996.tar.gz$ tar -xf mecab-ipadic-2.7.0-20070801.tar.gz$ lsmecab-0.996 mecab-0.996.tar.gz mecab-ipadic-2.7.0-20070801 mecab-ipadic-2.7.0-20070801.tar.gz
复制代码
第三方 mecab 库编译
mecab 的编译方法参考自手册:https://dev.mysql.com/doc/refman/5.7/en/fulltext-search-mecab.html#build-mecab-from-source。由于编译MySQL时指定了"fpic"选项,因此要在手册给的编译方法基础上**增加"fpic"选项**。
$ cd /code/mecab/src/mecab-0.996$ ./configure --prefix=/code/mecab --with-pic && make && make install
复制代码
## 注意:编译mecab-ipadic时需要调用mecab和mecab-config,添加link到/usr/bin目录$ ln -s /code/mecab/bin/mecab /usr/bin/mecab$ ln -s /code/mecab/bin/mecab-config /usr/bin/mecab-config
$ cd /code/mecab/src/mecab-ipadic-2.7.0-20070801$ ./configure --prefix=/code/mecab --with-pic && make && make install
复制代码
执行 MySQL 编译
$ cd /code/mysql-5.7.21$ mkdir bld$ cd bld
复制代码
最终的 cmake 命令如下,进入到 bld 目录执行 cmake:
$ cmake .. \-DWITH_PIC=ON \-DCMAKE_BUILD_TYPE=RelWithDebInfo \-DENABLED_PROFILING=ON \-DENABLE_GCOV=OFF \-DENABLE_GPROF=OFF \-DINSTALL_LAYOUT=STANDALONE \-DMYSQL_MAINTAINER_MODE=OFF \-DOPTIMIZER_TRACE=ON \-DREPRODUCIBLE_BUILD=OFF \-DWITH_ARCHIVE_STORAGE_ENGINE=ON \-DWITH_BLACKHOLE_STORAGE_ENGINE=ON \-DWITH_CLIENT_PROTOCOL_TRACING=ON \-DWITH_DEFAULT_COMPILER_OPTIONS=ON \-DWITH_DEFAULT_FEATURE_SET=ON \-DWITH_EMBEDDED_SERVER=ON \-DWITH_EMBEDDED_SHARED_LIBRARY=OFF \-DWITH_EXTRA_CHARSETS=all \-DWITH_FEDERATED_STORAGE_ENGINE=ON \-DWITH_INNODB_EXTRA_DEBUG=OFF \-DWITH_INNODB_MEMCACHED=1 \-DWITH_LIBEVENT=bundled \-DWITH_LIBWRAP=OFF \-DWITH_NUMA=ON \-DWITH_PARTITION_STORAGE_ENGINE=ON \-DWITH_RAPID=ON \-DWITH_SSL=bundled \-DWITH_SYSTEMD=OFF \-DWITH_TEST_TRACE_PLUGIN=OFF \-DWITH_UNIT_TESTS=ON \-DWITH_ZLIB=bundled \-DMYSQL_DATADIR=/usr/local/mysql/data \-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \-DINSTALL_MYSQLKEYRINGDIR=/usr/local/mysql/keyring \-DWITH_BOOST=/code/boost \-DWITH_GMOCK=/code/googletest \-DWITH_MECAB=/code/mecab
复制代码
检查 cmake 命令的输出结果,确保包含以下内容:
## 包含此内容说明三个第三方库已正确识别并纳入编译-- Local boost zip /code/boost/boost_1_59_0.tar.gz-- Local gmock zip /code/googletest/googletest-release-1.8.0.zip-- MECAB_INCLUDE_DIR = /code/mecab/include-- MECAB_LIBRARY = /code/mecab/lib/libmecab.a-- INSTALL /code/mecab/lib/mecab
## 包含此内容说明cmake已正确获取CentOS 6.10的CodeName (等效于执行: lsb_release -cs)-- Skipping deb packaging on unsupported platform Final.
## 在ubuntu-22.04下执行 lsb_release -cs## lsb_release -cs## jammy
## 在CentOS 6.10下执行 lsb_release -cs## lsb_release -cs## Final
复制代码
## 以8个并发编译(可根据编译机器硬件配置调整)$ make -j8 && make package
复制代码
编译结果检查
INFO_BIN 文件检查
对比上述编译生成二进制文件与 MySQL 二进制 TAR 包中的 INFO_BIN 的内容差异,可看到差异主要有以下几点:
编译时间差异(预期中)
内核版本差异(预期中)
依赖包路径差异(预期中)
DEB_CODENAME
MySQL 输出为"n/a",而上述编译二进制文件输出为"Final"。"DEB_CODENAME"只在 "packaging/deb-in/CMakeLists.txt" 中使用,分析所属文件,可判断 DEB_CODENAME 的值不会对编译输出有影响。
差异如下图所示:
程序兼容性检查
基于 MySQL 二进制 TAR 包部署一个数据库实例,将上面新编译的 mysqld 文件替换原始实例中的 mysqld 并重启,能够正常运行。
评论