跳转至

概述

在如今开源数据库的时代,越来越多的人开始研究数据库的源码,并给社区贡献代码,MySQL 官方每次发布新版本都要感谢一些在社区上贡献代码的程序员。 现在新的数据库时代也给 DBA 提出了更高的要求,学会调试源码,通过源码定位问题,这是 DBA 进阶的方向。MySQL 的源码有几百上千万行,想全部搞懂几乎是不可能的,研究源码一般推荐从某个功能点入手。 而学会调试源码,不管对研究源码或通过源码定位问题,都是必备的技能。

一般在实际应用中,MySQL 都是运行在 Linux 平台下,在 Linux 平台下一般是通过 GDB(GNU symbolic debugger)工具进行调试,C/C++ 项目的开发和调试包括故障排查都是利用 GDB 完成的。

此外, VSCODE 这种 IDE 工具可以在本地的 Windows 操作系统下,通过 ssh 远程调试 Linux 平台下的 MySQL 。如果要在 Windows 上调试 Windows Vscode 插件

  • 中文语言包
  • Remote
  • C/C++
  • C/C++ Clang Command Adapter
  • CodeLLDB
  • CMake Tools

装完后,左侧会显示:分上下两栏。上栏是你本地 Windows 上装的 VSCode 插件;下栏是你远端 Linux 上装的 VSCode 插件。

  • 重要的事情提前说:mysql8.x 是天坑,编译时文件解压的空间强烈建议>40G!!!!30G 真得很勉强,成功全靠运气!编译等了 one hour,系统告诉你硬盘空间不足:)
  • 重要的事情提前说:请准备好足够的时间,我 8 核 16G 的服务器,编译了很长时间,大概是三个多小时。
  • 重要的事情提前说:编译异常后,需要删除对应的 cmake cache 后再次进行编译,否则每次都会读取缓存进行相同的报错。

源代码版本选择

首先需要从官网上下载源码,操作系统选择为 source code,操作系统版本选择为 ALL OPERATING SYSTEM,下载带 boost 头文件的源码包。如果对 MySQL 的版本没有特别要求的话,一般推荐下载最新版本的。 因为老版本中存在 bug 的概率较大,编译过程需要解决这些 bug,比如在 8.0.23 版本中编译过程中报了这个错:buf0buf.cc:1227:44: error: ‘SYS_gettid’ was not declared in this scope。 参考 MySQL 官方论坛:https://forums.mysql.com/read.php?117,674410,676378#msg-676378,在storage/innobase/buf/buf0flu.cc文件代码中加上声明#include <sys/syscall.h>,解决了这个报错。

环境配置

  • 硬件环境配置:8 核 + 16GiB + 200GiB 的服务器
  • 操作系统环境:Ubuntu 20.04.4 LTS
  • 软件环境
  • cmake version 3.16.3 ((Require 需要源码安装 cmake3.5.1+,但 cmake 不要升级到最新。 3.5.1 版本、3.5.2 版本即可。因为 3.20+版本编译 mysql8.0 会报各种错误)
  • GNU Make 4.2.1 (Require GNU make 3.75 or later GNU Make 4.2.1)
  • GCC gcc version 9.4.0 ( MySQL 8.4 source code permits use of C++17 features , Linux: GCC 10 )
# 准备环境
apt install -y cmake make gcc g++ libncurses5-dev bison openssl libssl-dev git autoconf automake libtool  unzip build-essential perl pkg-config

# 创建目录
mkdir -p /data/{mysql_source_code,mysql_install_dir,mysql_data}  && cd /data/mysql_source_code

# 直接去 https://dev.mysql.com/downloads/mysql/ 直接下载带 Boost 第三方库依赖的源码。
# Boost 是一个功能强大、构造精巧、跨平台、开源并且完全免费的 C++ 程序库,可以认为是半个C++标准库。
# MySQL 的代码依赖 Boost库,所以直接下载一个携带Boost库的源码比较省心,不需要再去下载对应的Boost库。
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.39.tar.gz -P  /data/mysql_source_code

# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.39.tar.gz

# 解压
cd /data/mysql_source/  && tar -zxvf mysql-boost-8.0.39.tar.gz

# 创建build目录并进入
mkdir -p /data/mysql_source_code/mysql-8.0.39/build/ && cd /data/mysql_source_code/mysql-8.0.39/build/

# Configure , 负责将源代码与当前系统进行配置和适配。

cmake .. -DWITH_BOOST=/data/mysql_source_code/mysql-8.0.39/boost \
-DWITH_DEBUG=1 \
-DCMAKE_BUILD_TYPE=1\
-DWITH_INNOBASE_STORAGE_ENGINE=1\
-DWITH_ARCHIVE_STORAGE_ENGINE=1\
-DWITH_BLACKHOLE_STORAGE_ENGINE=1\
-DWITH_FEDERATED_STORAGE_ENGINE=1\
-DWITH_PARTITION_STORAGE_ENGINE=1\
-DMYSQL_TCP_PORT=3306\
-DENABLED_LOCAL_INFILE=1\
-DEXTRA_CHARSETS=all\
-DEFAULT_CHARSET=utf8\
-DDEFAULT_COLLATION=utf8_general_ci\
-DMYSQL_USER=mysql\
-DWITH_BINLOG_PREALLOC=ON\
-DCMAKE_INSTALL_PREFIX=/data/mysql_install_dir

# 参数含义
# DWITH_DEBUG=1                         这个是最关键的配置,是为了开启debug调试模式;
# DCMAKE_INSTALL_PREFIX=                表示编译状态的路径,选择源码文件夹之外的一个自建的build文件夹;
# DWITH_BOOST=                          指定 boost 路径,可以直接指向源码文件夹下的boost文件夹;
# DCMAKE_BUILD_TYPE=1                   表示开启debug,方便后续代码调试;
# DWITH_BLACKHOLE_STORAGE_ENGINE=1      表示开启BLACKHOLE存储引擎
# DWITH_PARTITION_STORAGE_ENGINE=1      表示开启PARTITION存储引擎
# DWITH_FEDERATED_STORAGE_ENGINE=1      表示开启FEDERATED存储引擎
# CMAKE_INSTALL_PREFIX=                 这个表示BASEDIR路径,默认是/usr/local/mysql,是各种配置的路径前缀PREFIX
# DMYSQL_DATADIR:                      这个表示表示MySQL默认的数据目录,选择build文件夹下的data文件
# 其他详细参数参考官网 https://dev.mysql.com/doc/refman/8.4/en/source-configuration-options.html
# Cmake构建参数,主要分为几类:
# 1. 通用参数:
# 2. 安装布局参数:
# 3. 存储参数:
# 4. 特性参数:

# 根据 Makefile 中的规则进行实际的编译过程,生成可执行文件或库。
make -j4

# 负责将最终编译好的文件复制到指定的安装目录中,以供系统中的其他程序使用。
make install

# 也可以使用make package来生成安装包(就像二进制包一样)


# 接着make install成功后,配置一个简单的常规配置文件/etc/my.cnf,就可以初始化数据库并启动数据库了。



/usr/local/mysql/bin/mysqld  --initialize-insecure

mysqld_safe --user=mysql &


# 启动完数据库后,登录数据库可以发现现在已经是debug模式了。
/usr/local/mysql/bin/mysql -u root -p
mysql> select version();
+--------------+
| version()    |
+--------------+
| 8.0.39-debug |
+--------------+
1 row in set (0.00 sec)

mysql>

修改MySQL版本

/include/mysql_version.h这是一个C语言的头文件,是在编译的过程中生成的,通过cmake和make之后就会生成。源代码目录中实际并不存在这个文件。

源代码实际上只有/include/mysql_version.h.in ,这种.h.in是一个模板文件,它是在cmake或者automake的过程中产生的一个用于输入设置信息等功能的中间文件。它会在你调用confing、automake等.sh文件之后,自动生成一个相应的.h文件,然后就可以在源码中调用。

# Bug #31466846 RENAME THE VERSION FILE TO MYSQL_VERSION

version  C++11 的一个头文件,但 MySQL 以往都是在源代码中用 VERSION 这个文件来表示版本号,在引入文件时又因 macOS 不区分文件大小写,产生了冲突,导致编译时报错中断。所以后面改成了MYSQL_VERSION
  • ./mysql-8.0.39/include/mysql_version.h.in 源代码中的模版文件,这个文件没有硬编码,只是定义了一系列宏
  • ./mysql-8.0.39/MYSQL_VERSION 版本文件,定义了版本号:MYSQL_VERSION_MAJOR.MYSQL_VERSION_MINOR.MYSQL_VERSION_PATCH
  • ./mysql-8.0.39/build/include/mysql_version.h make之后生成的版本文件
  • ./mysql-8.0.39/cmake/mysql_server.cmake 版本构建脚本

https://dev.mysql.com/doc/dev/mysql-server/8.0.40/mysql__version_8h_source.html

https://cloud.tencent.com/developer/article/2223495

#define PROTOCOL_VERSION            10
#define MYSQL_SERVER_VERSION       "8.0.39"
#define MYSQL_BASE_VERSION         "mysqld-8.0"
#define MYSQL_SERVER_SUFFIX_DEF    ""
#define MYSQL_VERSION_ID            80039
#define MYSQL_VERSION_STABILITY     "LTS"
#define MYSQL_PORT                  3306
#define MYSQL_ADMIN_PORT            33062
#define MYSQL_PORT_DEFAULT          0
#define MYSQL_UNIX_ADDR            "/tmp/mysql.sock"
#define MYSQL_CONFIG_NAME          "my"
#define MYSQL_PERSIST_CONFIG_NAME  "mysqld-auto"
#define MYSQL_COMPILATION_COMMENT  "Source distribution"
#define MYSQL_COMPILATION_COMMENT_SERVER  "Source distribution"
#define LIBMYSQL_VERSION           "8.0.39"
#define LIBMYSQL_VERSION_ID         80039

VSCODE REMOTE-SSH 工作原理

从官方介绍文档中的这张原理图我们可以看到,用户本地的VS Code是通过SSH通道连接到远程主机的。用户的开发代码、运行环境、调试环境都是在远程主机上。

远程连接是基于Visual Studio Code Remote - SSH这个扩展来实现的。

当用户进行远程连接时,VS Code会在远程主机上安装一个 server 包,这个安装过程是在首次连接时自动完成的。由于 Server 包是安装和运行在远端服务器上,而本地的 VS Code 只是编辑和展示的窗口,两者之间通过SSH Tunnel通信,因此实际的工作环境完全是在远端,如果需要使用第三方的扩展,也可以直接安装在远端服务器环境。

1、具体的连接过程如下:

首次连接时,下载VS Code ServerVS Code Server包的版本取决于你本地使用的VS Code的版本,下载地址为:

x86: https://update.code.visualstudio.com/commit:${commit_id}/server-linux-x64/stable
arm: https://update.code.visualstudio.com/commit:${commit_id}/server-linux-arm64/stable

其中commit_id是变化的,每个不同版本的VS Codecommit_id都不同,可以在VS Code的 Help -> About 中查看

[client]
port    = 3306
socket = /usr/local/mysql/mysql.sock

[mysql]
prompt="\u@\h \R:\m:\s [\d]> "
no-auto-rehash

[mysqld]
user    = root
port    = 3306
admin_address = 127.0.0.1
basedir = /usr/local/mysql
datadir = /data/mysql_data/
socket    = /usr/local/mysql/mysql.sock
pid-file = /usr/local/mysql/mysqld.pid
character-set-server = utf8mb4