IBUF相关


参考
http://mysql.taobao.org/monthly/2015/07/01/

  • ibuf说明

ibuf本质上是一个B+树,主要存储在ibdata中,其最大大小不能超过参数innodb_change_buffer_max_size的设置,如果超过则会触发合并操作,而在各个tablespace中的ibuf map page 主要存储的是page空闲空间的位图,主要作用是用来防止ibuf合并导致二级索引的B+树变化,因为ibuf的记录使用space和page no来定位需要合并的page,如果page no发生变化则不能合并,因此在写入ibuf内容的时候需要判断缓存的操作是否对二级索引B+树带来变化。

  • 不能进行IBUFF缓存的情况

A:如果本次是删除行,也就是delete操作(purge线程),并且二级索引中只有1条数据了或者二级索引page已经再读取中,这可能导致二级索引页合并,不能缓存
B:如果本次是插入行,也就是是insert操作,二级索引没有空闲,可能导致二级索引页分裂不能缓存
C:如果缓存大小已经大于了参数设置的大小,则不能缓存,且触发8个page的合并操作
D:参数关闭了对应操作的change buffer则不进行缓存
E:page已经在innodb buffer中不需要缓存
F:本次操作的行大于了二级索引页的1/2不进行缓存,这个基本不会出现
G:主键不缓存,二级唯一索引只缓存删除操作,因为如果缓存则可能导致唯一性不满足的情况

  • 参数修改innodb_change_buffering

参数的修改不会影响现有的ibuf信息,但是设置后就不会进行ibuf的写入,因此现有的ibuf也会慢慢合并掉。包含inserts/deletes/changes/purges/none 5个选项

  • 修改参数innodb_change_buffer_max_size

可能导致更多的合并操作,导致IO上升,ibuf_max_size_update(srv_change_buffer_max_size)
因为在ibuf insert中会判断是否超过了ibuf缓存的最大值,如果大于则会触发随机合并操作(IBUF_MERGE_AREA 8个pages)

  • IBUF和二级索引的关系

因为二级索引的修改都会涉及主键到二级索引的定位操作,因为先修改主键然后,修改二级索引,因此主要在btr_cur_search_to_nth_level定位函数上判断是否可以进行ibuf缓存

row_upd_sec_index_entry 
   ...
  ->btr_cur_search_to_nth_level
  • 缓存的操作主要有

IBUF_OP_INSERT = 0 insert操作
IBUF_OP_DELETE_MARK = 1 delete操作
IBUF_OP_DELETE = 2 purge线程操作

对于二级索引update都是delete和insert操作,但是delete mark的行可以在下一次二级索引插入同样长度行的时候进行重用

  • ibuf记录的结构
1、此处完成后ibuf中的字段包含4+用户字段数量如下
A、space id  4     IBUF_REC_FIELD_SPACE
B、marker   1      IBUF_REC_FIELD_MARKER
C、page no  4     IBUF_REC_FIELD_PAGE
D、metadata 可变
IBUF_REC_FIELD_METADATA
   IBUF_REC_OFFSET_COUNTER  2              -
   IBUF_REC_OFFSET_TYPE         1          -   --> BUF_REC_INFO_SIZE  4
   IBUF_REC_OFFSET_FLAGS       1           -
   n*DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE  可变  n为字段
      每个DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
      字段类型     2
      字段长度     2
      字符集类型 2      
E、user field  可变
    用户字段
  • 引入sentinel page的原因

update 修改二级索引 是 delete 和 insert这个时候delete 记录由于read view需要不能清理 一直保留着,这个时候二级索引 insert 一行相同的或者长度相同的二级索引记录,那这个del flag记录可能重用。

row_ins_must_modify_rec:用于主键和二级索引来判断是否直接利用del flag的记录。
row_ins_sec_index_entry_by_modify:考虑进行原地更新,二级索引主要出现在del flag标记的二级索引上。因为二级索引又是ibuf 缓存重要对象,因此purge 线程在对ibuf做del flag标记记录清理的时候会特别注意,因为可能这个del flag记录会被重用,这个时候需要引入ibuffer instance 的watch数组。

  • 初始化sentinel page,每个instance 都有 purge 线程+1个
    buf_pool_init_instance
  ->buf_pool->watch = (buf_page_t*) ut_zalloc_nokey( sizeof(*buf_pool->watch) * BUF_POOL_WATCH_SIZE)
     每个instance 初始化 purge + 1 个 watch pages 
  ->for (i = 0; i < BUF_POOL_WATCH_SIZE; i++)
     buf_pool->watch[i].buf_pool_index = buf_pool->instance_no;
     初始化每个watch page 的index 为本buf pool的instance_no
  • buf_pool_watch_set

主要是再purge线程获取page的时候设置page为BUF_BLOCK_ZIP_PAGE,防止二级索引的记录和前台session并发处理。初始化page的状态为BUF_BLOCK_POOL_WATCH ,也就是sentinel page处于空闲状态,purge持有的情况下转变为BUF_BLOCK_ZIP_PAGE状态

buf_page_get_gen
   ->if (mode == BUF_GET_IF_IN_POOL_OR_WATCH)
      如果获取page的时候是需要这个状态,则是purge线程
      ->buf_pool_watch_set
         先要寻找page是否再page中,然后判断page是否已经设置为BUF_BLOCK_ZIP_PAGE
         如果是则不做处理了
        首先获取一个buffer pool上的sentinel page
        for (i = 0; i < BUF_POOL_WATCH_SIZE; i++)
        ->switch (bpage->state)
           case BUF_BLOCK_POOL_WATCH:
              ->bpage->state = BUF_BLOCK_ZIP_PAGE
                 page更改为BUF_BLOCK_ZIP_PAGE状态
              ->bpage->id.copy_from(page_id)
              ->bpage->buf_fix_count = 1
              ->HASH_INSERT
                 将这个page的信息放入sentinel page中
  • buf_pool_watch_unset
    是上面函数的逆过程,主要调用是再purge线程缓存完ibuf操作后设置
    也就是函数btr_cur_search_to_nth_level中BTR_DELETE_OP操作调用

  • buf_pool_watch_remove
    buf_pool_watch_unset 也会调用这个函数,物理读取初始化page的时候更改sentinel page为BUF_BLOCK_POOL_WATCH,并且清理掉buffer pool hash中的缓存

  • buf_pool_watch_is_sentinel
    这个函数用于判断是否是sentinel page其调用者主要包含buf_page_get_gen,如果是sentinel page则直接进入物理读取流程
  • ibuf_merge_or_delete_for_page
    这个函数是应用ibuf到block的主要函数,主要的合并是在IO读取完成的时候进行也就是io_complete 中
  • 合并时机

1、IO 读取完成后
2、ibuf空间不够,随机合并8个page
3、master 线程每秒合并
4、slow shutdown
5、crash recovery
6、flush table for export (row_quiesce_table_start)

主要工作是对于

IBUF_OP_INSERT = 0  将缓存的insert的记录插入的二级索引中
IBUF_OP_DELETE_MARK = 1  将缓存的标记delete标记的记录,标记到二级索引中。
IBUF_OP_DELETE = 2 purge线程操作,将真正的删除操作在二级索引也删除。 
  • ibuf的构建和其他
row_ins_sec_index_entry 3421
  ->row_ins_sec_index_entry_low 2999
    ->btr_cur_search_to_nth_level 1152
       ->ibuf_insert   3812
          ->use= ibuf_use
             是否使用了ibuf
          ->no_counter = use <= IBUF_USE_INSERT
             如果只是缓存INSERT ibuf,则no_counter为true
          ->switch (op)
             对IBUF_OP_INSERT/IBUF_OP_DELETE_MARK/IBUF_OP_DELETE 分别处理
             这里也就是判断操作和参数设置是否相符,如果不相符则不使用ibuf
          ->buf_pool_t* buf_pool = buf_pool_get(page_id)
          ->buf_page_t* bpage= buf_page_get_also_watch(buf_pool, page_id)
          ->if (bpage != NULL){DBUG_RETURN(FALSE)}
             这里如果找到了page,则说明插入的page在buffer中,直接返回,不需要插入到ibuf中
          
          ->entry_size = rec_get_converted_size(index, entry, 0)
          ->if (entry_size>= page_get_free_space_of_empty(dict_table_is_comp(index->table))/ 2); DBUG_RETURN(FALSE)
             如果记录过大大于page的1/2不能插入到ibuf中
          ->ibuf_insert_low
             先尝试乐观插入 使用BTR_MODIFY_PREV
             ->ibuf_insert_low(BTR_MODIFY_PREV, op, no_counter,entry, entry_size,index, page_id, page_size, thr)
                op为IBUF_OP_INSERT/IBUF_OP_DELETE_MARK/IBUF_OP_DELETE种的一种
                index为插入的索引,一定为二级索引
                no_counter 为前面得到,如果只有BUF_USE_INSERT操作,则为false
                entry 为插入的数据
                ->do_merge = FALSE
                ->if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT)
                  大于了最大值 则不再缓存,这里实际上就是参数
                  innodb_change_buffer_max_size指定的大小,默认为25%
                  ->ibuf_contract(true)
                   触发一次合并操作
                   ->ibuf_merge_pages
                      ->btr_pcur_open_at_rnd_pos_func
                        ->btr_cur_open_at_rnd_pos_func
                          ->page_cur_open_on_rnd_user_rec
                             随机获取记录
                   ->ibuf_get_merge_page_nos
                       在随机位置上获取page
                       ->ibuf_get_merge_page_nos_func
                          合并page数量为IBUF_MERGE_AREA 8个page     
                          返回从ibuff索引中page记录的总大小(8)和page数量     
                   ->buf_read_ibuf_merge_pages
                      ->buf_read_ibuf_merge_pages(sync, space_ids, page_nos, *n_pages)
                         ->buf_read_page_low(&err, sync && (i + 1 == n_stored),IORequest::IGNORE_MISSING, BUF_READ_ANY_PAGE, page_id,page_size, true)           
                  ->return(DB_STRONG_FAIL)   
                    返回不能ibuf缓存
                ->heap = mem_heap_create(1024)
                  分配内存
                ->ibuf_entry = ibuf_entry_build(op, index, entry, page_id.space(), page_id.page_no(),no_counter ? ULINT_UNDEFINED : 0xFFFF, heap)     
                  构建insert buffer中的记录,记录就是space id page no counter 和 每个实际的字段
                  如果no_counter为true则为ULINT_UNDEFINED,否则为 0xFFFF
                  no_counter为true代表只缓存IBUF_USE_INSERT,当前参数一般为ALL,因此一般为0xFFFF
                  ->n_fields = dtuple_get_n_fields(entry);tuple = dtuple_create(heap, n_fields + IBUF_REC_FIELD_USER)
                    根据字段数量建立元组,IBUF_REC_FIELD_USER为4是什么意 
                    这里的4是4个字段包含,1、space id 2、marker 3、page no  4、metadata 5、user field
                    的前面4个
                  ->field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE);mach_write_to_4(buf, space); dfield_set_data(field, buf, 4);
                     写入space_id 4字节
                  ->field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER);mach_write_to_1(buf, 0);dfield_set_data(field, buf, 1);
                     写入默认值为 0
                  ->field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE);mach_write_to_4(buf, page_no);dfield_set_data(field, buf, 4);
                     写入page_no
                  ->ti = type_info = static_cast<byte*>(mem_heap_alloc(heap,i + n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE))
                     分配内存 IBUF_REC_INFO_SIZE + n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
                     IBUF_REC_INFO_SIZE 用于代表 IBUF_REC_OFFSET_TYPE IBUF_REC_OFFSET_FLAGS IBUF_REC_OFFSET_COUNTER的长度4字节
                  ->switch (i)  
                     准备写入IBUF_REC_FIELD_METADATA
                     case IBUF_REC_INFO_SIZE:
                     只考虑参数一般为ALL的情况
                     ->mach_write_to_2(ti + IBUF_REC_OFFSET_COUNTER, counter);
                     ->ti[IBUF_REC_OFFSET_TYPE] = (byte) op
                     ->ti[IBUF_REC_OFFSET_FLAGS] = dict_table_is_comp(index->table)? IBUF_REC_COMPACT : 0
                      ->ti += IBUF_REC_INFO_SIZE
                        这里写入IBUF_REC_OFFSET_COUNTER/IBUF_REC_OFFSET_TYPE/IBUF_REC_OFFSET_TYPE/IBUF_REC_OFFSET_FLAGS
                        等信息也就是IBUF_REC_FIELD_METADATA的前3信息,总部IBUF_REC_INFO_SIZE4字节大小
                      ->for (i = 0; i < n_fields; i++) 
                        ->field = dtuple_get_nth_field(tuple, i + IBUF_REC_FIELD_USER)
                           获取ibuf 记录的字段位置
                        ->entry_field = dtuple_get_nth_field(entry, i)
                           获取用户集中的字段 
                        ->dfield_copy(field, entry_field); 
                           将用户字段考呗到ibuf记录中
                        ->dtype_new_store_for_order_and_null_size(ti, dfield_get_type(entry_field), fixed_len)
                            设置DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE信息
                        ->ti += DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
                  ->field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_METADATA);
                  ->dfield_set_data(field, type_info, ti - type_info)
                    到这里IBUF_REC_FIELD_METADATA的信息才完全确认,因为各个字段的
                    DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE的信息是需要循环每个字段
                    才能完成
                  ->dtuple_set_types_binary(tuple, n_fields + IBUF_REC_FIELD_USER)
                    设置所有字段类型,完成后的记录类型如后面(1)
                ->if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE)
                   for循环
                   ->ibuf_data_enough_free_for_insert()
                     用于判断是否可以插入的信息
                     ->return(ibuf->free_list_len >= (ibuf->size / 2) + 3 * ibuf->height)
                       保留的free length比较大,大约为50%的空闲空间
                   ->if (!ibuf_add_free_page())
                      是否可以对ibuf增加新page,新增page 加锁放入到free list中
                      主要是写入到PAGE_BTR_IBUF_FREE_LIST,并且增加
                      FIL_PAGE_IBUF_FREE_LIST长度 
                      并且增加ibuffer内存中的free_list_len
                        ibuf->seg_size++;
                      ibuf->free_list_len++;
                   ->如果都不可以则返回不能缓存
                      return(DB_STRONG_FAIL)
                ->btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr)
                   使用ibuf_entry打开游标,定位到ibuf index的位置
                ->buffered = ibuf_get_volume_buffered(&pcur,page_id.space(),page_id.page_no(),op == IBUF_OP_DELETE ? &min_n_recs: NULL, &mtr);
                   这个函数用于返回如果合并当前ibuf 页后,可能导致的二级索引空间的变化量,如果是本条记录是IBUF_OP_DELETE操作
                   需要记录变化的行数
                ->if (op == IBUF_OP_DELETE && (min_n_recs < 2 || buf_pool_watch_occurred(page_id)))
                   导致二级索引页合并:如果是delete操作,并且二级索引中只有1条数据了或者已经再读取中,则不能缓存了,
                   因为可能合并后可能导致二级索引页合并
                   ->err = DB_STRONG_FAIL; 
                   标记错误不能缓存
                   goto func_exit;
                ->bitmap_page = ibuf_bitmap_get_map_page(page_id, page_size,&bitmap_mtr);
                   获取二级索引上的 bitmap block,
                ->if (op == IBUF_OP_INSERT)
                   如果缓存的是insert操作,需要坚持导致二级索引页分裂的情况
                   ->bits = ibuf_bitmap_page_get_bits(bitmap_page, page_id, page_size, IBUF_BITMAP_FREE,&bitmap_mtr);
                   ->if (buffered + entry_size + page_dir_calc_reserved_space(1)> ibuf_index_page_calc_free_from_bits(page_size, bits))
                      导致二级索引页分裂:如果本page合并后空间大于了剩余空间,合并可能导致二级索引页分裂
                      如果大于则不适合进行缓存
                      ->ibuf_get_merge_page_nos(FALSE,btr_pcur_get_rec(&pcur), &mtr,space_ids, page_nos, &n_stored);
                        扫描ibuf 游标 page中 ibuf rec的space 和 page no 集合
                     ->goto fail_exit
                        不适合缓存,但是读取本page中ibuf rec的page 进行merge    
                ->if (!no_counter) { 
                   ALL 都有no_counter
                ->ibuf_bitmap_page_set_bits(bitmap_page, page_id, page_size,IBUF_BITMAP_BUFFERED, TRUE,&bitmap_mtr);   
                   设置bit map 的IBUF_BITMAP_BUFFERED为true,表本page进行了缓存操作,需要合并
                   - IBUF_BITMAP_FREE 2   0(0 bytes)、1(512 bytes)、2(1024 bytes)、3(2048 bytes) 
                   - IBUF_BITMAP_BUFFERED 1  是否是ibuf操作
                   - IBUF_BITMAP_IBUF
                   为每个page记录信息,占用4位
                ->cursor = btr_pcur_get_btr_cur(&pcur);btr_cur_optimistic_insert;btr_cur_pessimistic_insert;
                   获取游标乐观或者悲观插入插入 到 ibuf索引中,本逻辑为乐观插入(BTR_MODIFY_PREV)
                   而BTR_MODIFY_TREE 可能是需要悲观插入的
                func_exit:
                ->buf_read_ibuf_merge_pages(false, space_ids,page_nos, n_stored)
          ->ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT
            如果乐观插入失败,则使用悲观插入          
            
#0  ibuf_insert (op=IBUF_OP_DELETE_MARK, entry=0x7fff7c0216c0, index=0x7fff7c01d0f0, page_id=..., page_size=..., thr=0x7fff7c0571a0)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:3706
#1  0x0000000001bedf0f in btr_cur_search_to_nth_level (index=0x7fff7c01d0f0, level=0, tuple=0x7fff7c0216c0, mode=PAGE_CUR_LE, latch_mode=2, cursor=0x7fffec28e020, has_search_latch=0, 
    file=0x22ee2e0 "/opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0row.cc", line=1073, mtr=0x7fffec28e120)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/btr/btr0cur.cc:1166
#2  0x0000000001b0a37c in btr_pcur_open_low (index=0x7fff7c01d0f0, level=0, tuple=0x7fff7c0216c0, mode=PAGE_CUR_LE, latch_mode=4098, cursor=0x7fffec28e020, 
    file=0x22ee2e0 "/opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0row.cc", line=1073, mtr=0x7fffec28e120)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/include/btr0pcur.ic:465


#0  ibuf_entry_build (op=IBUF_OP_INSERT, index=0x7fff95abe310, entry=0x7fff940257f0, space=29989, page_no=1310, counter=65535, heap=0x7fff94156148)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:1779
#1  0x00000000019f6d8b in ibuf_insert_low (mode=36, op=IBUF_OP_INSERT, no_counter=0, entry=0x7fff940257f0, entry_size=16, index=0x7fff95abe310, page_id=..., page_size=..., thr=0x7fff940f95a0)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:3425
#2  0x00000000019f7ac5 in ibuf_insert (op=IBUF_OP_INSERT, entry=0x7fff940257f0, index=0x7fff95abe310, page_id=..., page_size=..., thr=0x7fff940f95a0)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:3812
#3  0x0000000001bede51 in btr_cur_search_to_nth_level (index=0x7fff95abe310, level=0, tuple=0x7fff940257f0, mode=PAGE_CUR_LE, latch_mode=2, cursor=0x7fffec28cc40, has_search_latch=0, 
    file=0x22dc098 "/opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc", line=2999, mtr=0x7fffec28d000)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/btr/btr0cur.cc:1152
#4  0x0000000001abd939 in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x7fff95abe310, offsets_heap=0x7fff940fae38, heap=0x7fff940fb2e8, entry=0x7fff940257f0, trx_id=0, thr=0x7fff940f95a0, 
    dup_chk_only=false) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:2999
#5  0x0000000001abec00 in row_ins_sec_index_entry (index=0x7fff95abe310, entry=0x7fff940257f0, thr=0x7fff940f95a0, dup_chk_only=false)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3421
#6  0x0000000001abedb0 in row_ins_index_entry (index=0x7fff95abe310, entry=0x7fff940257f0, thr=0x7fff940f95a0) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3470
#7  0x0000000001abf2d5 in row_ins_index_entry_step (node=0x7fff940f92f0, thr=0x7fff940f95a0) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3618
#8  0x0000000001abf65f in row_ins (node=0x7fff940f92f0, thr=0x7fff940f95a0) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3760
#9  0x0000000001abfc83 in row_ins_step (thr=0x7fff940f95a0) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3945
#10 0x0000000001adfb9f in row_insert_for_mysql_using_ins_graph (mysql_rec=0x7fff9405c980 "\374\001", prebuilt=0x7fff940f8d50)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0mysql.cc:2283
#11 0x0000000001ae012b in row_insert_for_mysql (mysql_rec=0x7fff9405c980 "\374\001", prebuilt=0x7fff940f8d50) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/row/row0mysql.cc:2406
#12 0x000000000197ab14 in ha_innobase::write_row (this=0x7fff94025180, record=0x7fff9405c980 "\374\001") at /opt/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:8344
#13 0x0000000000f640b6 in handler::ha_write_row (this=0x7fff94025180, buf=0x7fff9405c980 "\374\001") at /opt/percona-server-locks-detail-5.7.22/sql/handler.cc:8466
#14 0x000000000178fb66 in write_record (thd=0x7fff94000b70, table=0x7fff94046b10, info=0x7fff940075e8, update=0x7fff94007660) at /opt/percona-server-locks-detail-5.7.22/sql/sql_insert.cc:1881

struct ibuf_t{
    ulint       size;       /*!< current size of the ibuf index
                    tree, in pages */
    ulint       max_size;   /*!< recommended maximum size of the
                    ibuf index tree, in pages */
    ulint       seg_size;   /*!< allocated pages of the file
                    segment containing ibuf header and
                    tree */
    bool        empty;      /*!< Protected by the page
                    latch of the root page of the
                    insert buffer tree
                    (FSP_IBUF_TREE_ROOT_PAGE_NO). true
                    if and only if the insert
                    buffer tree is empty. */
    ulint       free_list_len;  /*!< length of the free list */
    ulint       height;     /*!< tree height */
    dict_index_t*   index;      /*!< insert buffer index */

    ulint       n_merges;   /*!< number of pages merged */
    ulint       n_merged_ops[IBUF_OP_COUNT];
                    /*!< number of operations of each type
                    merged to index pages */
    ulint       n_discarded_ops[IBUF_OP_COUNT];
                    /*!< number of operations of each type
                    discarded without merging due to the
                    tablespace being deleted or the
                    index being dropped */
};

Ibuf: size 1, free list len 0, seg size 2,            0 merges
                                          ibuf page数量      合并次数
  
  
merged operations: merge 操作次数
 insert 0, delete mark 0, delete 0
discarded operations: 抛弃次数
 insert 0, delete mark 0, delete 0
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容