Skip to content

Latest commit

 

History

History
196 lines (189 loc) · 8.47 KB

MySQL Query.md

File metadata and controls

196 lines (189 loc) · 8.47 KB

mysql-server版本: 5.7.24

MySQL一条query的执行过程

(gdb) bt
#0  ha_innobase::index_first (this=0x7fff9801a780, buf=0x7fff9801ab90 "") at /root/mysql-server/storage/innobase/handler/ha_innodb.cc:9141
#1  0x0000000001983b29 in ha_innobase::rnd_next (this=0x7fff9801a780, buf=0x7fff9801ab90 "") at /root/mysql-server/storage/innobase/handler/ha_innodb.cc:9243
#2  0x0000000000f2be6f in handler::ha_rnd_next (this=0x7fff9801a780, buf=0x7fff9801ab90 "") at /root/mysql-server/sql/handler.cc:2947
#3  0x0000000001458e24 in rr_sequential (info=0x7fff9801cc48) at /root/mysql-server/sql/records.cc:510
#4  0x00000000014f0c44 in join_init_read_record (tab=0x7fff9801cbf8) at /root/mysql-server/sql/sql_executor.cc:2484
#5  0x00000000014ede81 in sub_select (join=0x7fff9801c630, qep_tab=0x7fff9801cbf8, end_of_records=false) at /root/mysql-server/sql/sql_executor.cc:1277
#6  0x00000000014ed814 in do_select (join=0x7fff9801c630) at /root/mysql-server/sql/sql_executor.cc:950
#7  0x00000000014eb77b in JOIN::exec (this=0x7fff9801c630) at /root/mysql-server/sql/sql_executor.cc:199
#8  0x000000000158460e in handle_query (thd=0x7fff98000b70, lex=0x7fff98002e88, result=0x7fff980070d0, added_options=0, removed_options=0) at /root/mysql-server/sql/sql_select.cc:184
#9  0x000000000153a41f in execute_sqlcom_select (thd=0x7fff98000b70, all_tables=0x7fff980067c8) at /root/mysql-server/sql/sql_parse.cc:5144
#10 0x0000000001533e3d in mysql_execute_command (thd=0x7fff98000b70, first_level=true) at /root/mysql-server/sql/sql_parse.cc:2816
#11 0x000000000153b382 in mysql_parse (thd=0x7fff98000b70, parser_state=0x7fffdc37f690) at /root/mysql-server/sql/sql_parse.cc:5570
#12 0x0000000001530c93 in dispatch_command (thd=0x7fff98000b70, com_data=0x7fffdc37fdf0, command=COM_QUERY) at /root/mysql-server/sql/sql_parse.cc:1484
#13 0x000000000152fafc in do_command (thd=0x7fff98000b70) at /root/mysql-server/sql/sql_parse.cc:1025
#14 0x0000000001660328 in handle_connection (arg=0x3659310) at /root/mysql-server/sql/conn_handler/connection_handler_per_thread.cc:300
#15 0x00000000018f73b9 in pfs_spawn_thread (arg=0x359f900) at /root/mysql-server/storage/perfschema/pfs.cc:2190
#16 0x00007ffff7bc6dc5 in start_thread () from /lib64/libpthread.so.0
#17 0x00007ffff668321d in clone () from /lib64/libc.so.6
|connection_handler_per_thread.cc	sql_parse.cc				sql_select.cc		sql_resolver.cc		sql_optimizer.cc	sql_executor.cc	records.cc	handler.cc	ha_innodb.cc
|-----------------------------------|---------------------------|-------------------|-------------------|-------------------|---------------|-----------|-----------
|handle_connection					|							|					|					|					|				|			|				
|-do_command						|							|					|					|					|				|			|			
|									|dispatch_command			|					|					|					|				|			|			
|									|mysql_parse				|					|					|					|				|			|			
|									|-parse_sql					|					|					|					|				|			|			
|									|-mysql_execute_command		|					|					|					|				|			|			
|									|--execute_sqlcom_select	|					|					|					|				|			|			
|									|							|handle_query		|					|					|				|			|			
|									|							|-prepare			|					|					|				|			|			
|									|							|					|SELECT_LEX::prepare|					|				|			|			
|									|							|-optimize			|					|					|				|			|			
|									|							|					|					|JOIN::optimize()	|				|			|			
|									|							|-JOIN::exec		|					|					|				|			|
|									|							|					|					|					|				|			|

sql_parse.cc```cpp /** Perform one connection-level (COM_XXXX) command. @param thd connection handle @param command type of command to perform @com_data com_data union to store the generated command @todo set thd->lex->sql_command to SQLCOM_END here. @todo The following has to be changed to an 8 byte integer @retval 0 ok @retval 1 request of thread shutdown, i. e. if command is COM_QUIT/COM_SHUTDOWN */ bool dispatch_command(THD *thd, const COM_DATA com_data, enum enum_server_command command) { // ... ... switch (command) { // .... ... case COM_QUERY: { DBUG_ASSERT(thd->m_digest == NULL); thd->m_digest= & thd->m_digest_state; thd->m_digest->reset(thd->m_token_array, max_digest_length);   // Read query from packet and store in thd->query. Used in COM_QUERY and COM_STMT_PREPARE. if (alloc_query(thd, com_data->com_query.query, com_data->com_query.length)) break; // fatal error is set MYSQL_QUERY_START(const_cast<char>(thd->query().str), thd->thread_id(), (char *) (thd->db().str ? thd->db().str : ""), (char *) thd->security_context()->priv_user().str, (char *) thd->security_context()->host_or_ip().str); const 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); #endif Parser_state parser_state; if (parser_state.init(thd, thd->query().str, thd->query().length)) break; mysql_parse(thd, &parser_state); // ... ... } // ... ... } // ... ... }


```cpp
/*
  When you modify mysql_parse(), you may need to mofify
  mysql_test_parse_for_slave() in this same file.
*/
/**
  Parse a query.
  @param       thd     Current thread
  @param       rawbuf  Begining of the query text
  @param       length  Length of the query text
  @param[out]  found_semicolon For multi queries, position of the character of
                               the next query in the query text.
*/
void mysql_parse(THD *thd, Parser_state *parser_state)
{
  int error MY_ATTRIBUTE((unused));
  DBUG_ENTER("mysql_parse");
  DBUG_PRINT("mysql_parse", ("query: '%s'", thd->query().str));
  DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
  /*
    Warning.
    The purpose of query_cache_send_result_to_client() is to lookup the
    query in the query cache first, to avoid parsing and executing it.
    So, the natural implementation would be to:
    - first, call query_cache_send_result_to_client,
    - second, if caching failed, initialise the lexical and syntactic parser.
    The problem is that the query cache depends on a clean initialization
    of (among others) lex->safe_to_cache_query and thd->server_status,
    which are reset respectively in
    - lex_start()
    - mysql_reset_thd_for_next_command()
    So, initializing the lexical analyser *before* using the query cache
    is required for the cache to work properly.
    FIXME: cleanup the dependencies in the code to simplify this.
  */
  mysql_reset_thd_for_next_command(thd);
  lex_start(thd);
  thd->m_parser_state= parser_state;
  invoke_pre_parse_rewrite_plugins(thd);
  thd->m_parser_state= NULL;
  enable_digest_if_any_plugin_needs_it(thd, parser_state);
  // 先去缓存里查,但因为缓存是只要有update就全部失效,一般不开启,这里可以忽略缓存
  if (query_cache.send_result_to_client(thd, thd->query()) <= 0)
  {
    LEX *lex= thd->lex;
    const char *found_semicolon;
    bool err= thd->get_stmt_da()->is_error();
    if (!err)
    {
      err= parse_sql(thd, parser_state, NULL);
      if (!err)
        err= invoke_post_parse_rewrite_plugins(thd, false);
      found_semicolon= parser_state->m_lip.found_semicolon;
    }
	// ... ...
  }
  // ... ...
}
/**
  Execute command saved in thd and lex->sql_command.
  @param thd                       Thread handle
  @todo
    - Invalidate the table in the query cache if something changed
    after unlocking when changes become visible.
    @todo: this is workaround. right way will be move invalidating in
    the unlock procedure.
    - TODO: use check_change_password()
  @retval
    FALSE       OK
  @retval
    TRUE        Error
*/
int
mysql_execute_command(THD *thd, bool first_level)
{
  // ... ...
  switch (lex->sql_command) {
  // ... ...
  case SQLCOM_SHOW_COLLATIONS:
  case SQLCOM_SHOW_STORAGE_ENGINES:
  case SQLCOM_SHOW_PROFILE:
  case SQLCOM_SELECT:
  {
    DBUG_EXECUTE_IF("use_attachable_trx",
                    thd->begin_attachable_ro_transaction(););
    thd->clear_current_query_costs();
    res= select_precheck(thd, lex, all_tables, first_table);
    if (!res)
      res= execute_sqlcom_select(thd, all_tables);
  // ... ...
}

https://blog.csdn.net/vipshop_fin_dev/article/details/79688717