思考mysql内核之初级系列10mysql内核调试方法.docx
《思考mysql内核之初级系列10mysql内核调试方法.docx》由会员分享,可在线阅读,更多相关《思考mysql内核之初级系列10mysql内核调试方法.docx(13页珍藏版)》请在冰点文库上搜索。
思考mysql内核之初级系列10mysql内核调试方法
在前面三篇,bingxi和alex聊了关于innodb的hash、list、以及动态数组的实现方法,这三个结构比较常用。
讲完前9篇内容,本篇会描述在windows环境下debugmysql的方法,强烈建议通过debug的方式进行学习。
在本篇里,bingxi和alex会聊到windows下常用的调试mysql代码的方法,仅供参考。
1)在windows和linux下调试的异同?
Bingxi:
“alex,咱们看myslq代码的方法,是通过windows看好呢,还是linux/unix下看呢,两者之间最大的差异是什么?
”
Alex:
“在mysql5.1的高版本开始,windows环境与linux环境使用同一套代码。
我电脑里面正好有两个版本的代码,我们看下mysql-6.0.4-alpha目录下的INSTALL-WIN-SOURCE文件,其中有这么一段:
TobuildMySQLonWindowsfromsource,youmustsatisfythe
followingsystem,compiler,andresourcerequirements:
*Windows2000,WindowsXP,ornewerversion.WindowsVistais
notsupporteduntilMicrosoftcertifiesVisualStudio2005on
Vista.
*CMake,whichcanbedownloadedfromhttp:
//www.cmake.org.
Afterinstalling,modifyyourpathtoincludethecmake
binary.
*MicrosoftVisualC++2005ExpressEdition,VisualStudio.Net
2003(7.1),orVisualStudio2005(8.0)compilersystem.
*IfyouareusingVisualC++2005ExpressEdition,youmust
alsoinstallanappropriatePlatformSDK.Moreinformationand
linkstodownloadsforvariousWindowsplatformsisavailable
from
*IfyouarecompilingfromaBitKeepertreeormakingchanges
totheparser,youneedbisonforWindows,whichcanbe
downloadedfrom
thepackagelabeled"Completepackage,excludingsources".
Afterinstallingthepackage,modifyyourpathtoincludethe
bisonbinaryandensurethatthisbinaryisaccessiblefrom
VisualStudio.
*Cygwinmightbenecessaryifyouwanttorunthetestscript
orpackagethecompiledbinariesandsupportfilesintoaZip
archive.(Cygwinisneededonlytotestorpackagethe
distribution,nottobuildit.)Cygwinisavailablefrom
.
*3GBto5GBofdiskspace.
可以通过这样的方式来生成一份代码,然后用vs2005或者更高版本来调试。
”
Bingxi:
“alex,你电脑里面的另外一个软件包是mysql-5.1.7的吧。
”
Alex:
“嗯,这个版本是mysql5.1.7代码刚出来的时候进行下载的。
这个版本的代码直接解压缩之后,可以直接用vs2003进行编译调试。
对innodb而言,用这个版本的就可以了,innodb的变化不大,如果需要理解查询引擎,则需要使用更新的版本进行学习。
”
Bingxi:
“mysql-5.1.7-beta-win-src.zip,这个软件包的内容,我们学了之后,会不会和linux下不一样,有人会有这样的疑问,毕竟在很多公司里面,mysql是运行在linux/unix环境的。
我们知道windows与linux/unix的差异还是存在的,尤其是底层的系统函数。
”
Alex:
“嗯,这个是很多人的疑问。
其实mysql进行了代码的封装,比如在5.1.7的windows版本的代码中,也是可以看到系统函数的封装。
比如eventsemaphore。
看下对应的代码:
/*************************************************************
Createsaneventsemaphore,i.e.,asemaphorewhichmayjusthavetwo
states:
signaledandnonsignaled.Thecreatedeventismanualreset:
it
mustberesetexplicitlybycallingsync_os_reset_event.*/
os_event_t
os_event_create(
/*============*/
/*out:
theeventhandle*/
constchar*name)/*in:
thenameoftheevent,ifNULL
theeventiscreatedwithoutaname*/
{
#ifdef__WIN__
os_event_tevent;
event=ut_malloc(sizeof(structos_event_struct));
event->handle=CreateEvent(NULL,/*Nosecurityattributes*/
TRUE,/*Manualreset*/
FALSE,/*Initialstatenonsignaled*/
(LPCTSTR)name);
if(!
event->handle){
fprintf(stderr,
"InnoDB:
CouldnotcreateaWindowseventsemaphore;Windowserror%lu\n",
(ulong)GetLastError());
}
#else/*Unix*/
os_event_tevent;
UT_NOT_USED(name);
event=ut_malloc(sizeof(structos_event_struct));
os_fast_mutex_init(&(event->os_mutex));
#ifdefined(UNIV_HOTBACKUP)&&defined(UNIV_HPUX10)
ut_a(0==pthread_cond_init(&(event->cond_var),
pthread_condattr_default));
#else
ut_a(0==pthread_cond_init(&(event->cond_var),NULL));
#endif
event->is_set=FALSE;
event->signal_count=0;
#endif/*__WIN__*/
/*Puttothelistofevents*/
os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list,os_event_list,event);
os_event_count++;
os_mutex_exit(os_sync_mutex);
return(event);
}
在os_event_create函数体,屏蔽了系统的差异性。
开发人员在开发时,需要创建event,只需要os_event_create就行了。
”
Bingxi:
“alex,那么按照这个思路,是不是可以获得两个信息:
1)如果需要debug系统封装函数,还是建议在linux/unix下也调试下,2)对我们查看非系统函数,在windows与linux/unix下调试,两者都是可以的。
”
Alex:
“嗯,用哪种调试方法都是可以的。
用哪个版本的也是可以的,本系列以描述innodb存储为主,因此使用5.1.7就可以了。
”
2)搭建windows环境下的mysql5.1.7的调试环境
Bingxi:
“好吧,那我们就开始搭建环境吧。
”
Alex:
“ok,我们先将代码找一个目录进行解压缩,本文中的解压缩位置为d:
\。
使用vs2003打开D:
\bin-mysql-5.1.7-beta\mysql.sln项目文件。
Bingxi,打开之后会有46个project,我们要编译其中哪些工具呢?
”
Bingxi:
“ok,至少要包含下面三个内容:
1)服务端程序,2)客户端程序,3)mysqladmin工具(用于退出调试时使用,直接使用中断调试太暴力了)。
顺着这个思路,我们一步步来编译。
首先编译服务端程序,也就是编译mysqld项目。
这里有三个建议,1)因为本系列主要调试mysqld的代码,因此需要将mysqld设置为启动项目,2)设置启动方式为console方法,这样可以在console窗口中看到打印信息,3)将D:
\bin-mysql-5.1.7-beta下的data文件夹进行压缩保存,这样,我们需要恢复到原始的数据,直接用保存的data进行覆盖就可以了。
设置为启动项目:
设置为console启动方式:
根据个人习惯,决定是否将data进行压缩保存。
接着,我们编译mysqld项目、mysql项目、mysqladmin项目。
编译产生的工具在D:
\mysql-5.1.7-beta\client_debug目录。
设置断点,比如查询的总入口是handle_select函数(在sql_select.cpp文件中)。
使用“进入单步执行新实例”进行调试。
如图:
执行时,停止在main函数开始处(可以一步步看看mysql是如何启动的),我们按F5,程序会直接执行,如果断点被执行,那么就会停在断点处,因为我们此处设置的是查询函数,所以没有被执行。
因此,我们需要通过客户端执行一条语句,来触发断点对应的代码被执行。
执行showdatabases命令之后,我们可以看到断点生效了。
这样我们通过F10\F11\F5\shift+F11等常用的快捷键进行调试了。
如果需要退出调试状态,则使用mysqladmin,如图(图中打印的一行错误信息不用理它,是系统的一个bug):
”
3)调试的技巧
Alex:
“bingxi,这个我理解了,有没有一些常用的技巧。
Alex常用的是通过快速监控,见下面的两图。
这样,我们可以看到变量的值。
但是,遇到想测试函数,或者看宏的值就有点麻烦了。
Bingxi,你给我讲讲。
”
Bingxi:
“最常用的方法是直接分析算法,如果有些确实不太明白,可以通过自己写测试函数的方法进行调试。
如果我想知道某一页属于哪个簇描述符,可以在fsp0fsp.c的文件尾加上我们自己的测试函数,同时设置断点:
接着在该文件的文件头(添加内容为红色选中处),声明定义:
接着找一个函数,进行调用函数test_bingxi,这里我们选择fsp_get_space_header函数,因为这个函数在同一个文件,并且启动的时候会被执行。
添加调用,添加内容为红色选中处。
然后,我们启动调试,按F5进入断点。
通过j值就可以知道UNIV_PAGE_SIZE的值,如果是多个宏计算后的值,也是一样的方法。
通过i1值就可以知道xdes_calc_descriptor_page(0)的返回值。
类似这样的方法,我们可以通过添加测试代码,将疑问的地方进行测试。
今天调试的就说到这儿吧。
”
Alex:
“ok,说完调试,开始正式进入innodb存储了。
咱们也是初学者,需要多debug来解惑。
今天不说晚安了,马上6点了,早安。
”
Bingxi:
“早安。
”