共计 3607 个字符,预计需要花费 10 分钟才能阅读完成。
一:背景
1. 讲故事
上一篇说了 mysql 的架构图,很多同学反馈说不过瘾,毕竟还是听我讲故事,那这篇就来说一说怎么利用 visual studio 对 mysql 进行源码级调试,毕竟源码面前,不谈隐私,圣人面前,皆为蝼蚁。
二:工具合集
mysql 是 C ++ 写的,要想在 windows 上编译,还需要下载几个必备小工具。
- mysql-5.7.12.zip
- cmake-3.17.3-win64-x64.msi
- boost_1_59_0.tar.gz
- bison-2.4.1-setup.exe
- windows 10 x64
这里简单说一下:可以用cmake
将源码生成 *.sln
可打开的解决方案,比如可以通过它最终生成 MySQL.sln
。boost
是 C ++ 中非常强大的基础库,bison
一个流行的语法分析器程序,用于给 mysql 提供语法分析,最后就是下载正确的 mysql 版本 5.7.12
。
三. 详细安装
我会写的比较细,毕竟我也花了一下午时间,寒酸(┬_┬)
1. cmake-3.17.3-win64-x64.msi 和 bison-2.4.1-setup.exe
cmake 和 bison 安装起来比较方便,一键安装就可以了,不过这里有一个大坑注意了,在安装 Bison
的时候,千万不要使用默认路径,因为默认路径有空格,会导致你后面 vs 编译的时候卡住,又不显示什么原因, 可气!!!所以我换成自定义的:C:\2\GnuWin32
。
最后确保 cmake
和 bison
的 bin 文件都在 环境变量中即可。
2. mysql-5.7.12.zip
这里我用 C:\2
作为根文件夹,所有的小工具都在这里,如图:
接下来将 mysql-5.7.12.zip
解压一下,然后进入解压后的文件夹,新建一个 boost 文件夹,将 boost_1_59_0.tar.gz
放入其中,然后再新建一个 brelease
文件夹可用于存放最终生成的MySql.sln
。???。
3. cmake 编译
都准备好了之后,可以开始 cmake 编译了。
PS C:\2\mysql-5.7.12\brelease> cmake .. -DDOWNLOAD_BOOST=1 -DWITH_BOOST="C:\2\mysql-5.7.12\boost\boost_1_59_0.tar.gz" | |
-- Building for: Visual Studio 16 2019 | |
CMake Deprecation Warning at CMakeLists.txt:26 (CMAKE_POLICY): | |
The OLD behavior for policy CMP0018 will be removed from a future version | |
of CMake. | |
-- Cannot find wix 3, installer project will not be generated | |
-- COMPILE_DEFINITIONS: _WIN32_WINNT=0x0601;WIN32_LEAN_AND_MEAN;NOGDI;NOMINMAX;HAVE_CONFIG_H | |
-- CMAKE_C_FLAGS: /DWIN32 /D_WINDOWS /W3 /MP /wd4800 /wd4805 /wd4996 | |
-- CMAKE_CXX_FLAGS: /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP /wd4800 /wd4805 /wd4996 /we4099 | |
-- CMAKE_C_FLAGS_DEBUG: /MTd /Z7 /Ob1 /Od /RTC1 /EHsc -DENABLED_DEBUG_SYNC -DSAFE_MUTEX | |
-- CMAKE_CXX_FLAGS_DEBUG: /MTd /Z7 /Ob1 /Od /RTC1 /EHsc -DENABLED_DEBUG_SYNC -DSAFE_MUTEX | |
-- CMAKE_C_FLAGS_RELWITHDEBINFO: /MT /Z7 /O2 /Ob1 /DNDEBUG /EHsc -DDBUG_OFF | |
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO: /MT /Z7 /O2 /Ob1 /DNDEBUG /EHsc -DDBUG_OFF | |
-- Configuring done | |
-- Generating done | |
-- Build files have been written to: C:/2/mysql-5.7.12/brelease |
当看到最后一句 Build files have been written to: C:/2/mysql-5.7.12/brelease
,恭喜你,MySQL.sln
生成好了。
4. 打开 MySQL.sln 编译项目
我的电脑安装的是 visual studio 2019
,接下来打开MySql.Sln
整体编译,需要等个十几分钟,看到下面的输出就算安装成功。
三:启动 mysql 并调试 insert
1. mysql 的初始化
这里要做两件事情,第一件事是将 mysql 的调试模式打开,第二件事就是附加 --initialize
启动参数。
<1> mysql 调试模式打开
修改 C:\2\mysql-5.7.12\sql\mysqld.cc
中的 test_lc_time_sz
方法中的 DBUG_ASSERT(0);
改成 DBUG_ASSERT(1);
如下图:
<2> vs 的 command 增加启动参数
上一篇大家都知道了,mysqld 项目是 mysql 的启动项目,main 函数也在其中,在 F5 调试之前增加初始化参数 --console --initialize
,如下图:
2. 继续入坑出坑
启动之后,有 103 个报错,气人呀。。。看错误信息应该是编码问题,如下图:
修改起来也很简单,将 C:\2\mysql-5.7.12\sqlsql_locale.cc
用 [utf-8 + BOM] 格式保存一下,然后对 mysqld
项目 Rebuild 再 Ctrl+F5
直接运行,终于谢天谢地,从输出可以看到,搞定啦。。。太不容易啦。
从上图中可以看到,默认密码是:zJDE>IC5o+ya
,先记录下这个密码,然后再把 CommandLine Arguments 中的 –initialize 去掉再重启 Console。
可以看到,3306 端口已开启,然后用刚才的 zJDE>IC5o+ya
连接即可,这里我使用 navicat。
连接上去后会提示修改默认密码,设置我就设置为:123456
,?? 嘿嘿,一切搞定~~~
3. 继续追踪 write_row
上一篇我们追踪到了 write_row
就断掉了,我当时说它是一个虚方法,由底层具体的存储引擎去调用,代码如下:
int handler::ha_write_row(uchar *buf) | |
{MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,{ error= write_row(buf); }) | |
} | |
// 这是一个虚方法 | |
virtual int write_row(uchar *buf __attribute__((unused))) | |
{return HA_ERR_WRONG_COMMAND;} |
到底这话虚不虚,这次我亲自调试一下给大家看看,证据先行哈。。。为了方便,我生成一条创表 sql。
drop database if exists `datamip`; | |
create database `datamip`; | |
drop table if exists `datamip`.`customer`; | |
create table `datamip`.`customer` ( | |
`customerID` int NOT NULL AUTO_INCREMENT COMMENT '自增主键', | |
`customerName` varchar(50) COMMENT '用户姓名', | |
`email` varchar(50) COMMENT '邮箱地址', | |
`desc` varchar(50) COMMENT '描述', | |
primary key (`customerID`) | |
) ENGINE=InnoDB charset=utf8 collate=utf8_bin; |
接下来,大家看仔细了,在源码 int handler::ha_write_row(uchar *buf)
方法处下一个断点,然后 F5 调试应用程序。
接下来可以执行 insert 操作,这地方会命中断点的。
insert into `datamip`.`customer`(customerName,email,`desc`) values('mary','123456789@qq.com','vip'); |
可以看到,断点命中了,然后进行单步调试,最终你会看到代码会进入到 C:\2\mysql-5.7.12\storage\innobase\handler\ha_innodb.cc
中的 int ha_innobase::write_row
方法,如下图:
然后找几个局部变量和调用堆栈看看。。。
四:总结
这就是我花了一下午的时间总结出的进坑出坑指南,希望能帮助大家节省时间,还是那句话,源码面前,不谈隐私,若还能进行调试,那一切皆为蝼蚁!