[MySQL源码] 一条简单insert语句的调用栈

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
RDS AI 助手,专业版
简介:

以下仅用于本人调试MySQL所用,不具备可读性。

———————————————————–

CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;

insert into t1 values (4,2);

ha_innobase::write_row

 |–>row_insert_for_mysql 

     |–>转换记录格式row_mysql_convert_row_to_innobase

     |–>保存检查点savept = trx_savept_take(trx);

     |–>row_ins_step

        |–>加IX锁lock_table(0, node->table, LOCK_IX, thr)

        |–> row_ins     //轮询索引,向表中插入记录,这里只有聚集索引

        .   |–>row_ins_index_entry_step

        .      |–>构建索引记录(node->entry)row_ins_index_entry_set_vals

        .      |–>row_ins_index_entry(node->index, node->entry, 0, TRUE, thr)

        .      .   |–>检查外键约束row_ins_check_foreign_constraints

        .      .   |->使用如下两步尝试插入记录

                   >>step1.row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,n_ext, thr)/* Try first optimistic descent to the B-tree */

                   >>step2,若step1失败,row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,n_ext, thr);/* Try then pessimistic descent to the B-tree */

                       |–> row_ins_index_entry_low

                             |–>确定search_mode

                             1)如果是聚集索引,search_mode为传参BTR_MODIFY_LEAF或BTR_MODIFY_TREE

                             2)当前事务的check_unique_secondary为false时(由变量unique_checks控制,默认为true,表示检查唯一索引约束),search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE

                             3)否则,search_mode = mode | BTR_INSERT

                             |–>btr_cur_search_to_nth_level  查询索引树,将cursor移动到记录相应的位置(待分析)

                             |–>检测是否有dup key,主键索引调用row_ins_duplicate_error_in_clust,二级索引调用row_ins_scan_sec_index_for_duplicate

                             |–>modify = row_ins_must_modify  (待分析)

                             >>当modify!=0时,表明已经有一个足够长的common prefix,直接覆盖插入记录(待分析)

                             >>当modify=0时:

                               1)当mode=BTR_MODIFY_LEAF时,调用btr_cur_optimistic_insert,尝试向一个索引page中插入记录,如果页面空闲空间太小,则返回失败

                                   |–>btr_cur_ins_lock_and_undo //检查是否有锁冲突,并插入undolog

                                         |–>lock_rec_insert_check_and_lock //检查锁冲突

                                               |–>没有下一个记录的锁冲突,即lock_rec_get_first返回NULL,更新二级索引trx id,返回

                                               |–>调用lock_rec_other_has_conflicting,检查是否有其他事务锁有下一个记录的LOCK_X, LOCK_GAP和LOCK_INSERT_INTENTION锁

                                               |–>检测到有冲突lock_rec_enqueue_waiting

                                                       |–> 创建锁记录lock_rec_create,type_code为LOCK_X | LOCK_GAP|LOCK_INSERT_INTENTION

                                                       |–>检测死锁

                                         |–>如果是聚集索引且不是Insert buffer

                                               |–>写入undo信息 trx_undo_report_row_operation(待分析)

                                               |–>设置聚集索引记录的trx id和回滚段指针,row_upd_index_entry_sys_field

                                    |–>插入记录page_cur_tuple_insert

                                    |–>更新该page的哈希索引btr_search_update_hash_on_insert(待分析)

                                    |–>继承下一条记录的gap锁?(inherit为TRUE),调lock_update_insert,这里不调用 (待分析) 

                                 2)否则

                                    a)调用buf_LRU_buf_pool_running_out,返回true,表示少于25%的buffer pool可用。根据注释,对于大事务,会将锁存储在buffer pool中(待证实)

                                    b)调用btr_cur_pessimistic_insert(待分析)

           

drop table t1;

CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;

insert into t1 values (1,2);

insert into t1 values (1,5) on duplicate key update b = b+1;

————————————————-

函数调用逻辑:

write_record->handler::ha_write_row->ha_innobase::write_row->

row_insert_for_mysql

     —->row_ins_step->row_ins->row_ins_index_entry

          |–>row_ins_index_entry_low

             |–>调用row_ins_duplicate_error_in_clust检测是否有dup key错误。

                   |–>对记录加锁

                      >>对于REPLACE, LOAD DATAFILE REPLACE以及INSERT ON DUPLICATE KEY UPDATE操作,对记录加一个排他锁(LOCK_X)row_ins_set_exclusive_rec_lock

                            a)聚集索引lock_clust_rec_read_check_and_lock

                            b)二级索引lock_sec_rec_read_check_and_lock

                      >>否则,加一个共享锁(LOCK_S)row_ins_set_shared_rec_lock

                   |–>调用row_ins_dupl_error_with_rec检查物理记录和将要插入的记录是否相同


从Innodb层返回到Server层后,write_record函数根据返回的错误值,继续下面的逻辑

|–>判断是否是dup key错误

|–>if (table->file->extra(HA_EXTRA_FLUSH_CACHE))    //  bug#52020相关点,稍后再议

|–>一堆乱七八糟的检查,构建记录等….

|–>row_update_for_mysql传递record到innodb更新数据

     |–>row_upd_step->row_upd

       |–>row_upd_clust_step

          |–>如果没有x锁,则尝试加锁lock_clust_rec_modify_check_and_lock

          |–>row_upd_clust_rec(待分析)

                   |–>btr_cur_optimistic_update


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
8月前
|
Ubuntu 关系型数据库 MySQL
MySQL源码编译安装
本文详细介绍了MySQL 8.0及8.4版本的源码编译安装全过程,涵盖用户创建、依赖安装、cmake配置、编译优化等步骤,并提供支持多Linux发行版的一键安装脚本,适用于定制化数据库部署需求。
2099 4
MySQL源码编译安装
|
10月前
|
NoSQL 关系型数据库 MySQL
在Visual Studio Code中设置MySQL源码调试环境
以上步骤涵盖了在VS Code中设置MySQL源码调试环境的主要过程,是一个相对高级的任务,旨在为希望建立强大开发和调试环境的开发者提供指引。遵循这些步骤,将可以利用VS Code强大的编辑和调试功能来深入理解和改进MySQL数据库的底层实现。
668 0
|
关系型数据库 MySQL PHP
源码编译安装LAMP(HTTP服务,MYSQL ,PHP,以及bbs论坛)
通过以上步骤,你可以成功地在一台Linux服务器上从源码编译并安装LAMP环境,并配置一个BBS论坛(Discuz!)。这些步骤涵盖了从安装依赖、下载源代码、配置编译到安装完成的所有细节。每个命令的解释确保了过程的透明度,使即使是非专业人士也能够理解整个流程。
489 18
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
649 1
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,并与使用 RPM 包安装进行了对比
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,并与使用 RPM 包安装进行了对比。通过具体案例,读者可以了解如何准备环境、下载源码、编译安装、配置服务及登录 MySQL。编译源码安装虽然复杂,但提供了更高的定制性和灵活性,适用于需要高度定制的场景。
836 3
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
1569 2
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤
【10月更文挑战第7天】本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据自身需求选择合适的方法。
626 3
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置服务等,并与使用 RPM 包安装进行了对比,帮助读者根据需求选择合适的方法。编译源码安装虽然复杂,但提供了更高的定制性和灵活性。
666 2
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
483 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
SQL 关系型数据库 MySQL
SQL语句编写的练习(MySQL)
这篇文章提供了MySQL数据库中关于学生表、课程表、成绩表和教师表的建表语句、数据插入示例以及一系列SQL查询练习,包括查询、排序、聚合和连接查询等操作。