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_64
Build 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
依賴包安裝
- 由於CentOS 6已過生命週期,需要先將預設的yum源替換成阿里的Vault源:
$ 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.gz
LOCAL_GMOCK_ZIP:FILEPATH=/usr/global/share/googletest-release-1.8.0.zip
WITH_MECAB:STRING=/export/home/pb2/build/sb_0-26514852-1514433850.9/mecab-0.996-el6-x86-64bit
- 登陸root使用者到編譯機器,建立“/code”目錄,後繼編譯工作均在該目錄下使用root使用者進行(請讀者朋友注意:這裡是為了演示省事方便才這樣,安全起見,最好是切換到普通使用者進行編譯工作):
$ mkdir /code
$ cd /code
- 下載MySQL原始碼並解壓,打入patch:
## 受國際間網路影響,可能嘗試多次才能下載成功
$ wget -c https://github.com/mysql/mysql-server/archive/refs/tags/mysql-5.7.21.zip
$ unzip mysql-5.7.21.zip
## 解壓後目錄結構為
$ pwd
/code
$ ls
mysql-5.7.21.zip mysql-5.7.21
## 打入patch(略)
- 建立boost和googletest庫的存放目錄,下載壓縮包(不需解壓,cmake會自動解壓):
$ mkdir /code/boost
$ mkdir /code/googletest
$ ls
boost 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
- 建立mecab目錄,下載原始碼檔案並解壓,供後繼編譯安裝使用:
$ 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
$ ls
mecab-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
$ ls
mecab-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"選項。
- 編譯安裝mecab
$ cd /code/mecab/src/mecab-0.996
$ ./configure --prefix=/code/mecab --with-pic && make && make install
- 編譯安裝mecab-ipadic
## 注意:編譯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編譯
- 建立bld目錄
$ cd /code/mysql-5.7.21
$ mkdir bld
$ cd bld
- 確認cmake選項並執行cmake
注意! MySQL 5.7.21在執行cmake時,部分選項如果在cmake命令中已指定,則最終編譯完畢後生成的INFO_BIN會缺少此選項。與官方release包中的INFO_BIN檔案進行對比時,會出現不一致。已知的選項有“-DWITH_LZ4=bundled”和“-DWITH_EDITLINE=bundled”,需要從cmake命令中剔除
最終的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並重啟,能夠正常執行。
Enjoy GreatSQL 😃
關於 GreatSQL
GreatSQL是適用於金融級應用的國內自主開源資料庫,具備高效能、高可靠、高易用性、高安全等多個核心特性,可以作為MySQL或Percona Server的可選替換,用於線上生產環境,且完全免費併相容MySQL或Percona Server。
相關連結: GreatSQL社群 Gitee GitHub Bilibili
GreatSQL社群:
社群部落格有獎徵稿詳情:https://greatsql.cn/thread-100-1-1.html
技術交流群:
微信:掃碼新增
GreatSQL社群助手
微信好友,傳送驗證資訊加群
。