日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

發布時間:2023/12/20 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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之前的一些格式轉換和初步的數據插入。

總結

以上是生活随笔為你收集整理的mysql 8.0 一条insert语句的具体执行流程分析(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。