|
1. 为什么要阅读MySQL源码?
之前已经看过 高性能MySQL 和 MySQL技术内幕InnoDB存储引擎, 但总觉得只是看看书上这么说还是不够.
比如 高性能MySQL 里画的有B-Tree索引的示意图,可是B-Tree索引究竟长什么样子,在MySQL里是怎么存储的,没什么概念; 里边还提到关联查询的”泳道图”,在代码层面到底是怎么执行的,也不清楚.
2. 从哪儿开始?
直接看MySQL的源码有点困难.
好在有一本讲MySQL的书, 叫 Understanding.MySQL.Internals, 书虽然有点老,但看起来是个不错的开始.
大概过一下书的内容,发现大部分内容还是看不下去. 只有第4章 Client/Server Communication 还能看.
3. Protocol
Understanding.MySQL.Internals 的第4章 Client/Server Communication 讲了MySQL Server和客户端沟通的协议, 结合着wireshark, 很快就能搞明白.
http://heguangyu5.github.io/mysql/1-protocol.html
4. main() -> mysqld_main()
MySQL是由C++写的,入口函数main()直接调用了mysqld_main().
Server启动的代码都在这里,大部分都看不懂.
直到最后的 handle_connections_sockets().
5. 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
6. 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
7. 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
8. .MYD and .MYI
由于之前看过InnoDB技术内幕,显然InnoDB比MyISAM要复杂多了.
MySQL Internals Manual 里边有一章讲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.
9. .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文件.
10. 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, 总算看到”泳道图”是怎么执行的了.

11. 下一步
OK, 万事开头难. 到此也算是开了个头了.
缓一缓后边再看下这个 23 Writing a Custom Storage Engine |
|