我是如何开始阅读MySQL源码的?

[TOC]

为什么要阅读MySQL源码?

之前已经看过 高性能MySQL 和 MySQL技术内幕InnoDB存储引擎, 但总觉得只是看看书上这么说还是不够.

比如 高性能MySQL 里画的有B-Tree索引的示意图,可是B-Tree索引究竟长什么样子,在MySQL里是怎么存储的,没什么概念; 里边还提到关联查询的"泳道图",在代码层面到底是怎么执行的,也不清楚.

从哪儿开始?

直接看MySQL的源码有点困难. 好在有一本讲MySQL的书, 叫 Understanding.MySQL.Internals, 书虽然有点老,但看起来是个不错的开始.

大概过一下书的内容,发现大部分内容还是看不下去. 只有第4章 Client/Server Communication 还能看.

Protocol

Understanding.MySQL.Internals 的第4章 Client/Server Communication 讲了MySQL Server和客户端沟通的协议, 结合着wireshark, 很快就能搞明白.

http://heguangyu5.github.io/mysql/1-protocol.html

main() -> mysqld_main()

MySQL是由C++写的,入口函数main()直接调用了mysqld_main(). Server启动的代码都在这里,大部分都看不懂. 直到最后的 handle_connections_sockets().

handle_connections_sockets()

读过UNP的看这部分代码应该都没问题.

poll()
accept()
thread_scheduler->add_connection()
pthread_create() or thead_cache

handle_one_connection()

for (;;) {
	while (connection_alive()) {
		do_command();
	}
	cache_thread();
}

do_command() -> dispatch_command()

http://heguangyu5.github.io/mysql/2-handle-connections-sockets.html

dispatch_command()

这里已经能够看到很多熟悉的词语了,CHANGE_USER,STMT_EXECUTE,STMT_FETCH.

不过最关键的执行SQL语句的部分, COM_QUERY, 看不懂.

mysql_parse() -> MYSQLparse()

Understanding.MySQL.Internals 的第9章 Parser and Optimizer, 是讲这部分的. 在Parse Tree部分有提到SQL语句最终在 mysql_execute_command() 里执行.

http://heguangyu5.github.io/mysql/3-dispatch-command.html

mysql_execute_command()

case SQLCOM_CREATE_DB:      mysql_create_db();
case SQLCOM_CREATE_TABLE:   mysql_create_table();
case SQLCOM_INSERT:         mysql_insert();
case SQLCOM_SELECT:         execute_sqlcom_select();

mysql_create_db()好理解. mysql_create_table()里有创建一个.frm文件,要是有文档说明下.frm文件的格式就好了.

于是就找到了这个 https://dev.mysql.com/doc/internals/en/fileformats.html 从这往篇文档可以看出, MySQL的历史真的太久了,官方文档对很多字段的说明都是always, ??. 看了这个文档还是搞不明白.frm文件的格式.

http://heguangyu5.github.io/mysql/4-mysql-execute-command.html

.MYD and .MYI

由于之前看过InnoDB技术内幕,显然InnoDB比MyISAM要复杂多了.

https://dev.mysql.com/doc/internals/en/ 里边有一章讲MyISAM的,仔细分析了.MYD和.MYI文件的格式,讲的挺清楚的.

.MYD的文件格式挺简单的. .MYI的就复杂很多了. 对着文档写个小程序读取并解析.MYI文件,有很大帮助.

http://heguangyu5.github.io/mysql/5-MyISAM.html https://github.com/heguangyu5/heguangyu5.github.io/blob/master/mysql/read-MYI.c

搞清楚了.MYD和.MYI的文件格式,很多名词术语也混个脸儿熟了. 回过头来再看.frm.

.frm

创建.frm文件的代码在 mysql_create_frm() 里. 努力一番后,再写个小程序读取并解析下.frm文件,总算搞清楚其格式了.

http://heguangyu5.github.io/mysql/6-frm.html https://github.com/heguangyu5/heguangyu5.github.io/blob/master/mysql/read-frm.c

在创建完.frm后,又调用了Storage Engine的ha_create()方法创建了其它相关的文件,比如MyISAM就创建了.MYD和.MYI文件.

plugin_init, mysql_insert, execute_sqlcom_select

这个时间回过头来再看下启动代码里的plugin_init部分,还是相对容易的搞清楚了Stroage Engine是怎么加载的了.

自己编译一个debug版本的mysqld会有一些帮助.

mysql_insert()还是比较简单的.

execute_sqlcom_select()就复杂了. 结合着Understanding.MySQL.Internals 的第9章 Parser and Optimizer, 总算看到"泳道图"是怎么执行的了.

下一步

OK, 万事开头难. 到此也算是开了个头了.

缓一缓后边再看下这个 https://dev.mysql.com/doc/internals/en/custom-engine.html

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章