天津做网站联系方式,wordpress怎么上传产品,技术支持 昆明网站建设,想自己做网站推广最近在mysql 8.0的代码上开发新的功能的时候#xff0c;梳理了insert语句的执行过程#xff0c;由于insert语句比较复杂并且涉及的内容很多#xff0c;在下面准备分3章节来分析#xff0c;这是第一个章节#xff0c;主要讲述sql解析和命令的分发部分。
代码版本#xff…最近在mysql 8.0的代码上开发新的功能的时候梳理了insert语句的执行过程由于insert语句比较复杂并且涉及的内容很多在下面准备分3章节来分析这是第一个章节主要讲述sql解析和命令的分发部分。
代码版本mysql 8.0.22
编程语言c c11 c14 c17
SQL语句是create table test(c1 int primary key, c2 varchar(50))engineinnodb;insert into test values(1,abc);
执行分类接口
源码开始位置在/sql/sql_parse.h 和 /sql/sql_parse.ccsql_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之前的一些格式转换和初步的数据插入。