November 30, 2012

[MySQL 源码] Innodb Pessimistic Insert流程

简单跟了下插入导致索引分裂的流程 ////////////////////////////////// 入口函数:row_ins_index_entry 实际上悲观插入和乐观插入是根据row_ins_index_entry_low的第一个参数来判断的 调用两次row_ins_index_entry_low 第一次参数为BTR_MODIFY_LEAF,表示只修改叶子节点,如果失败了 第二次参数为BTR_MODIFY_TREE,表示需要修改B-TREE,这时候会选择调用函数: btr_cur_pessimistic_insert: 1.首先做一次乐观插入(btr_cur_optimistic_insert),这实际上是重复的动作,会带来额外的开销,在后面的版本已经被移除了。http://bugs.mysql.com/bug.php?id=61456 2.检查锁,如果是聚集索引,还要记录undo,并记录回滚段指针,对于非聚集索引,要在Page上记录最大事务ID 之前已经分析过,这里不赘述。     err = btr_cur_ins_lock_and_undo(flags, cursor, entry,                     thr, mtr, &dummy_inh); 3.扩展文件,为Ibd预留足够的文件空间 n_extents = cursor->tree_height / 16 + 3; success = fsp_reserve_free_extents(&n_reserved, index->space,                            n_extents, FSP_NORMAL, mtr); 4.检查当前记录是否需要进行外部存储(page_zip_rec_needs_ext),如果需要的话,则需要对记录进行处理 在函数dtuple_convert_big_rec中,会去循环查找,能最大减少rec的外部存储列 但固定长度列、空列、外部存储列或则长度小于40字节的列不做考虑 另外,在是用DYNAMIC和COMPRESSED格式时,任何最大长度小于256字节的非BLOB列都是本地存储;而对于REDUNDANT和COMPACT类型而言,最大不超过788字节时都会本地存储。 big_rec_vec = dtuple_convert_big_rec(index, entry, &n_ext); 返回值类型为big_rec_struct,用于存储溢出数据。 如果找不到满足要求的最大列,返回NULL。 如果找到了,则替换原记录上的外部指针,并存储实际数据。 如果依然不满足页内存储,则继续寻找该记录上更多的列来进行外部存储。 5.开始进行索引分裂: a.如果当前记录的cursor在根Page上,则分裂节点,提升BTREE高度,然后再插入记录 *rec = btr_root_raise_and_insert(cursor, […]