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

最近在mysql 8.0的代码上开发新的功能的时候,梳理了insert语句的执行过程,由于insert语句比较复杂并且涉及的内容很多,在下面准备分3章节来分析,这是第一个章节,主要讲述sql解析和命令的分发部分。

代码版本:mysql 8.0.22

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

SQL语句是:create table test(c1 int primary key, c2 varchar(50))engine=innodb;insert into test values(1,"abc");

执行分类接口

源码开始位置在/sql/sql_parse.h 和 /sql/sql_parse.cc,sql_parse.cc是一个超大的文件,里面包括了很多个超大的函数,下面按sql执行顺序讲述:

| > do_command
| | > dispatch_command
| | | > mysql_parse(parse_sql)
| | | | > mysql_execute_command --> lex->m_sql_cmd->execute(thd)
| | | | | > thd->send_statement_status() // 检查当前sql的状态

 

1、do_command:从客户端connection到mysql server之后,接收到sql命令的入口

bool do_command(THD *thd) {bool return_value;int rc;NET *net = nullptr;enum enum_server_command command;COM_DATA com_data;DBUG_TRACE;DBUG_ASSERT(thd->is_classic_protocol());/*indicator of uninitialized lex => normal flow of errors handling(see my_message_sql)*/thd->lex->set_current_select(nullptr);/*XXX: this code is here only to clear possible errors of init_connect.Consider moving to prepare_new_connection_state() instead.That requires making sure the DA is cleared before non-parsing statementssuch as COM_QUIT.*/thd->clear_error();  // Clear error messagethd->get_stmt_da()->reset_diagnostics_area();thd->updated_row_count = 0;thd->busy_time = 0;thd->cpu_time = 0;thd->bytes_received = 0;thd->bytes_sent = 0;thd->binlog_bytes_written = 0;......return_value = dispatch_command(thd, &com_data, command);thd->get_protocol_classic()->get_output_packet()->shrink(thd->variables.net_buffer_length);out:/* The statement instrumentation must be closed in all cases. */DBUG_ASSERT(thd->m_digest == nullptr);DBUG_ASSERT(thd->m_statement_psi == nullptr);return return_value;
}

2、dispatch_command: 按照不同的SQL进行分类

    case COM_QUERY: {DBUG_ASSERT(thd->m_digest == nullptr);thd->m_digest = &thd->m_digest_state;thd->m_digest->reset(thd->m_token_array, max_digest_length);if (alloc_query(thd, com_data->com_query.query,com_data->com_query.length))break;  // fatal error is setconst char *packet_end = thd->query().str + thd->query().length;if (opt_general_log_raw)query_logger.general_log_write(thd, command, thd->query().str,thd->query().length);DBUG_PRINT("query", ("%-.4096s", thd->query().str));#if defined(ENABLED_PROFILING)thd->profiling->set_query_source(thd->query().str, thd->query().length);
#endifconst LEX_CSTRING orig_query = thd->query();Parser_state parser_state;if (parser_state.init(thd, thd->query().str, thd->query().length)) break;// Initially, prepare and optimize the statement for the primary// storage engine. If an eligible secondary storage engine is// found, the statement may be reprepared for the secondary// storage engine later.const auto saved_secondary_engine = thd->secondary_engine_optimization();thd->set_secondary_engine_optimization(Secondary_engine_optimization::PRIMARY_TENTATIVELY);mysql_parse(thd, &parser_state, false);......

3、mysql_parse(parse_sql):从文本字符串中解析输入的SQL,将解析出的AST树传给执行者

void mysql_parse(THD *thd, Parser_state *parser_state, bool update_userstat) {DBUG_TRACE;DBUG_PRINT("mysql_parse", ("query: '%s'", thd->query().str));DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););mysql_reset_thd_for_next_command(thd);lex_start(thd);bool err = thd->get_stmt_da()->is_error();if (!err) {err = parse_sql(thd, parser_state, nullptr);......error = mysql_execute_command(thd, true);
}

 

4、mysql_execute_command: 按照不同的SQL分类,进入不同的执行流程

switch (lex->sql_command) {case SQLCOM_PREPARE: {mysql_sql_stmt_prepare(thd);break;}case SQLCOM_EXECUTE: {mysql_sql_stmt_execute(thd);break;}case SQLCOM_DEALLOCATE_PREPARE: {mysql_sql_stmt_close(thd);break;}......case SQLCOM_REPLACE:case SQLCOM_INSERT:case SQLCOM_REPLACE_SELECT:case SQLCOM_INSERT_SELECT:case SQLCOM_DELETE:case SQLCOM_DELETE_MULTI:case SQLCOM_UPDATE:case SQLCOM_UPDATE_MULTI:case SQLCOM_CREATE_TABLE:case SQLCOM_CREATE_INDEX:case SQLCOM_DROP_INDEX:case SQLCOM_ASSIGN_TO_KEYCACHE:case SQLCOM_PRELOAD_KEYS:case SQLCOM_LOAD: {DBUG_ASSERT(first_table == all_tables && first_table != nullptr);DBUG_ASSERT(lex->m_sql_cmd != nullptr);res = lex->m_sql_cmd->execute(thd);break;}     
}

数据插入接口

数据插入部分在sql/sql_insert.cc中,执行的顺序如下:

| > Sql_cmd_dml::execute 
| | > write_record  

1、Sql_cmd_dml::execute : 向一个表中插入一行或多行,执行一个DML语句,这里是insert into test values(1,"abc");

bool Sql_cmd_dml::execute(THD *thd) {DBUG_TRACE;// Perform statement-specific executionif (execute_inner(thd)) goto err;......
}

2、write_record : 在sql_insert.cc中,功能:向表中写入一条记录,可选择删除冲突的记录。

如果需要,调用适当的触发器,参数如下:

THD *thd : 当前thread的上下文 TABLE *table : 该条record要插入到的table COPY_INFO *info : 用来处理唯一键冲突,记录影响行数 COPY_INFO *update : 处理 INSERT ON DUPLICATE KEY UPDATE 相关信息

bool write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update) {...store_record(table, insert_values);...
}

 

这一章节主要讲述sql解析、命令的分发、进入innodb存储引擎之前的sql转换等。第二章节主要讲述sql命令传递给innodb之前的一些格式转换和初步的数据插入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开发高级 Web 部件

通过用户控件实现 Web 部件相当容易,但是也有一些弊端: 受限的重用:如果不手动复制 .ascx 文件到其他 Web 应用程序的目录下,就不能动态添加这些控件到其他 Web 应用程序的页面中。 受限的个性化:用户控件的个性化仅限…

强一致性和弱一致性的区别

一致性包括强一致性和弱一致性: 弱一致性:可以理解为CAP定律中的不一致现象。但是经过一定的时间会达到最终一致性 强一致性: 包含线性一致性和顺序一致性。 因此强一致性不一定是线性一致性,但线性一致性一定是强一致性

Juqery Html(),append()等方法的Bug

标题中说是jquery中的Bug,只是个人这么认为,先申明一下! 这几天在做动态加载图片热区,我用Ajax获取到了area标签,这里有多个area,在IE8和FF里测试正常,可一到IE7,和IE6里面就显示不正常了。后来发现jquery中…

Cantor定理的一种好表述

今天我在A course on Borel sets 一书中看到了Cantor定理的一种好表述.我很喜欢这种表述.在很多书中,康托定理是这样表述的: 自然数集合的所有子集形成的集合是不可数集. 也有这样表述的: $2^{\mathbb{N}}$是不可数集. 不过在A course on Borel sets 中…

分页类与前台和后台的调用方法

using System;using System.Text; namespace WebDemo.Common{ public class LaomaPager { /// <summary> /// /// </summary> /// <param name"pageSize">一页多少条</param> /// <param name"currentPage">当前页</par…

MySQL中rename一个view对应的SQL语句

OS&#xff1a;linux ubuntu 最近在对MySQL数据库开发的过程中&#xff0c;需要修改一个view的名字&#xff0c;但是找了许久才找到对应的SQL&#xff0c;切记不是alter&#xff0c;而是rename table .... 在MySQL中&#xff0c;如果想要rename 视图的名字&#xff0c;需要使用…

SharePoint2007 配置MOSS基于AD的Forms验证

公司上边要求使用Forms验证方式登陆到MOSS系统 于是经过研究测试成功了, 这次上边又要求用户必须为AD用户 查了很多资料 经过了一番周折 终于测试成功了,无奈网上文章转载的太多, 差错太多,特将本人亲自测试的具体步骤贴出来 与大家一起进步 有什么不对的地方 还希望多提出宝贵…

ubuntu 12.04 nginx+ mono-fastcgi-server

mono是.NET在Linux下的的开源实现&#xff0c; 主要的运行方式分为两种apache mod_mononginx fastcgi (mono)考虑到nginx性能更好&#xff0c;这里讲述第二种实现方法因为Ubuntu 提供了完整的mono软件包支持&#xff0c;因此本文尝试在Ubuntu 12.04下搭建安装mono和fastcgi-s…

std::make_unique<T>和std::make_shared<T>

更建议使用&#xff1a;std::make_unique<T>构造unique_ptr对象&#xff1b;std::make_shared<T>构造shared_ptr对象 std::make_shared是C11的一部分&#xff0c;std::make_unique不是&#xff0c;它在C14才纳入标准库。如果你使用的是C11&#xff0c;不用忧伤&…

maven 聚合工程 用spring boot 搭建 spring cloud 微服务 模块式开发项目

项目的简单介绍: 项目采用maven聚合工程 用spring boot 搭建 spring cloud的微服务 模块式开发 项目的截图: 搭建开始: 能上图 我少打字 1.首先搭建maven的聚合工程 1.1创建聚合工程的父模块 1.2设置父模块的POM文件 主要是配置 spring boot版本&#xff0c;spring cloud 版本&…

Cheatsheet: 2010 12.13 ~ 12.23

Web Slow Website? 6 Ways to Speed it Up MongoDB Monitoring: Keep in it RAM Minify JavaScript on the fly - Cached JavaScript minification on the fly – ASP.NET and HttpHandler What To Do When Your Website Goes Down Methods to hide email addresses from page…

epoll原理详解

原文链接&#xff1a;https://blog.csdn.net/daaikuaichuan/article/details/83862311 设想一个场景&#xff1a;有100万用户同时与一个进程保持着TCP连接&#xff0c;而每一时刻只有几十个或几百个TCP连接是活跃的(接收TCP包)&#xff0c;也就是说在每一时刻进程只需要处理这…

使用loadrunner编写webservice接口请求

1、使用工具&#xff1a; loadrunner12&#xff0c;本实例截图中都是loadrunner12工具 2、操作步骤&#xff1a; 1)、新建脚本&#xff0c;选择Web Services协议&#xff1a; 2)、选择工具栏&#xff1a; 3)、点击Import&#xff0c;输入wsdl地址&#xff1a;测试代码用的地址&…

C#格式化字符串净化代码的方法

C#格式化字符串净化代码的方法&#xff0c;在C#编程中&#xff0c;字符串类型是最容易处理出错的地方&#xff0c;其代价往往也很昂贵&#xff0c;在.NET Framework中&#xff0c;字符串是一个不可变的类型&#xff0c;当一个字符串被修改后&#xff0c;总是创建一个新的副本&a…

实验二《Java面向对象程序设计》实验报告

一、实验内容 初步掌握单元测试和TDD理解并掌握面向对象三要素&#xff1a;封装、继承、多态初步掌握UML建模熟悉S.O.L.I.D原则了解设计模式 二、实验步骤 &#xff08;一&#xff09;单元测试 1.三种代码&#xff1a;伪代码、测试代码、产品代码需求&#xff1a;在一个MyUtil类…

Java 包装类 自动装箱和拆箱

包装类&#xff08;Wrapper Class&#xff09; 包装类是针对于原生数据类型的包装。 因为有8个原生数据类型&#xff0c;所以对应有8个包装类。 所有的包装类&#xff08;8个&#xff09;都位于java.lang下。 Java中的8个包装类分别是&#xff1a;Byte, Short, Integer, Long, …

Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结

知识背景&#xff1a; 210.25.132.181属于IP地址的ASCII表示法&#xff0c;也就是字符串形式。英语叫做IPv4 numbers-and-dots notation。 如果把210.25.132.181转换为整数形式&#xff0c;是3524887733&#xff0c;这个就是整数形式的IP地址。英语叫做binary data。&#xff0…

MySQL中alter table range partition

最近在用MySQL开发新功能时&#xff0c;使用到了alter table range partition的功能&#xff0c;在此总结下mysql innodb支持的alter table range partition相关功能。mysql的版本是8.0.22, os: linux ubuntu 对alter range partition的操作主要由以下几个&#xff1a; analy…

可恶,谁占用了我的80端口?

下午在室友的本本上上网&#xff0c;突然想看一个新闻系统&#xff0c;他的本上没有安装环境&#xff0c;于是下载一个wamp,安装。运行wamp&#xff0c;晕...怎么只有1个服务在运行&#xff0c;导致我的localhost打不开&#xff0c;看了一下mysql服务运行正常&#xff0c;apach…

laravel命令

新建控制器 php artisan make:controller IssuesController 新建控制器并自动生成对应RESTful风格路由相关CURD方法 php artisan make:controller IssuesController -r 新建一个迁移文件 php artisan make:migration create_issues_table --createissues 回滚上一次迁移的内容 …