1.调用的前序过程
1.1过程描述
Innodb的查询最终都是通过row_search_mvcc执行的,row_search_mvcc查询数据,如果是索引查询则从顶至下遍历B+ Tree至叶节点,如果是全表或全索引扫描则叶节点从左往右查询,如果数据在内存中则直接获取page对象,如果在磁盘中则通过page信息定位并加载page
btr_pcur_open_with_no_init():根据search_tuple放置cursor,从顶至下遍历B+ Tree,得到比如二级索引的record值
row_sel_get_clust_rec_for_mysql():通过二级索引的record值获取主键索引的record
1.2详细流程
2.主要流程
2.1函数整体描述
Searches for rows in the database using cursor
PHASE 0: Release a possible s-latch we are holding on the adaptive hash index latch if there is someone waiting behind
PHASE 1: Try to pop the row from the prefetch cache
PHASE 2: Try fast adaptive hash index search if possible
Next test if this is the special case where we can use the fast adaptive hash index to try the search. Since we must release the search system latch when we retrieve an externally stored field, we cannot use the adaptive hash index in a search in the case the row may be long and there may be externally stored fields.
PHASE 3: Open or restore index cursor position(正式开始)
PHASE 4: Look for matching records in a loop
PHASE 5: Move the cursor to the next index record
2.2基本参数及定义
dict_index_t *index = prebuilt->index; //索引
const dtuple_t *search_tuple = prebuilt->search_tuple; //索引查询条件
btr_pcur_t *pcur = prebuilt->pcur; //当前游标
dict_index_t *clust_index; //聚集索引(主键索引)
2.3索引查询
如果是索引查询,从顶至下遍历B+Tree,查找指定的叶子节点btr_pcur_open_with_no_init
2.4全表扫描/全索引扫描
如果是全表扫描或者全索引扫描,从左至右或者从右至左遍历叶子节点
2.5rec_loop
查询出来的record可能并不满足条件,需要循环遍历,所以这里添加rec_loop锚点,取到下一条record跳到此处
如果是该page的第一条记录infimun record(第一条记录不是真实存放数据的地方),跳到下一条;
如果是该页的最后一条记录supremum,跳到下一页。
Infimun和Supremum Records 系统虚拟的记录,Infimun表示比任何主键值都小的值,Supremum表示比任何可能的值都大的值。
2.6二级索引
如果该条记录不是聚簇索引,则是二级索引,通过二级索引去查主键索引
2.7正常退出
如果查到的record条件满足,则正常退出
2.8next_rec
取到的record如果不满足条件会跳到next_rec锚点,查找下一条记录并跳到rec_loop处理