Mysql源代码分析系列(1): 编译和调试
拖了很久了Mysqld源代码分析从今天开始吧,随着我阅读的进度推进,我会写一些文章记录自己的心得,但是不保证一定会写。其实也不保证一定有时间来完整的阅读所有的代码。阅读代码的目的有如下几点:
- 通过了解Mysql的架构,学习大型系统软件的体系结构,希望自己在工作的时候也能应用到其中的一些技术
- 通过阅读代码,能够更好的理解Mysql的使用,也能做更深入的应用,比如性能调优,加入自己需要的功能和模块,等等
至于写文章,还是一件比较费脑力和时间的事情,虽然把想法写下来有助于更好的掌握学到的东西,尽量吧,而且我的文笔比较差。
这是第一篇,从编译和调试Mysql开始,不急于进入代码阅读阶段。
相关资源:
从这个地方下载源代码和使用文档。
- http://forge.mysql.com/wiki/MySQL_Internals
这里有一系列文章介绍Mysql的内部原理,是非常好的代码理解参考资源,强烈推荐有兴趣的人仔细阅读。除了代码本身,这也是是最权威的资料。
- http://www.amazon.com/Understanding-MySQL-Internals-Sasha-Pachev/dp/0596009577
这好像是我知道的唯一介绍Mysql工作原理的书,可以看看,也不是很厚。Google一下这本书,很多地方都有下载,不过都是E文,大家讲究着看吧,谁叫这是老外做出来的呢。
下载代码:
- http://dev.mysql.com/downloads/
需要注册,下载最新的5.1版本或者更高。
Bazaar是Mysql使用的源代码管理工具,类似于CVS,俺也没用过,有兴趣的自己看文档吧:
- A Contributor's Guide to Launchpad - Part 1 - Getting Started
- A Contributor's Guide to Launchpad - Part 2 - Code Management
编译代码:
Mysql的代码编译是通过一些shell脚本来完成的。下载代码并解压后,有一个
BUILD目录,进去看看,里面有各种平台使用的编译脚本,我们要用的是debug版本,以方便我们使用gdb,所以使用的脚本是BUILD/compile-pentium-debug。打开看看,其实很简单,主要加了一个configure选项”--with-debug=full",并使用了debug_cflags 和debug_configs。脚本内容如下:
BUILD/compile-pentium-debug
#! /bin/sh
path=`dirname $0` #找到文件所在目录
set -- "$@" --with-debug=full #将命令行加上"--with-debug=full"
. "$path/SETUP.sh" # 导入SETUP.sh的内容,设置一些变量
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs"
. "$path/FINISH.sh" # 进行config和编译
"--with-debug"实际上是autoconf脚本里面定义的,打开
configure.in, 查找"with-debug",可以看看里面的参数有哪些不同。
执行脚本吧: $
BUILD/
compile-pentium-debug --prefix=$HOME/mysql-bin
这里我们执行目标安装目录是$HOME/mysql-bin,你也可以指定其他目录,尽量不要用默认目录,不然有可能和系统里面已经安装好的mysql文件冲突。
根据机器快慢,花的时间也不同,我用的机器花了不到10分钟。等待编译完毕,在
sql目录下面可以看到
sql/mysqld,恭喜你:-) 这就是mysql的服务器执行文件。
写到这里,我倒是很想就mysql的编译系统写点东西,呵呵,还是有很多比较有意思的地方的。
安装和运行:
安装: $
make && make install
一大堆信息之后你应该可以在~/mysql-bin下面找到很多文件了
$
ls /home/liuli/mysql-bin/
bin include info lib libexec man mysql-test share sql-bench
比较重要的目录:
* bin: 客户端程序和脚本,可以发现比较眼熟的mysql, mysqld_safe, mysqldump, mysqladmin等
* libexec: 服务器程序,包括mysqld
* share: 配置文件,包括一些实例配置文件比如my-small.cnf以及初次安装运行需要的初始数据库文件比如mysql_system_tables.sql。
Mysql能够运行还需要一些配置文件和数据文件,执行这个命令:
$
~/mysql-bin/bin/mysql_install_db --defaults-file=my.cnf --basedir=~/mysql-bin --datadir=~/mysql-bin/var
该命令将运行Mysqld的bootstrap过程,主要是安装Mysql的系统表,内容可以参照~/mysql-bin/share/mysql目录下的fill_help_tables.sql,mysql_system_tables.sql和mysql_system_tables_data.sql。这里我特别强调"--defaults-file"参数,这个参数是用来指定系统运行需要的"my.cnf"配置文件的。mysql_install_db需要知道系统的配置才能导入上述的三个sql文件,所以必须要制定一个配置文件,我就是把~/mysql-bin/share/mysql下面的"my-small.cnf"做为配置文件,大家也可以选自己对应的配置文件,如果不指定,会从/etc/mysqld/my.cnf导入配置。
注意: -defaults-file=my.cnf 选项必须放在第一个参数的位置,否则无效,而且mysql的大部分程序或者脚本都接受这个参数,但也必须放在第一个参数的位置上。
好了,如果没有错误发生,我们就可以运行mysqld啦!
$
~/mysql-bin/libexec/mysqld --defaults-file=my.cnf --basedir=~/mysql-bin --datadir=~/mysql-bin/var --skip-networking
ps一下,能够看到这个进程了吧。
可以用mysql练一下:
$mysql -S /tmp/mysql.sock
$show databases;
应该可以看到:
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
+--------------------+
2 rows in set (0.00 sec)
安装运行部分到这里就结束罗!下面进入调试环节。
调试:
代码调试:
当然是使用gdb啦,或者DDD也行,看个人喜好,这里用gdb做例子。
$
gdb --args ~/m
ysql-bin/libexec/mysqld --defaults-file=my.cnf --basedir=/home/aaa/mysql-bin --datadir=/home/aaa/mysql-bin/var --skip-networking
$ (gdb) br handle_one_connection
$ c
handle_one_connection顾名思义,是mysqld接到一个连接请求以后的处理函数。
另外上面的basedir和datadir用的都是全路径,否则会报错:Can't change dir to '~/mysql-bin/var/'
然后在另外一个shell里面:
$ mysql -S /tmp/mysql.sock
这时gdb会下来,显示:
Breakpoint 1, handle_one_connection (arg=0x86ede38) at sql_connect.cc:1076
1076 THD *thd= (THD*) arg;
(gdb) bt
#0 handle_one_connection (arg=0x86ede38) at sql_connect.cc:1076
#1 0x4fc133a8 in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#2 0x4fb647fe in clone () from /lib/tls/i686/cmov/libc.so.6
后面就很简单了,大家懂得的gdb奇技淫巧都可以上了,我就不再多说。
如果这里看不到函数名和文件名,那肯定是前面编译的时候没有用debug编译,重新来一遍吧。
性能调试:
很多时候大家对于mysql当前的性能比较感兴趣,想了解哪些函数大量占用CPU,我推荐两个工具,都是不用你重新编译mysqld的:
* sysprof: http://www.daimi.au.dk/~sandmann/sysprof/
* oprofile:http://oprofile.sourceforge.net/news/
Sysprof相对来说比较好用,oprofile功能更强大,用起来也稍微复杂。他们都可以用来显示当前系统上运行程序个部分占用CPU的情况,原理都是通过系统核心态定时的timer,看当前CPU的进程和EIP,还可以通过爬堆栈的方式找到代用堆栈,并打印出来,而且他们都是不仅对用户态的进程进行profile,还可以进行kernel的profile,特别强大。强烈推荐有对于mysqld的性能调试需求的读者使用,当然也是进行其他程序性能调试不可缺少的工具。