共计 2542 个字符,预计需要花费 7 分钟才能阅读完成。
这篇文章主要讲解了“Innodb 中 insert 第一次进行乐观插入逻辑分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“Innodb 中 insert 第一次进行乐观插入逻辑分析”吧!
实际在这之前记录是每行每行的插入,而且是每行每个索引的插入,这里仅仅讲述的是某行关于某个二级索引的乐观插入流程,所谓乐观就是不会引起索引树的结构更改,换而言之当前块有足够的空间进行插入。
本文仅仅记录乐观插入的流程,和函数的入口,实际上很多我们关心的东西在哪里比如,这里没有考虑压缩页:
重用空间只会检查 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
— 分裂建议建议分裂
感谢各位的阅读,以上就是“Innodb 中 insert 第一次进行乐观插入逻辑分析”的内容了,经过本文的学习后,相信大家对 Innodb 中 insert 第一次进行乐观插入逻辑分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!