日期:2014-05-16 浏览次数:20499 次
MySQL查询逻辑以及结果的输出有规律吗?本身问题是不值得讨论的,突然被问到这个问题时,觉得有必要把其深入的实现原理搞明白。因此,通过一些实验进行验证,并跟踪源码,对现有的查询有了深入的理解。
源码分析
查询于存储引擎的实现密切相关,因此,以下内容主要针对Innodb存储引擎的查询处理进行深入研究。对于查询输出的入口点,本文从do_select()(sql\sql_select.cc)函数开始。该函数主要用于查询匹配的结果,并将查询结果通过socket传输,或者写到数据表中。
首先看一下调用逻辑,如下所示:
do_select(): 查询入口函数。 | sub_select(): 查询部分join的记录。循环调用ha_innobase::rnd_next()和evaluate_join_record()获取并处理该部分的每条记录。(sql\sql_select.cc:11705) | | evaluate_join_record(): 处理一条查询记录。(sql\sql_select.cc:11758) | | rr_sequential():调用ha_innobase::rnd_next()读取下一条记录。(sql\records.cc:452) | | | ha_innobase::rnd_next(): 读取下一条记录。(storage\innobase\handler\ha_innodb.cc:6141) | | | | ha_innobase::general_fetch(): 从给定的索引位置获取下一条或上一条记录。(storage\innobase\handler\ha_innodb.cc:5948) | | | | | row_search_for_mysql(): 从数据库中查询一条记录。以下分为6个阶段分别处理各个部分。(storage\innobase\row\row0sel.c:3369) | | | | | | 第一阶段:释放自适应hash索引的锁。 | | | | | | | rw_lock_get_writer()函数用于获取读写锁。如果获取失败,释放目前的读写锁。(storage\innobase\include\sync0rw.ic:122) | | | | | | 第二阶段:从预读的cache中获取记录。 | | | | | | | row_sel_pop_cached_row_for_mysql():函数用于从cache中读取一行记录,(storage\innobase\row\row0sel.c:3167) | | | | | | | | row_sel_copy_cached_field_for_mysql(): 函数读取每个字段。(storage\innobase\row\row0sel.c:3134) | | | | | | 第三阶段:使用自适应hash索引快速查找。 | | | | | | | row_sel_try_search_shortcut_for_mysql()函数使用hash索引获取聚集索引的记录。(storage\innobase\row\row0sel.c:3293) | | | | | | | | row_sel_store_mysql_rec()函数将获取的innobase格式的行记录转化为mysql格式。(storage\innobase\row\row0sel.c:2692) | | | | | | | | | row_sel_field_store_in_mysql_format()函数将innobase格式的行记录中的每个字段转化为mysql格式。(storage\innobase\row\row0sel.c:2535) | | | | | | 第四阶段:打开并恢复索引的游标位置。 | | | | | | | sel_restore_position_for_mysql(): 恢复索引的游标位置。(storage\innobase\row\row0sel.c:3070) | | | | | | | | btr_pcur_restore_position_func(): 恢复一个持久化游标的位置。(storage\innobase\btr\btr0pcur.c:208) | | | | | | | | | btr_cur_get_index(): 获取索引。(storage\innobase\include\btr0pcur.ic:51) | | | | | | | | | buf_page_optimistic_get(): | | | | | | | | | btr_pcur_get_rec(): 获取持久化游标的记录。(stor
|