ITPub博客

首页 > 数据库 > MySQL > Innodb:insert 第一次进行乐观插入逻辑(二级索引)

Innodb:insert 第一次进行乐观插入逻辑(二级索引)

原创 MySQL 作者:gaopengtttt 时间:2018-11-02 16:55:36 0 删除 编辑

水平有限,能力有限


实际在这之前记录是每行每行的插入,而且是每行每个索引的插入,这里仅仅讲述的是某行关于某个二级索引的乐观插入流程,所谓乐观就是不会引起索引树的结构更改,换而言之当前块有足够的空间进行插入。

本文仅仅记录乐观插入的流程,和函数的入口,实际上很多我们关心的东西在哪里比如,这里没有考虑压缩页:

  • 重用空间只会检查del链表的第一个成员,因此块中可能存在碎片

  • 是否触发悲观插入是通过计算整个块的剩余空间和插入记录的长度比较得出的结果,剩余空间包含了碎片空间

  • 对于插入印象锁需要根据下一条记录是否上锁来判断是否需要加并且等待

  • 可能会触发锁继承

  • 唯一检查会可能触发LOCK_S也是这里进入的

  • 插入之前要定位数据

  • undo在redo生成之前生成

逻辑入口如下:

->row_ins_sec_index_entry_low 第一次进行乐观插入 mode=BTR_MODIFY_LEAF
  -> 是否是唯一键 是 row_ins_scan_sec_index_for_duplicate 进行唯一性检查
  -> 进行唯一性检测结果处理
  -> 进行数据查找 btr_cur_search_to_nth_level
     ->page_cur_search_with_match_bytes
  -> 如果只是检查重复值跳过下面逻辑 if (dup_chk_only) 
  -> 进行乐观插入,假设不修改B+树结构 btr_cur_optimistic_insert,主要通过BTR_MODIFY_LEAF标示识别,此处不考虑压缩页
    ->计算转换逻辑记录(元组)为物理记录后的长度 rec_get_converted_size
      ->rec_get_converted_size_comp
    ->是否需要外部存储page_zip_rec_needs_ext
    ->获取块的空闲空间大小 page_get_max_insert_size_after_reorganize 备注(1
    ->进行是否需要悲观插入的逻辑判断,主要还是空间不够的情况 备注(2,如果需要悲观插入则这里返回了
    ->如果是主键还需要预留部分空间 备注(3,如果没有预留空间也会进入悲观插入流程
    ->判断是否需要加锁和开undo btr_cur_ins_lock_and_undo,此函数还会返回是否需要做锁继承的处理为输出参数inherit
      ->检查是否需要加锁lock_rec_insert_check_and_lock 插入印象锁就在这里
      ->记录undo trx_undo_report_row_operation
      ->更改row undo ptr指针row_upd_index_entry_sys_field
    ->做实际插入操作 page_cur_tuple_insert
      ->逻辑记录转换为物理记录 rec_convert_dtuple_to_rec
      ->获取每个字段的偏移量 rec_get_offsets
      ->进行实际插入 page_cur_insert_rec_low
        ->获取记录的实际大小
        ->寻找合适的位置进行插入,本步骤会找到合适的位置返回给insert_buf
          ->获取free链表的头部记录,注意只会检查第一个记录,不会做遍历,因此块中碎片是极有可能出现的
            只是innodb可以重组
          ->如果合适则使用
          ->不合适则返回
        ->进行记录创建拷贝 memcpy方式复制数据到insert_buf指向的位置,完成这一步记录加入到了块中 下面需要维护各种块信息  
        ->将记录加入到记录链表
        ->更新行的N_OWNER为0,以及设置heap_no
        ->设置块的一些最后修改属性如PAGE_DIRECTION、PAGE_N_DIRECTION、PAGE_LAST_INSERT
        ->更新slot的信息,可能涉及更改owner记录信息和owner记录的N_OWNER信息
        ->写redo信息 page_cur_insert_rec_write_log
      ->返回插入记录的offset
    ->进行AHI维护 btr_search_update_hash_on_insert/btr_search_update_hash_node_on_insert
    ->进行可能的锁的分裂 lock_update_insert 此处主要的判断是前面的输出参数inherit
    ->进行CHANGE BUFFER维护 ibuf_update_free_bits_if_full
  -> 如果成功修改最大事物ID PAGE_MAX_TRX_ID page_update_max_trx_id
  -> 返回结果
  • 备注1) 计算方式为
    空页的容量 = 页大小(比如16K) - 页头大小(120) - 页尾大小(8) - 初始化2个槽大小(4=2*2)
    实际的数据占用空间 = 已经分配数据空间的最大数据偏移量 - 页头大小(120) - 已经删除且purge的空间包含碎片空间 + 槽大小

然后用
空页的容量 - 实际的数据占用空间=实际可用空间

因为页中难免会出现一些碎片,但是innodb的page拥有重新组织的能力,能够释放这部分空间。其重组函数为btr_page_reorganize_low

  • 备注2) 逻辑包含
    如果包含碎片空间那么
    -- 如果可用空间不足或者可用空间已经少于了重组块的设置BTR_CUR_PAGE_REORGANIZE_LIMIT(UNIV_PAGE_SIZE / 32)
    -- 记录数量大于1
    -- 可用空间小于了插入记录的大小
    否则
    -- 可用空间小于了插入记录的大小

  • 备注3) 逻辑包含
    --叶子结点
    -- 主键
    -- 记录大于两行
    -- 剩余的空间 - 行的空间 < page_size/16
    -- 分裂建议建议分裂

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7728585/viewspace-2218565/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
wxh gp_22389860 <<深入理解MySQL主从原理专栏>> 发布 可加WX了解

注册时间:2008-10-13

  • 博文量
    715
  • 访问量
    3020160