今天很开心终于搞定了MYSQL调试了,像开发程序一样,边写边运行,跟SHELL脚本那么方便了。
以前看大佬在LInux系统上使用源码编译,然后使用GDB,再用VIM+CSDOPE定位,跳转。实在不太方便!
如何在LINUX下源码编译MYSQL 8,请看我写的。
使用VSCODE 看了姜前辈的也不知所措,感觉跳跃比较大,好像很简单样
用VSCode 编译和调试MySQL,每个DBA 都应 get的小技能
https://mp.weixin.qq.com/s/RO_Ipa9_SH8_DuVholrgvg
VScode,yyds!用VScode编译和调试MySQL
https://mp.weixin.qq.com/s/Q-hFTDzoTW5cFk3foW7BAw
对VSCODE 摸索了下 写了篇
大家最好是在一台干净的虚拟机上安装,也就是没有其他的MYSQL实例在运行,强占了/etc/my.cnf位置。否则会出现很多问题,不知道为啥的问题!
当然根据MYSQL 源码DEBUG编译 预先安装好了GCC5.5,CMAKE,MYSQLD预先包RPM,GDB。VIM和CSCOPE就不必了。然后MYSQLD能成功运行起来.
根据这篇 VSCODE 从相恋到分手 你安装好了对应的插件。VSCODE插件很多时候需要访问外网,有时候非常慢。
以上是前提条件!
以下VSCODE插件,安装在LINUX服务器上

创建CMAKE配置文件
链接到LINUX系统MYSQL8源码目录,看我这里是直接在当层目录

创建c_cpp_properties.json 文件
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/local/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
gcc5.5 一般安装在/usr/local/bin/gcc;
includePath 是头文件路径,workspaceFolder工作空间目录就是链接远程的目录
Settings.json 类似CMAKE编译配置
相对以前少了D开头
cmake .. \
-DWITH_BOOST=/u01/mysql8/source/boost/ \
-DWITH_DEBUG=ON \
-DWITH_SSL=bundled \
-DWITH_INNODB_MEMCACHED=ON \
-DWITH_ZLIB=system \
-DDEFAULT_CHARSET=utf8mb4 \
-DCMAKE_INSTALL_PREFIX=/u01/mysql8/soft \
-DMYSQL_DATADIR=/u01/mysql8/data \
-DWITHOUT_CSV_STORAGE_ENGINE=1 \
-DWITHOUT_BLACKHOLD_STORAGE_ENGINE=1 \
-DWITHOUT_FEDERATED_STORAGE_ENGINE=1 \
-DWITHOUT_ARCHIVE_STORAGE_ENGINE=1 \
-DWITHOUT_MRG_MYISAM_STORAGE_ENGINE=1 \
-DWITHOUT_NDBCLUSTER_STORAGE_ENGINE=1 \
-DFORCE_INSOURCE_BUILD=1 \
-DCMAKE_CXX_COMPILER=/usr/local/bin/g++ \
-DCMAKE_C_COMPILER=/usr/local/bin/gcc
{
"cmake.buildBeforeRun": true,
"cmake.buildDirectory": "/home/source_code/mysql_8_buildr",
"cmake.configureSettings": {
"WITH_DEBUG": "1",
"CMAKE_INSTALL_PREFIX": "home/source_code/mysql_8_buildr",
"MYSQL_DATADIR": "home/source_code/mysql_8_buildr/data",
"SYSCONFDIR": "home/source_code/mysql_8_buildr/etc",
"MYSQL_TCP_PORT": "3309",
"MYSQL_UNIX_ADDR": "home/source_code/mysql_8_buildr/data/mysql-debug.sock",
"DEFAULT_CHARSET": "utf8mb4",
"DEFAULT_COLLATION_FOR_UTF8MB4": "utf8mb4_general_ci",
"WITH_BOOST": "${workspaceFolder}/mysql-8.0.24/boost",
"DOWNLOAD_BOOST": "0"
},
"files.associations": {
"*.ipp": "cpp",
"*.cc" : "cpp"
},
"cmake.parallelJobs": 0,
"cmake.cmakePath": "cmake",
"cmake.sourceDirectory": "${workspaceFolder}/mysql-8.0.24",
}
为了减少麻烦不要SSL和ZLIB 其它的也可以不要!
"CMAKE_INSTALL_PREFIX": "home/source_code/mysql_8_buildr",
"MYSQL_DATADIR": "home/source_code/mysql_8_buildr/data",
"SYSCONFDIR": "home/source_code/mysql_8_buildr/etc",
"MYSQL_TCP_PORT": "3309",
"MYSQL_UNIX_ADDR": "home/source_code/mysql_8_buildr/data/mysql-debug.sock",
这几个参数是因为本仙机器上已经安装了MYSQLD所以端口换成了3309,
另外直接在建造目录下跑数据库,不想在安装到其他目录下。不过大家还是按照编译安装方式安装到别的目录下。
设置好了就保存下
CRTL+SHIFT+P 在顶部显示命令框,输入cmake:配置

然后CMAKE就检查你写的配置文件
也可以通过命令配置 输入SELECT A KIT 选择GCC版本

选择CMAKE 工程文件 CMAKELISTS.TXT 下面的图版本问题无关大雅,是MYSQL8源码根目录下的CMAKELISTS.TXT总工程文件,源码子目下有很多工程文件


遇到问题

解决了后删除重配

全量编译
"cmake.parallelJobs": 0,
这个参数表示 根据机器CPU多少自动配置并发线程,建议改成1.避免卡死!


[build] [100%] Linking CXX executable ../../../../runtime_output_directory/mysqlrouter_keyring
[build] [100%] Built target mysqlrouter_keyring
[build] Build finished with exit code 0
单线程编译比较久主要看SSD和CPU是否给力!
编译FAQ
9.2.1 error:
‘app_data_ptr’ does not name a type
这里有个问题,
MYSQL 源码工程 插件部分 会在输出项目目录下 再生成源码文件,就是XCOM_VP.H
下图所示 XCOM->APP_DATA.H 调用XCOM_VP.H 文件, 该文件时编译产生的源码文件,奇怪吧! 没有生成完整,只有22行
9.2.2 CC1
[build] [ 73%]
Generating xdr_gen/xcom_vp.h, xdr_gen/xcom_vp_xdr.c
[build] cpp:
error trying to exec 'cc1': execvp: No such file or directory
[build]
/usr/bin/rpcgen: C preprocessor failed with exit code 1
[build] cpp:
error trying to exec 'cc1': execvp: No such file or directory
这个需要重新编译安装GCC
5.5
9.2.3 CXXABI_1.3.9
/runtime_output_directory/uca9dump:
/lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found
strings
/home/source_code/gcc5/gcc-5.5.0/build/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
| grep CXXABI
把它复制过去 然后创建软链接
调试MYSQLD
添加调试文件

launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "/home/source_code/mysql_8_buildr/bin/mysqld",
"args": ["--defaults-file=/home/source_code/mysql_8_buildr/etc/my.cnf"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
"program":"${workspaceRoot}/myexe", //执行这个文件,相当于命令行中输入这行
"args":["param1","param2","2>&1",">","out"], //program的参数,相当于命令行中在program后输入用空格隔开的这些参数。我这里前两个是执行文件自带的参数设置,后三个是将标准输出和标准错误输入到文件out中。
"stopAtEntry":false, //大概是表示是否在main函数处停下,类似在main上打断点。
"cwd":"${workspaceRoot]", //表示在哪个目录下执行program,相当于命令行中输入cd 该行
启动调试程序
注意这里调试程序会启动MYSQLD服务器
启动调试,launch.json 文件配置完成之后,运行和调试
下拉框就能看到刚刚添加的配置,点击 (gdb) 启动
前面的小三角
,启动 MySQL,然后就可以开始调试了。

这样我们的MYSQL8版本成功启动了!
[root@localhost etc]# ps -ef | grep mysql
root 16509 16454 3 10:01 ? 00:00:02 /home/source_code/mysql_8_buildr/bin/mysqld --defaults-file=/home/source_code/mysql_8_buildr/etc/my.cnf
root 16675 6658 0 10:02 pts/22 00:00:00 grep --color mysql
root 27139 1 0 Feb20 ? 01:03:35 /usr/sbin/mysqld
设置断点
在 MySQL 源码中打个断点,先打开 sql/sql_parse.cc
文件:

开始调试
先暂时取消断点,启动MYSQL 客户端

再开启断点,然后在客户端输入SQL命令,输入完后就卡在那了

这时候VSCODE 断点被捕获

单步下去后我们看到边上的变量

通过选择,右键菜单,添加到监视器,我们看到这个SQL类型是SELECT

继续执行下去 这个ALL_TABLES变量 从语法解析获得数据,它是个结构体,在左边可以展开。
注意黄色的方块箭头,它指向的是将要执行的行代码,它上一行是执行过的。

增量编译
稍微改写下2038的限制
Sql_parse.cc
if (thd->killed == THD::KILL_QUERY) thd->killed = THD::NOT_KILLED;
thd->set_time();
if (is_time_t_valid_for_timestamp(thd->query_start_in_secs()) == false) {
CTRL+鼠标 点击 is_time_t_valid_for_timestamp 进行跳转
my_time.h
inline bool is_time_t_valid_for_timestamp(time_t x) {
return x <= TIMESTAMP_MAX_VALUE && x >= TIMESTAMP_MIN_VALUE;
}
把2038 和int32_t 改成4096 int64_t
/** Time handling defaults */
constexpr const int TIMESTAMP_MAX_YEAR = 2038;
/** Two-digit years < this are 20XX; >= this are 19XX */
constexpr const int YY_PART_YEAR = 70;
constexpr const int TIMESTAMP_MIN_YEAR = (1900 + YY_PART_YEAR - 1);
constexpr const int TIMESTAMP_MAX_VALUE = std::numeric_limits<std::int64_t>::max();
constexpr const int TIMESTAMP_MIN_VALUE = 1;
这个文件被#include <my_time.h> 很多地方,先看能否单独编译
CRTL+SHIFT+P
输入Cmake:B 然后选择生成目标

我们只生成MYSQLD 就行

这里选择建造的目录,然后手工复制到安装目录下
编译报错

改错 const int 改成const long 在linx 64下 long类型是64位,win下是32位
/** Time handling defaults */
constexpr const int TIMESTAMP_MAX_YEAR = 4096;
/** Two-digit years < this are 20XX; >= this are 19XX */
constexpr const int YY_PART_YEAR = 70;
constexpr const int TIMESTAMP_MIN_YEAR = (1900 + YY_PART_YEAR - 1);
constexpr const long TIMESTAMP_MAX_VALUE = std::numeric_limits<std::int64_t>::max();
constexpr const int TIMESTAMP_MIN_VALUE = 1;
编译成功

修改系统时间 提前进入2039年,原来PERCONA 8的数据库实例自动挂掉
[root@localhost etc]# date -s 20390308
Tue Mar 8 00:00:00 WIB 2039
[root@localhost etc]# hwclock
Wed 08 Mar 2023 02:10:27 PM WIB -0.452625 seconds
[root@localhost etc]# hwclock -w
[root@localhost etc]# hwclock
Tue 08 Mar 2039 12:00:58 AM WIB -0.822792 seconds
显示原来的SQLE数据库挂了
[root@localhost etc]# ps -ef | grep mysqld
我们的成功启动
[root@localhost etc]# clear
[root@localhost etc]# service mysql8debug start
Starting MySQL [ OK ]

测试效果

后言 KVM 虚拟机需要4G的内存,周四和周五 遇到了编译安装的时候说G++错误,然后就退出,错误信息很模糊,我以为自己的VBOX里安装的GCC CMAKE坏了.我以为删除了GCC和CMAKE 目录导致的,然后重新安装GCC,GCC编译需要1个多小时,.然后编译安装,已经用VSCODE编译过, 只是安装,可发现在VSCODE还是XSHELL里面都要再编译一次. 尤其是编译到52%,或者62%的时候才报. 浪费大把时间才能验证还会不会报错!





