17

MySql轻松入门系列——第二站 使用visual studio 对mysql进行源码级调试

 4 years ago
source link: https://segmentfault.com/a/1190000022891162
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一:背景

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.slnboost 是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

jAzEr2u.png!web

最后确保 cmakebison 的bin文件都在 环境变量中即可。

nUFfU3n.png!web

2. mysql-5.7.12.zip

这里我用 C:\2 作为根文件夹,所有的小工具都在这里,如图:

Qr6fIna.png!web

接下来将 mysql-5.7.12.zip 解压一下,然后进入解压后的文件夹,新建一个boost文件夹,将 boost_1_59_0.tar.gz 放入其中,然后再新建一个 brelease 文件夹可用于存放最终生成的 MySql.sln 。:smile::smile::smile:。

m6beE3Q.png!web

fiIBjy2.png!web

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 生成好了。

QZR3ea3.png!web

4. 打开 MySQL.sln 编译项目

我的电脑安装的是 visual studio 2019 ,接下来打开 MySql.Sln 整体编译,需要等个十几分钟,看到下面的输出就算安装成功。

bmEJfqJ.png!web

三: 启动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); 如下图:

ZZ3eA3B.png!web

<2> vs的command增加启动参数

上一篇大家都知道了,mysqld项目是mysql的启动项目,main函数也在其中,在F5调试之前增加初始化参数 --console --initialize ,如下图:

AbEJreq.png!web

2. 继续入坑出坑

启动之后,有103个报错,气人呀。。。看错误信息应该是编码问题,如下图:

jyEbiiY.png!web

修改起来也很简单,将 C:\2\mysql-5.7.12\sqlsql_locale.cc 用 [utf-8 + BOM] 格式保存一下,然后对 mysqld 项目Rebuild再 Ctrl+F5 直接运行,终于谢天谢地,从输出可以看到,搞定啦。。。太不容易啦。

uui2QjR.png!web

从上图中可以看到,默认密码是: zJDE>IC5o+ya ,先记录下这个密码,然后再把CommandLine Arguments 中的--initialize去掉再重启Console。

JFRfYry.png!web

可以看到,3306端口已开启,然后用刚才的 zJDE>IC5o+ya 连接即可,这里我使用navicat。

ma6NvmF.png!web

连接上去后会提示修改默认密码,设置我就设置为: 123456 ,:grin::grin:嘿嘿,一切搞定~~~

EfEZnai.png!web

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调试应用程序。

a6JBBbQ.png!web

接下来可以执行insert操作,这地方会命中断点的。

insert into  `datamip`.`customer`(customerName,email,`desc`) values('mary','[email protected]','vip');

vyAZrar.png!web

可以看到,断点命中了,然后进行单步调试,最终你会看到代码会进入到 C:\2\mysql-5.7.12\storage\innobase\handler\ha_innodb.cc 中的 int ha_innobase::write_row 方法,如下图:

2Mze2yy.png!web

然后找几个局部变量和调用堆栈看看。。。

JRRJvee.png!web

3EzMBjE.png!web

四: 总结

这就是我花了一下午的时间总结出的进坑出坑指南,希望能帮助大家节省时间,还是那句话,源码面前,不谈隐私,若还能进行调试,那一切皆为蝼蚁!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK