最近在做一个小特性,让InnoDB支持repair table来重建corrupted的索引,本文描述的是实现过程中遇到的一个小问题,主要和innodb drop index相关的一些随笔记录。
现象:针对损坏的page,加上一个标记位为corrupted,然而在删除索引并重建后,该标记未被清除掉,但是我在读取page时已经加了清理标记的操作(buf_page_init_low)。
drop index流程:
a. ha_innobase::prepare_inplace_alter_table
设置index->to_be_dropped = 1
b. ha_innobase::inplace_alter_table
不干活
c. ha_innobase::commit_inplace_alter_table
commit_try_norebuild
//row_merge_rename_index_to_drop : 将需要drop的index 在数据词典里rename成TEMP_INDEX_PREFIX前缀+index名
commit_cache_norebuild
//index->page = FIL_NULL
//row_merge_drop_indexes_dict:从数据词典SYS_INDEXES,SYS_FIELDS,中删除索引项相关记录。
/////row_merge_drop_indexes_dict—>que_eval_sql—>que_run_threads—>que_run_threads_low—>row_upd_step—>row_upd—>row_upd_clust_step—>dict_drop_index_tree 从系统表中删除记录,会触发释放索引树
/////////////btr_free_but_not_root—>fseg_free_step—>fseg_free_extent—>btr_search_drop_page_hash_when_freed 删除所有的AHI项
//dict_index_remove_from_cache:从cache中移除索引
alter_stats_norebuild
//dict_stats_drop_index: 从系统表mysql/innodb_index_stats中移除索引的物化的统计信息
如何处理二级索引在buffer pool中的page:
从代码逻辑来看,对drop掉的二级索引并没有做标脏驱逐处理,还是留在buffer pool中,也没有从Page hash中删除,仅仅释放自适应哈希记录。
如何重用:
由于被drop的索引段已经被设置为free,因此可以重用Page。然而buffer pool中的老索引的page可能并没有被驱逐掉,还存在于page hash中,这些block可以被重用,相关堆栈:
row_merge_build_indexes—>row_merge_insert_index_tuples—>btr_cur_pessimistic_insert—>btr_page_split_and_insert—>btr_page_alloc—>btr_page_alloc_low—>fseg_alloc_free_page_general—>fseg_alloc_free_page_low
—>fsp_page_create
—>buf_page_create
—>fsp_init_file_page //重新初始化page,抛弃旧的内容