一:背景
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
方法,如下圖:
然後找幾個區域性變數和呼叫堆疊看看。。。
四: 總結
這就是我花了一下午的時間總結出的進坑出坑指南,希望能幫助大家節省時間,還是那句話,原始碼面前,不談隱私,若還能進行除錯,那一切皆為螻蟻!