1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

Reuse THD for new user connections

- To ensure that mallocs are marked for the correct THD, even if it's
  allocated in another thread, I added the thread_id to the THD constructor
- Added st_my_thread_var to thr_lock_info_init() to avoid a call to my_thread_var
- Moved things from THD::THD() to THD::init()
- Moved some things to THD::cleanup()
- Added THD::free_connection() and THD::reset_for_reuse()
- Added THD to CONNECT::create_thd()
- Added THD::thread_dbug_id and st_my_thread_var->dbug_id. These are needed
  to ensure that we have a constant thread_id used for debugging with a THD,
  even if it changes thread_id (=connection_id)
- Set variables.pseudo_thread_id in constructor. Removed not needed sets.
This commit is contained in:
Monty
2016-04-07 19:51:40 +03:00
committed by Sergei Golubchik
parent 54f3e18f6e
commit 89685d55d7
34 changed files with 220 additions and 130 deletions

View File

@ -336,17 +336,6 @@ void thd_set_killed(THD *thd)
thd->killed= KILL_CONNECTION;
}
/**
Clear errors from the previous THD
@param thd THD object
*/
void thd_clear_errors(THD *thd)
{
my_errno= 0;
thd->mysys_var->abort= 0;
}
/**
Set thread stack in THD object
@ -456,7 +445,7 @@ my_socket thd_get_fd(THD *thd)
{
return mysql_socket_getfd(thd->net.vio->mysql_socket);
}
#endif
#endif /* ONLY_FOR_MYSQL_CLOSED_SOURCE_SCHEDULED */
/**
Get current THD object from thread local data
@ -468,6 +457,18 @@ THD *thd_get_current_thd()
return current_thd;
}
/**
Clear errors from the previous THD
@param thd THD object
*/
void thd_clear_errors(THD *thd)
{
my_errno= 0;
thd->mysys_var->abort= 0;
}
/**
Get thread attributes for connection threads
@ -845,7 +846,7 @@ extern "C" void thd_kill_timeout(THD* thd)
}
THD::THD(bool is_wsrep_applier)
THD::THD(my_thread_id id, bool is_wsrep_applier)
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
/* statement id */ 0),
rli_fake(0), rgi_fake(0), rgi_slave(NULL),
@ -854,17 +855,13 @@ THD::THD(bool is_wsrep_applier)
binlog_unsafe_warning_flags(0),
binlog_table_maps(0),
table_map_for_update(0),
arg_of_last_insert_id_function(FALSE),
first_successful_insert_id_in_prev_stmt(0),
first_successful_insert_id_in_prev_stmt_for_binlog(0),
first_successful_insert_id_in_cur_stmt(0),
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
m_examined_row_count(0),
accessed_rows_and_keys(0),
m_digest(NULL),
m_statement_psi(NULL),
m_idle_psi(NULL),
thread_id(0),
thread_id(id),
thread_dbug_id(id),
os_thread_id(0),
global_disable_checkpoint(0),
failed_com_change_user(0),
@ -910,6 +907,7 @@ THD::THD(bool is_wsrep_applier)
set_current_thd(this);
status_var.local_memory_used= sizeof(THD);
status_var.global_memory_used= 0;
variables.pseudo_thread_id= thread_id;
main_da.init();
/*
@ -973,14 +971,12 @@ THD::THD(bool is_wsrep_applier)
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
#endif
#ifndef EMBEDDED_LIBRARY
mysql_audit_init_thd(this);
#endif
net.vio=0;
net.buff= 0;
client_capabilities= 0; // minimalistic client
system_thread= NON_SYSTEM_THREAD;
cleanup_done= abort_on_warning= 0;
cleanup_done= free_connection_done= abort_on_warning= 0;
peer_port= 0; // For SHOW PROCESSLIST
transaction.m_pending_rows_event= 0;
transaction.on= 1;
@ -1003,7 +999,6 @@ THD::THD(bool is_wsrep_applier)
/* Variables with default values */
proc_info="login";
where= THD::DEFAULT_WHERE;
variables.server_id = global_system_variables.server_id;
slave_net = 0;
m_command=COM_CONNECT;
*scramble= '\0';
@ -1064,7 +1059,6 @@ THD::THD(bool is_wsrep_applier)
tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff);
my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
substitute_null_with_insert_id = FALSE;
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
lock_info.mysql_thd= (void *)this;
m_token_array= NULL;
@ -1425,10 +1419,16 @@ void THD::init(void)
reset_binlog_local_stmt_filter();
set_status_var_init();
bzero((char *) &org_status_var, sizeof(org_status_var));
status_in_global= 0;
start_bytes_received= 0;
last_commit_gtid.seq_no= 0;
last_stmt= NULL;
status_in_global= 0;
/* Reset status of last insert id */
arg_of_last_insert_id_function= FALSE;
stmt_depends_on_first_successful_insert_id_in_prev_stmt= FALSE;
first_successful_insert_id_in_prev_stmt= 0;
first_successful_insert_id_in_prev_stmt_for_binlog= 0;
first_successful_insert_id_in_cur_stmt= 0;
#ifdef WITH_WSREP
wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE;
wsrep_conflict_state= NO_CONFLICT;
@ -1547,12 +1547,14 @@ void THD::init_for_queries()
void THD::change_user(void)
{
add_status_to_global();
if (!status_in_global) // Reset in init()
add_status_to_global();
cleanup();
reset_killed();
if (!cleanup_done)
cleanup();
cleanup_done= 0;
status_in_global= 0;
reset_killed();
thd_clear_errors(this);
init();
stmt_map.reset();
my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
@ -1616,6 +1618,8 @@ void THD::cleanup(void)
my_hash_free(&user_vars);
sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache);
auto_inc_intervals_forced.empty();
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
mysql_ull_cleanup(this);
/* All metadata locks must have been released by now. */
@ -1627,6 +1631,63 @@ void THD::cleanup(void)
}
/*
Free all connection related resources associated with a THD.
This is used when we put a thread into the thread cache.
After this call should either call ~THD or reset_for_reuse() depending on
circumstances.
*/
void THD::free_connection()
{
DBUG_ASSERT(free_connection_done == 0);
my_free(db);
db= NULL;
#ifndef EMBEDDED_LIBRARY
if (net.vio)
vio_delete(net.vio);
net.vio= 0;
net_end(&net);
#endif
ha_close_connection(this);
plugin_thdvar_cleanup(this);
mysql_audit_free_thd(this);
main_security_ctx.destroy();
/* close all prepared statements, to save memory */
stmt_map.reset();
free_connection_done= 1;
profiling.restart(); // Reset profiling
}
/*
Reset thd for reuse by another connection
This is only used for user connections, so the following variables doesn't
have to be reset:
- Replication (slave) variables.
- Variables not reset between each statements. See reset_for_next_command.
*/
void THD::reset_for_reuse()
{
mysql_audit_init_thd(this);
change_user(); // Calls cleanup() & init()
get_stmt_da()->reset_diagnostics_area();
main_security_ctx.init();
failed_com_change_user= 0;
is_fatal_error= 0;
client_capabilities= 0;
peer_port= 0;
query_name_consts= 0; // Safety
abort_on_warning= 0;
free_connection_done= 0;
m_command= COM_CONNECT;
profiling.reset();
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
#endif
}
THD::~THD()
{
THD *orig_thd= current_thd;
@ -1653,26 +1714,15 @@ THD::~THD()
mysql_mutex_lock(&LOCK_wsrep_thd);
mysql_mutex_unlock(&LOCK_wsrep_thd);
mysql_mutex_destroy(&LOCK_wsrep_thd);
if (wsrep_rgi) delete wsrep_rgi;
delete wsrep_rgi;
#endif
/* Close connection */
#ifndef EMBEDDED_LIBRARY
if (net.vio)
vio_delete(net.vio);
net_end(&net);
#endif
stmt_map.reset(); /* close all prepared statements */
if (!free_connection_done)
free_connection();
if (!cleanup_done)
cleanup();
mdl_context.destroy();
ha_close_connection(this);
mysql_audit_release(this);
plugin_thdvar_cleanup(this);
main_security_ctx.destroy();
my_free(db);
db= NULL;
free_root(&transaction.mem_root,MYF(0));
mysql_cond_destroy(&COND_wakeup_ready);
mysql_mutex_destroy(&LOCK_wakeup_ready);
@ -1692,7 +1742,6 @@ THD::~THD()
rli_fake= NULL;
}
mysql_audit_free_thd(this);
if (rgi_slave)
rgi_slave->cleanup_after_session();
my_free(semisync_info);
@ -2089,7 +2138,16 @@ bool THD::store_globals()
Let mysqld define the thread id (not mysys)
This allows us to move THD to different threads if needed.
*/
mysys_var->id= thread_id;
mysys_var->id= thread_id;
/* thread_dbug_id should not change for a THD */
if (!thread_dbug_id)
thread_dbug_id= mysys_var->dbug_id;
else
{
/* This only changes if we are using pool-of-threads */
mysys_var->dbug_id= thread_dbug_id;
}
#ifdef __NR_gettid
os_thread_id= (uint32)syscall(__NR_gettid);
#else
@ -2106,7 +2164,7 @@ bool THD::store_globals()
We have to call thr_lock_info_init() again here as THD may have been
created in another thread
*/
thr_lock_info_init(&lock_info);
thr_lock_info_init(&lock_info, mysys_var);
return 0;
}