mysql 主要脉络 (看c/c++ 建议使用QT)
文件 | 函数 |
1.sql->mysqld.cc(这是整个MySQL的入口) | mysqld_socket_acceptor->connection_event_loop(); |
2.sql/conn_handler->connection_handler_manager.cc | m_connection_handler->add_connection(channel_info) |
3.sql/conn_handler->connection_handler_per_thread.cc | error= mysql_thread_create(key_thread_one_connection, &id, &connection_attrib, handle_connection, (void*) channel_info); |
4.sql->sql_parse.cc | do_command(thd) |
5.sql->sql_parse.cc | return_value= dispatch_command(thd, &com_data, command); |
6.sql->sql_parse.cc | mysql_parse(thd, &parser_state); |
7.sql->sql_parse.cc | error= mysql_execute_command(thd, true); |
8.sql->sql_parse.cc | res= execute_sqlcom_select(thd, all_tables); |
9.sql->sql_parse.cc | res= handle_query(thd, lex, result, 0, 0); select->join->exec(); |
10.sql->sql_select.cc | select->join->exec(); |
extern "C" void *handle_connection(void *arg)
{
...
{
while (thd_connection_alive(thd))
{
if (do_command(thd))
break;
}
end_connection(thd);
}
....
}
bool dispatch_command(THD *thd, const COM_DATA *com_data,enum enum_server_command command) { ... switch (command) { case COM_INIT_DB: { ... 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); 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 MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query().str, thd->query().length); Parser_state parser_state; if (parser_state.init(thd, thd->query().str, thd->query().length)) break; mysql_parse(thd, &parser_state); while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) { /* Multiple queries exits, execute them individually */ const char *beginning_of_next_stmt= parser_state.m_lip.found_semicolon; /* Finalize server status flags after executing a statement. */ thd->update_server_status(); thd->send_statement_status(); query_cache.end_of_result(thd); #ifndef EMBEDDED_LIBRARY mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS, thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->mysql_errno() : 0, command_name[command].str); #endif size_t length= static_cast<size_t>(packet_end - beginning_of_next_stmt); log_slow_statement(thd); /* Remove garbage at start of query */ while (length > 0 && my_isspace(thd->charset(), *beginning_of_next_stmt)) { beginning_of_next_stmt++; length--; } /* PSI end */ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); thd->m_statement_psi= NULL; thd->m_digest= NULL; /* DTRACE end */ if (MYSQL_QUERY_DONE_ENABLED()) { MYSQL_QUERY_DONE(thd->is_error()); } /* SHOW PROFILE end */ #if defined(ENABLED_PROFILING) thd->profiling.finish_current_query(); #endif /* SHOW PROFILE begin */ #if defined(ENABLED_PROFILING) thd->profiling.start_new_query("continuing"); thd->profiling.set_query_source(beginning_of_next_stmt, length); #endif /* DTRACE begin */ MYSQL_QUERY_START(const_cast<char*>(beginning_of_next_stmt), 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); /* PSI begin */ thd->m_digest= & thd->m_digest_state; thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, com_statement_info[command].m_key, thd->db().str, thd->db().length, thd->charset(), NULL); THD_STAGE_INFO(thd, stage_starting); MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt, length); thd->set_query(beginning_of_next_stmt, length); thd->set_query_id(next_query_id()); /* Count each statement from the client. */ thd->status_var.questions++; thd->set_time(); /* Reset the query start time. */ parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ mysql_parse(thd, &parser_state); } /* Need to set error to true for graceful shutdown */ if((thd->lex->sql_command == SQLCOM_SHUTDOWN) && (thd->get_stmt_da()->is_ok())) error= TRUE; DBUG_PRINT("info",("query ready")); break; } ... thd->send_statement_status(); //网络返回 thd->rpl_thd_ctx.session_gtids_ctx().notify_after_response_packet(thd); query_cache.end_of_result(thd); ... }