mysql8 用C++源码角度看客户端发起sql网络请求,并处理sql命令

MySQL 8 的 C++ 源码中,处理网络请求和 SQL 命令的流程涉及多个函数和类。以下是关键的函数和类,以及它们的作用:

1. do_command 函数

do_command 函数是 MySQL 服务器中处理客户端命令的核心函数。它从客户端读取一个命令并执行。这个函数在 sql/sql_parse.cc 文件中定义。

函数原型

cpp复制

bool do_command(THD *thd);
主要步骤
  1. 初始化

    • 清除可能的错误状态。

    • 设置线程的当前查询块为空。

    • 清除错误消息和诊断区域。

  2. 读取命令

    • 设置网络读取超时。

    • 调用 thd->get_protocol()->get_command 从客户端读取命令。

  3. 处理命令

    • 如果读取命令失败,处理错误并返回。

    • 否则,调用 dispatch_command 处理具体的命令。

  4. 清理

    • 无论成功还是失败,清理线程的资源和状态。

2. dispatch_command 函数

dispatch_command 函数根据客户端发送的命令类型(如 COM_QUERYCOM_STMT_PREPARE 等)调用相应的处理函数。这个函数也在 sql/sql_parse.cc 文件中定义。

函数原型

cpp复制

bool dispatch_command(THD *thd, COM_DATA *com_data, enum enum_server_command command);
主要步骤
  1. 检查命令类型

    • 根据命令类型调用相应的处理函数。例如:

      • COM_QUERY:调用 mysql_parse 解析和执行 SQL 查询。

      • COM_STMT_PREPARE:调用 mysql_parse 解析和准备预处理语句。

      • COM_QUIT:处理客户端断开连接。

  2. 执行命令

    • 调用相应的处理函数执行命令。

  3. 返回结果

    • 返回命令执行的结果。

3. handle_connection 函数

handle_connection 函数是处理新连接的线程函数。它在 sql/sql_connect.cc 文件中定义。这个函数负责初始化新连接的线程,并调用 do_command 处理客户端命令。

函数原型

cpp复制

extern "C" void *handle_connection(void *arg);
主要步骤
  1. 初始化线程

    • 初始化线程的资源和状态。

    • 设置线程的 TLS(线程局部存储)。

  2. 处理连接

    • 调用 do_command 处理客户端命令。

    • 如果客户端断开连接,清理线程的资源。

  3. 清理线程

    • 释放线程的资源。

    • 退出线程。

4. Connection_handler_manager 类

Connection_handler_manager 类负责管理连接处理程序。它在 sql/sql_connect.cc 文件中定义。这个类的主要职责包括:

  • 接受新的连接。

  • 创建新的线程来处理连接。

  • 管理连接的生命周期。

主要方法
  • process_new_connection:处理新的连接。

  • add_connection:将新的连接添加到连接处理程序中。

##

/**Read one command from connection and execute it (query or simple command).This function is called in loop from thread function.For profiling to work, it must never be called recursively.@retval0  success@retval1  request of thread shutdown (see dispatch_command() description)
*/bool do_command(THD *thd) {bool return_value;int rc;NET *net = nullptr;enum enum_server_command command = COM_SLEEP;COM_DATA com_data;DBUG_TRACE;assert(thd->is_classic_protocol());/*indicator of uninitialized lex => normal flow of errors handling(see my_message_sql)*/thd->lex->set_current_query_block(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();/*This thread will do a blocking read from the client whichwill be interrupted when the next command is received fromthe client, the connection is closed or "net_wait_timeout"number of seconds has passed.*/net = thd->get_protocol_classic()->get_net();my_net_set_read_timeout(net, thd->variables.net_wait_timeout);net_new_transaction(net);/*WL#15369 : to make connections threads sleep to test ifER_THREAD_STILL_ALIVE, and ER_NUM_THREADS_STILL_ALIVE arebeing logged in the intended way, i.e. when connection threadsare still alive, even after forcefully disconnecting them inclose_connections().*/DBUG_EXECUTE_IF("simulate_connection_thread_hang", sleep(15););/*Synchronization point for testing of KILL_CONNECTION.This sync point can wait here, to simulate slow code executionbetween the last test of thd->killed and blocking in read().The goal of this test is to verify that a connection does nothang, if it is killed at this point of execution.(Bug#37780 - main.kill fails randomly)Note that the sync point wait itself will be terminated by akill. In this case it consumes a condition broadcast, but doesnot change anything else. The consumed broadcast should notmatter here, because the read/recv() below doesn't use it.*/DEBUG_SYNC(thd, "before_do_command_net_read");/* For per-query performance counters with log_slow_statement */struct System_status_var query_start_status;thd->clear_copy_status_var();if (opt_log_slow_extra) {thd->copy_status_var(&query_start_status);}rc = thd->m_mem_cnt.reset();if (rc)thd->m_mem_cnt.set_thd_error_status();else {/*Because of networking layer callbacks in place,this call will maintain the following instrumentation:- IDLE events- SOCKET events- STATEMENT events- STAGE eventswhen reading a new network packet.In particular, a new instrumented statement is started.See init_net_server_extension()*/thd->m_server_idle = true;rc = thd->get_protocol()->get_command(&com_data, &command);thd->m_server_idle = false;}if (rc) {
#ifndef NDEBUGchar desc[VIO_DESCRIPTION_SIZE];vio_description(net->vio, desc);DBUG_PRINT("info", ("Got error %d reading command from socket %s",net->error, desc));
#endif  // NDEBUGMYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);/* Instrument this broken statement as "statement/com/error" */thd->m_statement_psi = MYSQL_REFINE_STATEMENT(thd->m_statement_psi, com_statement_info[COM_END].m_key);/* Check if we can continue without closing the connection *//* The error must be set. */assert(thd->is_error());thd->send_statement_status();/* Mark the statement completed. */MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());thd->m_statement_psi = nullptr;thd->m_digest = nullptr;if (rc < 0) {return_value = true;  // We have to close it.goto out;}net->error = NET_ERROR_UNSET;return_value = false;goto out;}#ifndef NDEBUGchar desc[VIO_DESCRIPTION_SIZE];vio_description(net->vio, desc);DBUG_PRINT("info", ("Command on %s = %d (%s)", desc, command,Command_names::str_notranslate(command).c_str()));expected_from_debug_flag = TDM::ANY;DBUG_EXECUTE_IF("tdon", { expected_from_debug_flag = TDM::ON; });DBUG_EXECUTE_IF("tdzero", { expected_from_debug_flag = TDM::ZERO; });DBUG_EXECUTE_IF("tdna", { expected_from_debug_flag = TDM::NOT_AVAILABLE; });
#endif  // NDEBUGDBUG_PRINT("info", ("packet: '%*.s'; command: %d",(int)thd->get_protocol_classic()->get_packet_length(),thd->get_protocol_classic()->get_raw_packet(), command));if (thd->get_protocol_classic()->bad_packet)assert(0);  // Should be caught earlier// Reclaim some memorythd->get_protocol_classic()->get_output_packet()->shrink(thd->variables.net_buffer_length);/* Restore read timeout value */my_net_set_read_timeout(net, thd->variables.net_read_timeout);DEBUG_SYNC(thd, "before_command_dispatch");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. */assert(thd->m_digest == nullptr);assert(thd->m_statement_psi == nullptr);return return_value;
}

##

/**Perform one connection-level (COM_XXXX) command.@param thd             connection handle@param command         type of command to perform@param com_data        com_data union to store the generated command@todoset thd->lex->sql_command to SQLCOM_END here.@todoThe following has to be changed to an 8 byte integer@retval0   ok@retval1   request of thread shutdown, i. e. if command isCOM_QUIT
*/
bool dispatch_command(THD *thd, const COM_DATA *com_data,enum enum_server_command command) {assert(thd->lex->m_IS_table_stats.is_valid() == false);assert(thd->lex->m_IS_tablespace_stats.is_valid() == false);
#ifndef NDEBUGauto tabstat_grd = create_scope_guard([&]() {assert(thd->lex->m_IS_table_stats.is_valid() == false);assert(thd->lex->m_IS_tablespace_stats.is_valid() == false);});
#endif /* NDEBUG */bool error = false;Global_THD_manager *thd_manager = Global_THD_manager::get_instance();DBUG_TRACE;DBUG_PRINT("info", ("command: %d", command));Sql_cmd_clone *clone_cmd = nullptr;/* SHOW PROFILE instrumentation, begin */
#if defined(ENABLED_PROFILING)thd->profiling->start_new_query();
#endif/* Performance Schema Interface instrumentation, begin */thd->m_statement_psi = MYSQL_REFINE_STATEMENT(thd->m_statement_psi, com_statement_info[command].m_key);thd->set_command(command);/*Commands which always take a long time are logged intothe slow log only if opt_log_slow_admin_statements is set.*/thd->enable_slow_log = true;thd->lex->sql_command = SQLCOM_END; /* to avoid confusing VIEW detectors *//*KILL QUERY may come after cleanup in mysql_execute_command(). Next queryexecution is interrupted due to this. So resetting THD::killed here.THD::killed value can not be KILL_TIMEOUT here as timer used for statementmax execution time is disarmed in the cleanup stage ofmysql_execute_command. KILL CONNECTION should terminate the connection.Hence resetting THD::killed only for KILL QUERY case here.*/if (thd->killed == THD::KILL_QUERY) thd->killed = THD::NOT_KILLED;thd->set_time();if (is_time_t_valid_for_timestamp(thd->query_start_in_secs()) == false) {/*If the time has gone past end of epoch we need to shutdown the server. Butthere is possibility of getting invalid time value on some platforms.For example, gettimeofday() might return incorrect value on solarisplatform. Hence validating the current time with 5 iterations beforeinitiating the normal server shutdown process because of time gettingpast 2038.*/const int max_tries = 5;LogErr(WARNING_LEVEL, ER_CONFIRMING_THE_FUTURE, max_tries);int tries = 0;while (++tries <= max_tries) {thd->set_time();if (is_time_t_valid_for_timestamp(thd->query_start_in_secs()) == true) {LogErr(WARNING_LEVEL, ER_BACK_IN_TIME, tries);break;}LogErr(WARNING_LEVEL, ER_FUTURE_DATE, tries);}if (tries > max_tries) {/*If the time has got past epoch, we need to shut this server down.We do this by making sure every command is a shutdown and wehave enough privileges to shut the server downTODO: remove this when we have full 64 bit my_time_t support*/LogErr(ERROR_LEVEL, ER_UNSUPPORTED_DATE);const ulong master_access = thd->security_context()->master_access();thd->security_context()->set_master_access(master_access | SHUTDOWN_ACL);error = true;kill_mysql();}}thd->set_query_id(next_query_id());thd->reset_rewritten_query();thd_manager->inc_thread_running();if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))thd->status_var.questions++;/**Clear the set of flags that are expected to be cleared at thebeginning of each command.*/thd->server_status &= ~SERVER_STATUS_CLEAR_SET;if (thd->get_protocol()->type() == Protocol::PROTOCOL_PLUGIN &&!(server_command_flags[command] & CF_ALLOW_PROTOCOL_PLUGIN)) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));thd->killed = THD::KILL_CONNECTION;error = true;goto done;}/**Enforce password expiration for all RPC commands, except thefollowing:COM_QUERY/COM_STMT_PREPARE and COM_STMT_EXECUTE do a morefine-grained check later.COM_STMT_CLOSE and COM_STMT_SEND_LONG_DATA don't return anything.COM_PING only discloses information that the server is running,and that's available through other means.COM_QUIT should work even for expired statements.*/if (unlikely(thd->security_context()->password_expired() &&command != COM_QUERY && command != COM_STMT_CLOSE &&command != COM_STMT_SEND_LONG_DATA && command != COM_PING &&command != COM_QUIT && command != COM_STMT_PREPARE &&command != COM_STMT_EXECUTE)) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));goto done;}if (mysql_event_tracking_command_notify(thd, AUDIT_EVENT(EVENT_TRACKING_COMMAND_START), command,Command_names::str_global(command).c_str())) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);goto done;}/*For COM_QUERY,wait until query attributes are extracted.*/if (command != COM_QUERY) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);}switch (command) {case COM_INIT_DB: {LEX_STRING tmp;thd->status_var.com_stat[SQLCOM_CHANGE_DB]++;thd->convert_string(&tmp, system_charset_info,com_data->com_init_db.db_name,com_data->com_init_db.length, thd->charset());const LEX_CSTRING tmp_cstr = {tmp.str, tmp.length};if (!mysql_change_db(thd, tmp_cstr, false)) {query_logger.general_log_write(thd, command, thd->db().str,thd->db().length);my_ok(thd);}break;}case COM_REGISTER_SLAVE: {// TODO: access of protocol_classic should be removedif (!register_replica(thd, thd->get_protocol_classic()->get_raw_packet(),thd->get_protocol_classic()->get_packet_length()))my_ok(thd);break;}case COM_RESET_CONNECTION: {thd->status_var.com_other++;thd->cleanup_connection();my_ok(thd);break;}case COM_CLONE: {thd->status_var.com_other++;/* Try loading clone plugin */clone_cmd = new (thd->mem_root) Sql_cmd_clone();if (clone_cmd && clone_cmd->load(thd)) {clone_cmd = nullptr;}thd->lex->m_sql_cmd = clone_cmd;thd->lex->sql_command = SQLCOM_CLONE;break;}case COM_SUBSCRIBE_GROUP_REPLICATION_STREAM: {Security_context *sctx = thd->security_context();if (!sctx->has_global_grant(STRING_WITH_LEN("GROUP_REPLICATION_STREAM")).first) {my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "");error = true;break;}if (!error && call_gr_incoming_connection_cb(thd, thd->active_vio->mysql_socket.fd,thd->active_vio->ssl_arg? static_cast<SSL *>(thd->active_vio->ssl_arg): nullptr)) {my_error(ER_UNKNOWN_COM_ERROR, MYF(0));error = true;break;}my_ok(thd);break;}case COM_CHANGE_USER: {int auth_rc;thd->status_var.com_other++;thd->cleanup_connection();USER_CONN *save_user_connect =const_cast<USER_CONN *>(thd->get_user_connect());LEX_CSTRING save_db = thd->db();/*LOCK_thd_security_ctx protects the THD's security-context frominspection by SHOW PROCESSLIST while we're updating it. However,there is no need to protect this context while we're reading it,sinceother threads are not supposed to modify it.Nested acquiring of LOCK_thd_data is fine (see below).*/const Security_context save_security_ctx(*(thd->security_context()));MUTEX_LOCK(grd_secctx, &thd->LOCK_thd_security_ctx);auth_rc = acl_authenticate(thd, COM_CHANGE_USER);auth_rc |= mysql_event_tracking_connection_notify(thd, AUDIT_EVENT(EVENT_TRACKING_CONNECTION_CHANGE_USER));if (auth_rc) {*thd->security_context() = save_security_ctx;thd->set_user_connect(save_user_connect);thd->reset_db(save_db);my_error(ER_ACCESS_DENIED_CHANGE_USER_ERROR, MYF(0),thd->security_context()->user().str,thd->security_context()->host_or_ip().str,(thd->password ? ER_THD(thd, ER_YES) : ER_THD(thd, ER_NO)));thd->killed = THD::KILL_CONNECTION;error = true;} else {
#ifdef HAVE_PSI_THREAD_INTERFACE/* we've authenticated new user */PSI_THREAD_CALL(notify_session_change_user)(thd->get_psi());
#endif /* HAVE_PSI_THREAD_INTERFACE */if (save_user_connect) decrease_user_connections(save_user_connect);mysql_mutex_lock(&thd->LOCK_thd_data);my_free(const_cast<char *>(save_db.str));save_db = NULL_CSTR;mysql_mutex_unlock(&thd->LOCK_thd_data);}break;}case COM_STMT_EXECUTE: {/* Clear possible warnings from the previous command */thd->reset_for_next_command();Prepared_statement *stmt = nullptr;if (!mysql_stmt_precheck(thd, com_data, command, &stmt)) {PS_PARAM *parameters = com_data->com_stmt_execute.parameters;copy_bind_parameter_values(thd, parameters,com_data->com_stmt_execute.parameter_count);mysqld_stmt_execute(thd, stmt, com_data->com_stmt_execute.has_new_types,com_data->com_stmt_execute.open_cursor, parameters);thd->bind_parameter_values = nullptr;thd->bind_parameter_values_count = 0;}break;}case COM_STMT_FETCH: {/* Clear possible warnings from the previous command */thd->reset_for_next_command();Prepared_statement *stmt = nullptr;if (!mysql_stmt_precheck(thd, com_data, command, &stmt))mysqld_stmt_fetch(thd, stmt, com_data->com_stmt_fetch.num_rows);break;}case COM_STMT_SEND_LONG_DATA: {Prepared_statement *stmt;thd->get_stmt_da()->disable_status();if (!mysql_stmt_precheck(thd, com_data, command, &stmt))mysql_stmt_get_longdata(thd, stmt,com_data->com_stmt_send_long_data.param_number,com_data->com_stmt_send_long_data.longdata,com_data->com_stmt_send_long_data.length);break;}case COM_STMT_PREPARE: {/* Clear possible warnings from the previous command */thd->reset_for_next_command();Prepared_statement *stmt = nullptr;DBUG_EXECUTE_IF("parser_stmt_to_error_log", {LogErr(INFORMATION_LEVEL, ER_PARSER_TRACE,com_data->com_stmt_prepare.query);});DBUG_EXECUTE_IF("parser_stmt_to_error_log_with_system_prio", {LogErr(SYSTEM_LEVEL, ER_PARSER_TRACE, com_data->com_stmt_prepare.query);});if (!mysql_stmt_precheck(thd, com_data, command, &stmt))mysqld_stmt_prepare(thd, com_data->com_stmt_prepare.query,com_data->com_stmt_prepare.length, stmt);break;}case COM_STMT_CLOSE: {Prepared_statement *stmt = nullptr;thd->get_stmt_da()->disable_status();if (!mysql_stmt_precheck(thd, com_data, command, &stmt))mysqld_stmt_close(thd, stmt);break;}case COM_STMT_RESET: {/* Clear possible warnings from the previous command */thd->reset_for_next_command();Prepared_statement *stmt = nullptr;if (!mysql_stmt_precheck(thd, com_data, command, &stmt))mysqld_stmt_reset(thd, stmt);break;}case COM_QUERY: {/*IMPORTANT NOTE:Every execution path for COM_QUERY should call onceMYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES()*/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)) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);break;  // fatal error is set}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);
#endifconst LEX_CSTRING orig_query = thd->query();Parser_state parser_state;if (parser_state.init(thd, thd->query().str, thd->query().length)) {MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi, false);break;}parser_state.m_input.m_has_digest = true;// we produce digest if it's not explicitly turned off// by setting maximum digest length to zeroif (get_max_digest_length() != 0)parser_state.m_input.m_compute_digest = true;// 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);copy_bind_parameter_values(thd, com_data->com_query.parameters,com_data->com_query.parameter_count);/* This will call MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES() */dispatch_sql_command(thd, &parser_state);// Check if the statement failed and needs to be restarted in// another storage engine.check_secondary_engine_statement(thd, &parser_state, orig_query.str,orig_query.length);thd->set_secondary_engine_optimization(saved_secondary_engine);DBUG_EXECUTE_IF("parser_stmt_to_error_log", {LogErr(INFORMATION_LEVEL, ER_PARSER_TRACE, thd->query().str);});DBUG_EXECUTE_IF("parser_stmt_to_error_log_with_system_prio", {LogErr(SYSTEM_LEVEL, ER_PARSER_TRACE, thd->query().str);});while (!thd->killed && (parser_state.m_lip.found_semicolon != nullptr) &&!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_slow_query_status();thd->send_statement_status();const std::string &cn = Command_names::str_global(command);mysql_event_tracking_general_notify(thd, AUDIT_EVENT(EVENT_TRACKING_GENERAL_STATUS),thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->mysql_errno(): 0,cn.c_str(), cn.length());size_t length =static_cast<size_t>(packet_end - beginning_of_next_stmt);log_slow_statement(thd);thd->reset_copy_status_var();/* 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 = nullptr;thd->m_digest = nullptr;/* 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);
#endifmysql_thread_set_secondary_engine(false);/* PSI begin */thd->m_digest = &thd->m_digest_state;thd->m_digest->reset(thd->m_token_array, max_digest_length);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(), nullptr);THD_STAGE_INFO(thd, stage_starting);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);thd->set_secondary_engine_optimization(Secondary_engine_optimization::PRIMARY_TENTATIVELY);/* TODO: set thd->lex->sql_command to SQLCOM_END here */dispatch_sql_command(thd, &parser_state);check_secondary_engine_statement(thd, &parser_state,beginning_of_next_stmt, length);thd->set_secondary_engine_optimization(saved_secondary_engine);}thd->bind_parameter_values = nullptr;thd->bind_parameter_values_count = 0;/* 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;}case COM_FIELD_LIST:  // This isn't actually needed{char *fields;/* Locked closure of all tables */LEX_STRING table_name;LEX_STRING db;push_deprecated_warn(thd, "COM_FIELD_LIST","SHOW COLUMNS FROM statement");/*SHOW statements should not add the used tables to the list of tablesused in a transaction.*/MDL_savepoint mdl_savepoint = thd->mdl_context.mdl_savepoint();thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]++;if (thd->copy_db_to(&db.str, &db.length)) break;thd->convert_string(&table_name, system_charset_info,(char *)com_data->com_field_list.table_name,com_data->com_field_list.table_name_length,thd->charset());const Ident_name_check ident_check_status =check_table_name(table_name.str, table_name.length);if (ident_check_status == Ident_name_check::WRONG) {/* this is OK due to convert_string() null-terminating the string */my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);break;} else if (ident_check_status == Ident_name_check::TOO_LONG) {my_error(ER_TOO_LONG_IDENT, MYF(0), table_name.str);break;}mysql_reset_thd_for_next_command(thd);lex_start(thd);/* Must be before we init the table list. */if (lower_case_table_names && !is_infoschema_db(db.str, db.length))table_name.length = my_casedn_str(files_charset_info, table_name.str);Table_ref table_list(db.str, db.length, table_name.str, table_name.length,table_name.str, TL_READ);/*Init Table_ref members necessary when the undelryingtable is view.*/table_list.query_block = thd->lex->query_block;thd->lex->query_block->m_table_list.link_in_list(&table_list,&table_list.next_local);thd->lex->add_to_query_tables(&table_list);if (is_infoschema_db(table_list.db, table_list.db_length)) {ST_SCHEMA_TABLE *schema_table =find_schema_table(thd, table_list.alias);if (schema_table) table_list.schema_table = schema_table;}if (!(fields =(char *)thd->memdup(com_data->com_field_list.query,com_data->com_field_list.query_length)))break;// Don't count end \0thd->set_query(fields, com_data->com_field_list.query_length - 1);query_logger.general_log_print(thd, command, "%s %s",table_list.table_name, fields);if (open_temporary_tables(thd, &table_list)) break;if (check_table_access(thd, SELECT_ACL, &table_list, true, UINT_MAX,false))break;thd->lex->sql_command = SQLCOM_SHOW_FIELDS;// See comment in opt_trace_disable_if_no_security_context_access()const Opt_trace_start ots(thd, &table_list, thd->lex->sql_command,nullptr, nullptr, 0, nullptr, nullptr);mysqld_list_fields(thd, &table_list, fields);thd->lex->cleanup(true);/* No need to rollback statement transaction, it's not started. */assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));close_thread_tables(thd);thd->mdl_context.rollback_to_savepoint(mdl_savepoint);if (thd->transaction_rollback_request) {/*Transaction rollback was requested since MDL deadlock wasdiscovered while trying to open tables. Rollback transactionin all storage engines including binary log and release alllocks.*/trans_rollback_implicit(thd);thd->mdl_context.release_transactional_locks();}thd->cleanup_after_query();thd->lex->destroy();break;}case COM_QUIT:/* Prevent results of the form, "n>0 rows sent, 0 bytes sent" */thd->set_sent_row_count(0);/* We don't calculate statistics for this command */query_logger.general_log_print(thd, command, NullS);// Don't give 'abort' message// TODO: access of protocol_classic should be removedif (thd->is_classic_protocol())thd->get_protocol_classic()->get_net()->error = NET_ERROR_UNSET;thd->get_stmt_da()->disable_status();  // Don't send anything backerror = true;                          // End serverbreak;case COM_BINLOG_DUMP_GTID:// TODO: access of protocol_classic should be removederror = com_binlog_dump_gtid(thd, (char *)thd->get_protocol_classic()->get_raw_packet(),thd->get_protocol_classic()->get_packet_length());break;case COM_BINLOG_DUMP:// TODO: access of protocol_classic should be removederror = com_binlog_dump(thd, (char *)thd->get_protocol_classic()->get_raw_packet(),thd->get_protocol_classic()->get_packet_length());break;case COM_REFRESH: {int not_used;push_deprecated_warn(thd, "COM_REFRESH", "FLUSH statement");/*Initialize thd->lex since it's used in many base functions, such asopen_tables(). Otherwise, it remains uninitialized and may cause crashduring execution of COM_REFRESH.*/lex_start(thd);thd->status_var.com_stat[SQLCOM_FLUSH]++;const ulong options = (ulong)com_data->com_refresh.options;if (trans_commit_implicit(thd)) break;thd->mdl_context.release_transactional_locks();if (check_global_access(thd, RELOAD_ACL)) break;query_logger.general_log_print(thd, command, NullS);
#ifndef NDEBUGbool debug_simulate = false;DBUG_EXECUTE_IF("simulate_detached_thread_refresh",debug_simulate = true;);if (debug_simulate) {/*Simulate a reload without a attached thread session.Provides a environment similar to that of when theserver receives a SIGHUP signal and reloads cachesand flushes tables.*/bool res;current_thd = nullptr;res = handle_reload_request(nullptr, options | REFRESH_FAST, nullptr,&not_used);current_thd = thd;if (res) break;} else
#endifif (handle_reload_request(thd, options, (Table_ref *)nullptr,&not_used))break;if (trans_commit_implicit(thd)) break;close_thread_tables(thd);thd->mdl_context.release_transactional_locks();thd->lex->destroy();my_ok(thd);break;}case COM_STATISTICS: {System_status_var current_global_status_var;ulong uptime;size_t length [[maybe_unused]];ulonglong queries_per_second1000;char buff[250];const size_t buff_len = sizeof(buff);query_logger.general_log_print(thd, command, NullS);thd->status_var.com_stat[SQLCOM_SHOW_STATUS]++;mysql_mutex_lock(&LOCK_status);calc_sum_of_all_status(&current_global_status_var);mysql_mutex_unlock(&LOCK_status);if (!(uptime = (ulong)(thd->query_start_in_secs() - server_start_time)))queries_per_second1000 = 0;elsequeries_per_second1000 = thd->query_id * 1000LL / uptime;length = snprintf(buff, buff_len - 1,"Uptime: %lu  Threads: %d  Questions: %lu  ""Slow queries: %llu  Opens: %llu  Flush tables: %lu  ""Open tables: %u  Queries per second avg: %u.%03u",uptime, (int)thd_manager->get_thd_count(),(ulong)thd->query_id,current_global_status_var.long_query_count,current_global_status_var.opened_tables,refresh_version, table_cache_manager.cached_tables(),(uint)(queries_per_second1000 / 1000),(uint)(queries_per_second1000 % 1000));// TODO: access of protocol_classic should be removed.// should be rewritten using store functionsif (thd->get_protocol_classic()->write(pointer_cast<const uchar *>(buff),length))break;if (thd->get_protocol()->flush()) break;thd->get_stmt_da()->disable_status();break;}case COM_PING:thd->status_var.com_other++;my_ok(thd);  // Tell client we are alivebreak;case COM_PROCESS_INFO:bool global_access;LEX_CSTRING db_saved;thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]++;push_deprecated_warn(thd, "COM_PROCESS_INFO","SHOW PROCESSLIST statement");global_access = (check_global_access(thd, PROCESS_ACL) == 0);if (!thd->security_context()->priv_user().str[0] && !global_access) break;query_logger.general_log_print(thd, command, NullS);db_saved = thd->db();DBUG_EXECUTE_IF("force_db_name_to_null", thd->reset_db(NULL_CSTR););mysqld_list_processes(thd, global_access ? NullS : thd->security_context()->priv_user().str,false, false);DBUG_EXECUTE_IF("force_db_name_to_null", thd->reset_db(db_saved););break;case COM_PROCESS_KILL: {push_deprecated_warn(thd, "COM_PROCESS_KILL","KILL CONNECTION/QUERY statement");if (thd_manager->get_thread_id() & (~0xfffffffful))my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "thread_id", "mysql_kill()");else {thd->status_var.com_stat[SQLCOM_KILL]++;sql_kill(thd, com_data->com_kill.id, false);}break;}case COM_SET_OPTION: {thd->status_var.com_stat[SQLCOM_SET_OPTION]++;switch (com_data->com_set_option.opt_command) {case (int)MYSQL_OPTION_MULTI_STATEMENTS_ON:// TODO: access of protocol_classic should be removedthd->get_protocol_classic()->add_client_capability(CLIENT_MULTI_STATEMENTS);my_eof(thd);break;case (int)MYSQL_OPTION_MULTI_STATEMENTS_OFF:thd->get_protocol_classic()->remove_client_capability(CLIENT_MULTI_STATEMENTS);my_eof(thd);break;default:my_error(ER_UNKNOWN_COM_ERROR, MYF(0));break;}break;}case COM_DEBUG:thd->status_var.com_other++;if (check_global_access(thd, SUPER_ACL)) break; /* purecov: inspected */query_logger.general_log_print(thd, command, NullS);my_eof(thd);
#ifdef WITH_LOCK_ORDERLO_dump();
#endif /* WITH_LOCK_ORDER */break;case COM_SLEEP:case COM_CONNECT:         // Impossible herecase COM_TIME:            // Impossible from clientcase COM_DELAYED_INSERT:  // INSERT DELAYED has been removed.case COM_END:default:my_error(ER_UNKNOWN_COM_ERROR, MYF(0));break;}done:assert(thd->open_tables == nullptr ||(thd->locked_tables_mode == LTM_LOCK_TABLES));/* Finalize server status flags after executing a command. */thd->update_slow_query_status();if (thd->killed) thd->send_kill_message();thd->send_statement_status();/* After sending response, switch to clone protocol */if (clone_cmd != nullptr) {assert(command == COM_CLONE);error = clone_cmd->execute_server(thd);}if (command == COM_SUBSCRIBE_GROUP_REPLICATION_STREAM && !error) {wait_for_gr_connection_end(thd);}thd->rpl_thd_ctx.session_gtids_ctx().notify_after_response_packet(thd);if (!thd->is_error() && !thd->killed)mysql_event_tracking_general_notify(thd, AUDIT_EVENT(EVENT_TRACKING_GENERAL_RESULT), 0, nullptr, 0);const std::string &cn = Command_names::str_global(command);mysql_event_tracking_general_notify(thd, AUDIT_EVENT(EVENT_TRACKING_GENERAL_STATUS),thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->mysql_errno() : 0,cn.c_str(), cn.length());/* command_end is informational only. The plugin cannot abortexecution of the command at this point. */mysql_event_tracking_command_notify(thd, AUDIT_EVENT(EVENT_TRACKING_COMMAND_END), command, cn.c_str());log_slow_statement(thd);THD_STAGE_INFO(thd, stage_cleaning_up);thd->reset_query();thd->set_command(COM_SLEEP);thd->set_proc_info(nullptr);thd->lex->sql_command = SQLCOM_END;/* Performance Schema Interface instrumentation, end */MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());thd->m_statement_psi = nullptr;thd->m_digest = nullptr;thd->reset_query_for_display();/* Prevent rewritten query from getting "stuck" in SHOW PROCESSLIST. */thd->reset_rewritten_query();thd_manager->dec_thread_running();/* Freeing the memroot will leave the THD::work_part_info invalid. */thd->work_part_info = nullptr;/*If we've allocated a lot of memory (compared to the default preallocationsize = 8192; note that we don't actually preallocate anymore), freeit so that one big query won't cause us to hold on to a lot of RAM forever.If not, keep the last block so that the next query will hopefully be able torun without allocating memory from the OS.The factor 5 is pretty much arbitrary, but ends up allowing threeallocations (1 + 1.5 + 1.5²) under the current allocation policy.*/constexpr size_t kPreallocSz = 40960;if (thd->mem_root->allocated_size() < kPreallocSz)thd->mem_root->ClearForReuse();elsethd->mem_root->Clear();/* SHOW PROFILE instrumentation, end */
#if defined(ENABLED_PROFILING)thd->profiling->finish_current_query();
#endifreturn error;
}

##

/**Parse an SQL command from a text string and pass the resulting AST to thequery executor.@param thd          Current session.@param parser_state Parser state.
*/void dispatch_sql_command(THD *thd, Parser_state *parser_state) {DBUG_TRACE;DBUG_PRINT("dispatch_sql_command", ("query: '%s'", thd->query().str));statement_id_to_session(thd);DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););mysql_reset_thd_for_next_command(thd);// It is possible that rewritten query may not be empty (in case of// multiqueries). So reset it.thd->reset_rewritten_query();lex_start(thd);thd->m_parser_state = parser_state;invoke_pre_parse_rewrite_plugins(thd);thd->m_parser_state = nullptr;// we produce digest if it's not explicitly turned off// by setting maximum digest length to zeroif (get_max_digest_length() != 0)parser_state->m_input.m_compute_digest = true;LEX *lex = thd->lex;const char *found_semicolon = nullptr;bool err = thd->get_stmt_da()->is_error();size_t qlen = 0;if (!err) {err = parse_sql(thd, parser_state, nullptr);if (!err) err = invoke_post_parse_rewrite_plugins(thd, false);found_semicolon = parser_state->m_lip.found_semicolon;qlen = found_semicolon ? (found_semicolon - thd->query().str): thd->query().length;/*We set thd->query_length correctly to not log several queries, when weexecute only first. We set it to not see the ';' otherwise it would getinto binlog and Query_log_event::print() would give ';;' output.*/if (!thd->is_error() && found_semicolon && (ulong)(qlen)) {thd->set_query(thd->query().str, qlen - 1);}}DEBUG_SYNC_C("sql_parse_before_rewrite");if (!err) {/*Rewrite the query for logging and for the Performance Schemastatement tables. (Raw logging happened earlier.)Sub-routines of mysql_rewrite_query() should try to only rewrite whennecessary (e.g. not do password obfuscation when query contains nopassword).If rewriting does not happen here, thd->m_rewritten_query is stillempty from being reset in alloc_query().*/if (thd->rewritten_query().length() == 0) mysql_rewrite_query(thd);if (thd->rewritten_query().length()) {lex->safe_to_cache_query = false;  // see comments belowthd->set_query_for_display(thd->rewritten_query().ptr(),thd->rewritten_query().length());} else if (thd->slave_thread) {/*In the slave, we add the information to pfs.events_statements_history,but not to pfs.threads, as that is what the test suite expects.*/MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query().str,thd->query().length);} else {thd->set_query_for_display(thd->query().str, thd->query().length);}if (!(opt_general_log_raw || thd->slave_thread)) {if (thd->rewritten_query().length())query_logger.general_log_write(thd, COM_QUERY,thd->rewritten_query().ptr(),thd->rewritten_query().length());else {query_logger.general_log_write(thd, COM_QUERY, thd->query().str, qlen);}}}const bool with_query_attributes = (thd->bind_parameter_values_count > 0);MYSQL_NOTIFY_STATEMENT_QUERY_ATTRIBUTES(thd->m_statement_psi,with_query_attributes);DEBUG_SYNC_C("sql_parse_after_rewrite");if (!err) {thd->m_statement_psi = MYSQL_REFINE_STATEMENT(thd->m_statement_psi, sql_statement_info[thd->lex->sql_command].m_key);if (mqh_used && thd->get_user_connect() &&check_mqh(thd, lex->sql_command)) {if (thd->is_classic_protocol())thd->get_protocol_classic()->get_net()->error = NET_ERROR_UNSET;} else {if (!thd->is_error()) {/* Actually execute the query */if (found_semicolon) {lex->safe_to_cache_query = false;thd->server_status |= SERVER_MORE_RESULTS_EXISTS;}lex->set_trg_event_type_for_tables();int error [[maybe_unused]];if (unlikely((thd->security_context()->password_expired() ||thd->security_context()->is_in_registration_sandbox_mode()) &&lex->sql_command != SQLCOM_SET_PASSWORD &&lex->sql_command != SQLCOM_ALTER_USER)) {if (thd->security_context()->is_in_registration_sandbox_mode())my_error(ER_PLUGIN_REQUIRES_REGISTRATION, MYF(0));elsemy_error(ER_MUST_CHANGE_PASSWORD, MYF(0));error = 1;} else {resourcegroups::Resource_group *src_res_grp = nullptr;resourcegroups::Resource_group *dest_res_grp = nullptr;MDL_ticket *ticket = nullptr;MDL_ticket *cur_ticket = nullptr;auto mgr_ptr = resourcegroups::Resource_group_mgr::instance();const bool switched = mgr_ptr->switch_resource_group_if_needed(thd, &src_res_grp, &dest_res_grp, &ticket, &cur_ticket);error = mysql_execute_command(thd, true);if (switched)mgr_ptr->restore_original_resource_group(thd, src_res_grp,dest_res_grp);thd->resource_group_ctx()->m_switch_resource_group_str[0] = '\0';if (ticket != nullptr)mgr_ptr->release_shared_mdl_for_resource_group(thd, ticket);if (cur_ticket != nullptr)mgr_ptr->release_shared_mdl_for_resource_group(thd, cur_ticket);}}}} else {/*Log the failed raw query in the Performance Schema. This statement didnot parse, so there is no way to tell if it may contain a password of not.The tradeoff is:a) If we do log the query, a user typing by accident a broken querycontaining a password will have the password exposed. This is veryunlikely, and this behavior can be documented. Remediation is touse a new password when retyping the corrected query.b) If we do not log the query, finding broken queries in the clientapplication will be much more difficult. This is much more likely.Considering that broken queries can typically be generated by attempts atSQL injection, finding the source of the SQL injection is critical, so thedesign choice is to log the query text of broken queries (a).*/thd->set_query_for_display(thd->query().str, thd->query().length);/* Instrument this broken statement as "statement/sql/error" */thd->m_statement_psi = MYSQL_REFINE_STATEMENT(thd->m_statement_psi, sql_statement_info[SQLCOM_END].m_key);assert(thd->is_error());DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error()));}THD_STAGE_INFO(thd, stage_freeing_items);sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size);sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size);thd->lex->destroy();thd->end_statement();thd->cleanup_after_query();assert(thd->change_list.is_empty());DEBUG_SYNC(thd, "query_rewritten");
}

##

extern "C" {
static void *handle_connection(void *arg) {Global_THD_manager *thd_manager = Global_THD_manager::get_instance();Connection_handler_manager *handler_manager =Connection_handler_manager::get_instance();Channel_info *channel_info = static_cast<Channel_info *>(arg);bool pthread_reused [[maybe_unused]] = false;if (my_thread_init()) {connection_errors_internal++;channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false);handler_manager->inc_aborted_connects();Connection_handler_manager::dec_connection_count();delete channel_info;my_thread_exit(nullptr);return nullptr;}for (;;) {THD *thd = init_new_thd(channel_info);if (thd == nullptr) {connection_errors_internal++;handler_manager->inc_aborted_connects();Connection_handler_manager::dec_connection_count();break;  // We are out of resources, no sense in continuing.}#ifdef HAVE_PSI_THREAD_INTERFACEif (pthread_reused) {/*Reusing existing pthread:Create new instrumentation for the new THD job,and attach it to this running pthread.*/PSI_thread *psi = PSI_THREAD_CALL(new_thread)(key_thread_one_connection,0 /* no sequence number */,thd, thd->thread_id());PSI_THREAD_CALL(set_thread_os_id)(psi);PSI_THREAD_CALL(set_thread)(psi);}
#endif#ifdef HAVE_PSI_THREAD_INTERFACE/* Find the instrumented thread */PSI_thread *psi = PSI_THREAD_CALL(get_thread)();/* Save it within THD, so it can be inspected */thd->set_psi(psi);
#endif /* HAVE_PSI_THREAD_INTERFACE */mysql_thread_set_psi_id(thd->thread_id());mysql_thread_set_psi_THD(thd);const MYSQL_SOCKET socket =thd->get_protocol_classic()->get_vio()->mysql_socket;mysql_socket_set_thread_owner(socket);thd_manager->add_thd(thd);if (thd_prepare_connection(thd))handler_manager->inc_aborted_connects();else {while (thd_connection_alive(thd)) {if (do_command(thd)) break;}end_connection(thd);}close_connection(thd, 0, false, false);thd->get_stmt_da()->reset_diagnostics_area();thd->release_resources();// Clean up errors now, before possibly waiting for a new connection.
#if OPENSSL_VERSION_NUMBER < 0x10100000LERR_remove_thread_state(0);
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */thd_manager->remove_thd(thd);Connection_handler_manager::dec_connection_count();#ifdef HAVE_PSI_THREAD_INTERFACE/* Stop telemetry, while THD is still available. */if (psi != nullptr) {PSI_THREAD_CALL(abort_telemetry)(psi);}/* Decouple THD and the thread instrumentation. */thd->set_psi(nullptr);mysql_thread_set_psi_THD(nullptr);
#endif /* HAVE_PSI_THREAD_INTERFACE */delete thd;#ifdef HAVE_PSI_THREAD_INTERFACE/* Delete the instrumentation for the job that just completed. */PSI_THREAD_CALL(delete_current_thread)();
#endif /* HAVE_PSI_THREAD_INTERFACE */// Server is shutting down so end the pthread.if (connection_events_loop_aborted()) break;channel_info = Per_thread_connection_handler::block_until_new_connection();if (channel_info == nullptr) break;pthread_reused = true;if (connection_events_loop_aborted()) {// Close the channel and exit as server is undergoing shutdown.channel_info->send_error_and_close_channel(ER_SERVER_SHUTDOWN, 0, false);delete channel_info;channel_info = nullptr;Connection_handler_manager::dec_connection_count();break;}}my_thread_end();my_thread_exit(nullptr);return nullptr;
}
}  // extern "C"

##

bool Per_thread_connection_handler::add_connection(Channel_info *channel_info) {int error = 0;my_thread_handle id;DBUG_TRACE;// Simulate thread creation for test case before we check thread cacheDBUG_EXECUTE_IF("fail_thread_create", error = 1; goto handle_error;);if (!check_idle_thread_and_enqueue_connection(channel_info)) return false;/*There are no idle threads available to take up the newconnection. Create a new thread to handle the connection*/channel_info->set_prior_thr_create_utime();error =mysql_thread_create(key_thread_one_connection, &id, &connection_attrib,handle_connection, (void *)channel_info);
#ifndef NDEBUG
handle_error:
#endif  // !NDEBUGif (error) {connection_errors_internal++;if (!create_thd_err_log_throttle.log())LogErr(ERROR_LEVEL, ER_CONN_PER_THREAD_NO_THREAD, error);channel_info->send_error_and_close_channel(ER_CANT_CREATE_THREAD, error,true);Connection_handler_manager::dec_connection_count();return true;}Global_THD_manager::get_instance()->inc_thread_created();DBUG_PRINT("info", ("Thread created"));return false;
}

##gdb调试栈,处理客户端连接

(gdb) bt
#0  my_thread_create (thread=0x7ffde2e84658, attr=0x57cc6d05fd80 <connection_attrib>, func=0x57cc69d4da88 <pfs_spawn_thread(void*)>, arg=0x57cca0dc1ea0)at /home/yym/mysql8/mysql-8.1.0/mysys/my_thread.cc:80
#1  0x000057cc69d4dd3a in pfs_spawn_thread_vc (key=5, seqnum=0, thread=0x7ffde2e84658, attr=0x57cc6d05fd80 <connection_attrib>,start_routine=0x57cc67e0e643 <handle_connection(void*)>, arg=0x57cca10e5ca0) at /home/yym/mysql8/mysql-8.1.0/storage/perfschema/pfs.cc:3089
#2  0x000057cc67e0e010 in inline_mysql_thread_create (key=5, sequence_number=0, thread=0x7ffde2e84658, attr=0x57cc6d05fd80 <connection_attrib>,start_routine=0x57cc67e0e643 <handle_connection(void*)>, arg=0x57cca10e5ca0) at /home/yym/mysql8/mysql-8.1.0/include/mysql/psi/mysql_thread.h:139
#3  0x000057cc67e0ecaf in Per_thread_connection_handler::add_connection (this=0x57cca0c26e10, channel_info=0x57cca10e5ca0)at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_per_thread.cc:420
#4  0x000057cc67f73289 in Connection_handler_manager::process_new_connection (this=0x57cca028d4d0, channel_info=0x57cca10e5ca0)at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_manager.cc:260
#5  0x000057cc679ceea4 in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0x57cca0d1f290)at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_acceptor.h:65
#6  0x000057cc679bf5a3 in mysqld_main (argc=22, argv=0x57cc9ea287b8) at /home/yym/mysql8/mysql-8.1.0/sql/mysqld.cc:8355
#7  0x000057cc679aa4cd in main (argc=9, argv=0x7ffde2e84d68) at /home/yym/mysql8/mysql-8.1.0/sql/main.cc:25(gdb) bt
#0  handle_connection (arg=0x57cca10e5ca0) at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_per_thread.cc:252
#1  0x000057cc69d4dbdc in pfs_spawn_thread (arg=0x57cca0dc1ea0) at /home/yym/mysql8/mysql-8.1.0/storage/perfschema/pfs.cc:3043
#2  0x00007834cd694ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#3  0x00007834cd726850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

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

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

相关文章

深度学习在医疗影像分析中的应用

引言 随着人工智能技术的快速发展&#xff0c;深度学习在各个领域都展现出了巨大的潜力。特别是在医疗影像分析中&#xff0c;深度学习的应用不仅提高了诊断的准确性&#xff0c;还大大缩短了医生的工作时间&#xff0c;提升了医疗服务的质量。本文将详细介绍深度学习在医疗影像…

计算机领域QPM、TPM分别是什么并发指标,还有其他类似指标吗?

在计算机领域&#xff0c;QPM和TPM是两种不同的并发指标&#xff0c;它们分别用于衡量系统处理请求的能力和吞吐量。 QPM&#xff08;每分钟请求数&#xff09; QPM&#xff08;Query Per Minute&#xff09;表示每分钟系统能够处理的请求数量。它通常用于衡量系统在单位时间…

【安当产品应用案例100集】036-视频监控机房权限管理新突破:安当windows操作系统登录双因素认证解决方案

一、机房管理痛点&#xff1a;权限失控下的数据泄露风险 在智慧城市与数字化转型浪潮下&#xff0c;视频监控系统已成为能源、金融、司法等行业的核心安防设施。然而&#xff0c;传统机房管理模式中&#xff0c;值班人员通过单一密码即可解锁监控画面的操作漏洞&#xff0c;正…

Unity抖音云启动测试:如何用cmd命令行启动exe

相关资料&#xff1a;弹幕云启动&#xff08;原“玩法云启动能力”&#xff09;_直播小玩法_抖音开放平台 1&#xff0c;操作方法 在做云启动的时候&#xff0c;接完发现需要命令行模拟云环境测试启动&#xff0c;所以研究了下。 首先进入cmd命令&#xff0c;CD进入对应包的文件…

< OS 有关 > 利用 google-drive-ocamlfuse 工具,在 Ubuntu 24 系统上 加载 Google DRIVE 网盘

Created by Dave On 8Feb.2025 起因&#xff1a; 想下载 StableDiffusion&#xff0c;清理系统文件时把 i/o 搞到 100%&#xff0c;已经删除到 apt 缓存&#xff0c;还差 89MB&#xff0c;只能另想办法。 在网上找能不能挂在 Google 网盘&#xff0c;百度网盘&#xff0c;或 …

【LITS游戏——暴力DFS+剪枝优化】

题目 代码 #include <bits/stdc.h> using namespace std; using pll pair<int, int>; #define x first #define y second const int N 51; pll d[4][4][4] {{{{0, 0}, {1, 0}, {2, 0}, {2, 1}}, {{0, 0}, {1, 0}, {1, -1}, {1, -2}}, {{0, 0}, {0, 1}, {1, 1},…

Redisson全面解析:从使用方法到工作原理的深度探索

文章目录 写在文章开头详解Redisson基本数据类型基础配置字符串操作列表操作映射集阻塞队列延迟队列更多关于Redisson详解Redisson 中的原子类详解redisson中的发布订阅模型小结参考写在文章开头 Redisson是基于原生redis操作指令上进一步的封装,屏蔽了redis数据结构的实现细…

用Python进行websocket接口测试

这篇文章主要介绍了用Python进行websocket接口测试&#xff0c;帮助大家更好的理解和使用python&#xff0c;感兴趣的朋友可以了解下 我们在做接口测试时&#xff0c;除了常见的http接口&#xff0c;还有一种比较多见&#xff0c;就是socket接口&#xff0c;今天讲解下怎么用P…

【RocketMQ 存储】- 同步刷盘服务 GroupCommitService

文章目录 1. 前言2. 参数3. 队列相关4. 核心逻辑 run4.1 waitForRunning4.2 doCommit4.3 flush 5. 小结 本文章基于 RocketMQ 4.9.3 1. 前言 RocketMQ 存储部分系列文章&#xff1a; 【RocketMQ 存储】- RocketMQ存储类 MappedFile【RocketMQ 存储】- 一文总结 RocketMQ 的存…

基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具&#xff0c;旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病&#xff0c;通常表现为认知障碍、记忆丧失和语言障碍等症状…

IDEA编写SpringBoot项目时使用Lombok报错“找不到符号”的原因和解决

目录 概述|背景 报错解析 解决方法 IDEA配置解决 Pom配置插件解决 概述|背景 报错发生背景&#xff1a;在SpringBoot项目中引入Lombok依赖并使用后出现"找不到符号"的问题。 本文讨论在上述背景下发生的报错原因和解决办法&#xff0c;如果仅为了解决BUG不论原…

【异常解决】在idea中提示 hutool 提示 HttpResponse used withoud try-with-resources statement

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

搜维尔科技:提供人形机器人传感器的应用案例分析

视觉传感器 • 家庭服务场景&#xff1a;在家庭清洁机器人中&#xff0c;视觉传感器可以识别家具、障碍物的位置和形状&#xff0c;规划清洁路径&#xff0c;避开桌椅、宠物玩具等。如小米扫地机器人&#xff0c;通过视觉传感器与算法结合&#xff0c;能构建房间地图&#xff…

虹科波形小课堂 | 三分钟掌握车辆相对压缩测试!不拆发动机、不测缸压就能判断故障缸!

不拆发动机、不测缸压&#xff0c;只测个电流也能知道哪个缸压缩有问题&#xff1f;没错&#xff01;做个相对压缩测试&#xff0c;测下起动电流就行&#xff0c;简单又实用&#xff01;今天&#xff0c;从原理到方法&#xff0c;几分钟教会你&#xff01; 我们都知道&#xf…

自然语言处理NLP_[1]-NLP入门

文章目录 1.自然语言处理入门1. 什么是自然语言处理2.自然语言处理的发展简史3 自然语言处理的应用场景1. **机器翻译**2. **文本分类**3. **情感分析**4. **问答系统**5. **文本生成**6. **信息抽取**7. **语音识别与合成**8. **文本摘要**9. **搜索引擎优化**10. **聊天机器人…

无限使用Cursor

原理&#xff1a;运行程序获得15天的免费试用期&#xff0c;重新运行程序重置试用期&#xff0c;实现无限使用。免费的pro账号&#xff0c;一个月有250的高级模型提问次数。 前提&#xff1a;已安装cursor cursor-vip工具&#xff1a;https://cursor.jeter.eu.org?p95d60efe…

LIMO:少即是多的推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型&#xff08;LLM&#xff09;中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据&#xff08;通常超过 100,000 个示例&#xff09;&#xff0c;但本文展…

一种基于Leaflet.Legend的图例动态更新方法

目录 前言 一、场景再现 1、需求描述 2、核心方法介绍 3、存在的问题 二、问题解决 1、重复解决办法 2、图例不展示解决办法 3、成果展示 三、总结 前言 在当今数字化时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术已经广泛应用于各个领域&#xff0c;…

【AI时代】使用ollama私有化部署deepseek的过程及问题记录

文章目录 说明下载模型通过ollama下载通过modelscope下载 部署open-webui问题记录临时目录空间不足单机多卡部署后台启动 说明 对于DeepSeek的私有化部署&#xff0c;现在网上已经有很全面的资料了&#xff0c;本文主要记录部署以及部署过程中遇到的问题。目前对于这些问题&am…

使用 SDKMAN! 在 Mac(包括 ARM 架构的 M1/M2 芯片)上安装 Java 8

文章目录 1. 安装 SDKMAN!2. 查找可用的 Java 8 版本3. 安装 Java 84. 验证安装5. 切换 Java 版本&#xff08;可选&#xff09;6. 解决 ARM 架构兼容性问题总结 可以使用 SDKMAN! 在 Mac&#xff08;包括 ARM 架构的 M1/M2 芯片&#xff09;上安装 Java 8。SDKMAN! 是一个强大…