dispatch_command(
enum enum_server_command command,
THD *thd,
char *packet,
uint packet_length
) {
thd->command = command;
thd->set_query_id(next_query_id());
inc_thread_running(); // thread_running++
switch (command) {
case COM_INIT_DB: mysql_change_db(dbname); break;
case COM_REGISTER_SLAVE: register_slave(); break;
case COM_CHANGE_USER: thd->change_user();... break;
case COM_STMT_EXECUTE: mysqld_stmt_execute(); break;
case COM_STMT_FETCH: mysqld_stmt_fetch(); break;
case COM_STMT_SEND_LONG_DATA: mysql_stmt_get_longdata(); break;
case COM_STMT_PREPARE: mysqld_stmt_prepare(); break;
case COM_STMT_CLOSE: mysqld_stmt_close(); break;
case COM_STMT_RESET: mysqld_stmt_reset(); break;
case COM_QUERY:
break;
case COM_FIELD_LIST:
break;
case COM_QUIT:
thd->stmt_da->disable_status();
error = TRUE;
break;
case COM_BINLOG_DUMP:
break;
// COM_REFRESH, COM_SHUTDIWN, COM_STATISTICS, COM_PING, COM_PROCESS_INFO
// COM_PROCESS_KILL, COM_SET_OPTION, COM_DEBUG
}
thd->update_server_status();
thd->protocol->end_statement();
query_cache_end_of_result(thd); // Query_cache::end_of_result(THD *thd)
log_slow_statement(thd);
thd->reset_query();
thd->command = COM_SLEEP;
dec_thread_running(); // thread_running--
}
Protocol::end_statement()
switch (thd->stmt_da->status()) {
case DA_ERROR:
send_error(thd->stmt_da->sql_errno(), stmt_da->message(), stmt_da->get_sqlstate());
break;
case DA_EOF:
send_eof(thd->server_status, stmt_da->statement_warn_count);
break;
case DA_OK:
send_ok(thd->server_status,
stmt_da->statement_warn_count,
stmt_da->affected_rows(),
stmt_da->last_insert_id(),
stmt_da->message()
);
break;
}
mysql_change_db(dbname)
check_db_name();
check_db_dir_existence(); // 每个数据库在/var/lib/mysql里有一个单独的目录,
// 每个表都有一个对应的table_name.frm,
// 还有一个文本文件db.opt记录着这个数据库的默认字符集
mysql_change_db_impl(dbname, db_access, db_default_charset);
thd->reset_db(dbname); // thd->db = dbname;
thd->security_ctx->db_access = db_access;
thd->db_charset = db_default_charset;
thd->variables.collation_database = db_default_charset;
COM_QUERY
alloc_query();
query = sql '\0' dbname_length dbname flags
thd->set_query(query);
parser_state.init(thd, thd->query(), thd->query_length());
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
query_cache_send_result_to_client(thd, query, query_length);
while (parser_state.m_lip.found_semicolon != NULL) {
// multiple queries
mysql_parse(next_query);
}
mysql_parse(query) => MYSQLparse