mysql 8.0 一条insert语句的具体执行流程分析(三)

代码版本:mysql 8.0.22

编程语言:c++ && c++11 && c++14 && c++17

上一篇文章:mysql 8.0 一条insert语句的具体执行流程分析(二)_一缕阳光的博客-CSDN博客

主要介绍了存储引擎部分,这个章节主要介绍insert一条语句时有二级索引时需要调用哪些接口,调用接口的顺序如下:

下面的接口基本上看源码就能理解,不再重述。

下面以聚集索引和二级索引为例,聚集索引调用接口如下:

| > row_ins_clust_index_entry
| | > row_ins_clust_index_entry_low
| | | > btr_cur_optimistic_insert
| | | | > btr_cur_ins_lock_and_undo
| | | | | > trx_undo_report_row_operation
| | | | | | > trx_undo_page_report_insert
| | | | | | | > trx_undo_page_set_next_prev_and_add
| | | | | | | | > trx_undof_page_add_undo_rec_log

| | | | > page_cur_tuple_insert
| | | | | > rec_convert_dtuple_to_rec
            > rec_convert_dtuple_to_rec_new
            > rec_convert_dtuple_to_rec_old
              > rec_convert_dtuple_to_rec_comp
            
| | | | | > page_cur_insert_rec_low
            > page_cur_insert_rec_write_log

(12)、row_ins_clust_index_entry : 插入entry到一个聚集索引,会调用13中的接口
(13)、row_ins_clust_index_entry_low : 尝试将entry插入到聚集索引中,忽略外键约束。
(14)、btr_cur_optimistic_insert : 插入一个page到一个索引tree
(15)、btr_cur_ins_lock_and_undo : 检查lock和写undo log
(16)、page_cur_tuple_insert : 将一条record追加到当前page,需要与17中的函数完成
(17)、page_cur_insert_rec_low : 将一条record追加到当前page,以非压缩方式写入

二级索引调用接口如下:

| > row_ins_sec_index_entry
| | > row_ins_sec_index_entry_low
| | | > btr_cur_search_to_nth_level
        > ibuf_should_try
| | | > row_ins_scan_sec_index_for_duplicate

(18)、row_ins_sec_index_entry : 在二级索引中插入entry
(19)、row_ins_sec_index_entry_low : 尝试将entry插入二级索引。如果找到一个字段完全相同的记录,则必须将另一个记录标记为已删除,然后再插入到二级索引中
(20)、btr_cur_search_to_nth_level : 在索引tree中给定的level上找到当前位置
(21)、row_ins_scan_sec_index_for_duplicate : 扫描给定索引项处的唯一非聚集索引,以确定该项的键值是否发生唯一性冲突。对可能重复的记录设置共享锁

最后,所有断点都被执行之后,使用bt命令将堆栈信息打印出来,由于断点太多了,打印了主要的一些函数,如下:

(gdb) bt
#0  btr_cur_optimistic_insert (flags=0, cursor=0x7fffe83d4ae0, offsets=0x7fffe83d4a78, 
    heap=0x7fffe83d4a70, entry=0x7fff300cb370, rec=0x7fffe83d4a80, big_rec=0x7fffe83d4a68, 
    thr=0x7fff3029c6f8, mtr=0x7fffe83d50a0)
    at /storage/innobase/btr/btr0cur.cc:2833
#1  0x000055555a4c7571 in row_ins_clust_index_entry_low (flags=0, mode=2, index=0x7fff3028a640, 
    n_uniq=1, entry=0x7fff300cb370, thr=0x7fff3029c6f8, dup_chk_only=false)
    at storage/innobase/row/row0ins.cc:2518
#2  0x000055555a4c945c in row_ins_clust_index_entry (index=0x7fff3028a640, entry=0x7fff300cb370, 
    thr=0x7fff3029c6f8, dup_chk_only=false)
    at /storage/innobase/row/row0ins.cc:3097
#3  0x000055555a4c9c14 in row_ins_index_entry (index=0x7fff3028a640, entry=0x7fff300cb370, 
    multi_val_pos=@0x7fff3029c3f8: 0, thr=0x7fff3029c6f8)
    at /storage/innobase/row/row0ins.cc:3289
#4  0x000055555a4ca26f in row_ins_index_entry_step (node=0x7fff3029c338, thr=0x7fff3029c6f8)
    at /storage/innobase/row/row0ins.cc:3425
#5  0x000055555a4ca616 in row_ins (node=0x7fff3029c338, thr=0x7fff3029c6f8)
    at /storage/innobase/row/row0ins.cc:3544
#6  0x000055555a4caa92 in row_ins_step (thr=0x7fff3029c6f8)
    at /storage/innobase/row/row0ins.cc:3668
#7  0x000055555a4ea804 in row_insert_for_mysql_using_ins_graph (mysql_rec=0x7fff302892c8 "\376\005", 
    prebuilt=0x7fff3029b830) at /storage/innobase/row/row0mysql.cc:1581
#8  0x000055555a4eae9a in row_insert_for_mysql (mysql_rec=0x7fff302892c8 "\376\005", 
    prebuilt=0x7fff3029b830) at /storage/innobase/row/row0mysql.cc:1711
#9  0x000055555a2a9ad9 in ha_innobase::write_row (this=0x7fff30287bf8, record=0x7fff302892c8 "\376\005")
    at /storage/innobase/handler/ha_innodb.cc:8629
#10 0x0000555558d4ace2 in handler::ha_write_row (this=0x7fff30287bf8, buf=0x7fff302892c8 "\376\005")
    at /sql/handler.cc:7831
#11 0x00005555590a14a7 in write_record (thd=0x7fff30001040, table=0x7fff30287270, info=0x7fffe83d64f0, 
    update=0x7fffe83d6570) at /sql/sql_insert.cc:2148
#12 0x000055555909cb7e in Sql_cmd_insert_values::execute_inner (this=0x7fff302becc8, thd=0x7fff30001040)
    at /sql/sql_insert.cc:633
#13 0x00005555589ff8fc in Sql_cmd_dml::execute (this=0x7fff302becc8, thd=0x7fff30001040)
    at /sql/sql_select.cc:612
#14 0x000055555897bd6e in mysql_execute_command (thd=0x7fff30001040, first_level=true)
    at /sql/sql_parse.cc:3420
#15 0x00005555589810b9 in dispatch_sql_command (thd=0x7fff30001040, parser_state=0x7fffe83d7b90)
    at /sql/sql_parse.cc:4988
#16 0x0000555558977226 in dispatch_command (thd=0x7fff30001040, com_data=0x7fffe83d8b80, 
    command=COM_QUERY) at /sql/sql_parse.cc:1836
#17 0x00005555589756df in do_command (thd=0x7fff30001040)
    at /sql/sql_parse.cc:1320
#18 0x0000555558b6ee3d in handle_connection (arg=0x55556006bbe0)
    at /sql/conn_handler/connection_handler_per_thread.cc:301
#19 0x000055555aa337b6 in pfs_spawn_thread (arg=0x55555fee7ae0)
    at /storage/perfschema/pfs.cc:2900
--Type <RET> for more, q to quit, c to continue without paging--
#20 0x00007ffff7f95609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#21 0x00007ffff76e0293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

到此为止,在MySQL中insert一条record的基本过程已经梳理完毕,流程还是比较清晰的,有数据库初级经验的基本都能理清楚。

接下来几篇文章主要讲述MySQL中redo.log中的mtr。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值