diff options
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 108 |
1 files changed, 45 insertions, 63 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 69e60109d42..c10eedaadfb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -49,9 +49,6 @@ #include <m_ctype.h> #include <sys/stat.h> #include <thr_alarm.h> -#ifdef __WIN__0 -#include <io.h> -#endif #include <mysys_err.h> #include <limits.h> @@ -70,6 +67,8 @@ #ifdef WITH_WSREP #include "wsrep_thd.h" #include "wsrep_trans_observer.h" +#else +static inline bool wsrep_is_bf_aborted(THD* thd) { return false; } #endif /* WITH_WSREP */ #include "opt_trace.h" #include <mysql/psi/mysql_transaction.h> @@ -486,7 +485,9 @@ void thd_set_ha_data(THD *thd, const struct handlerton *hton, const void *ha_data) { plugin_ref *lock= &thd->ha_data[hton->slot].lock; + mysql_mutex_lock(&thd->LOCK_thd_data); thd->ha_data[hton->slot].ha_ptr= const_cast<void*>(ha_data); + mysql_mutex_unlock(&thd->LOCK_thd_data); if (ha_data && !*lock) *lock= ha_lock_engine(NULL, (handlerton*) hton); else if (!ha_data && *lock) @@ -836,6 +837,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) mysql_mutex_init(key_LOCK_wakeup_ready, &LOCK_wakeup_ready, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_thd_kill, &LOCK_thd_kill, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wakeup_ready, &COND_wakeup_ready, 0); + mysql_mutex_record_order(&LOCK_thd_kill, &LOCK_thd_data); /* Variables with default values */ proc_info="login"; @@ -1531,30 +1533,15 @@ void THD::reset_db(const LEX_CSTRING *new_db) /* Do operations that may take a long time */ -void THD::cleanup(bool have_mutex) +void THD::cleanup(void) { DBUG_ENTER("THD::cleanup"); DBUG_ASSERT(cleanup_done == 0); - if (have_mutex) - set_killed_no_mutex(KILL_CONNECTION,0,0); - else - set_killed(KILL_CONNECTION); + set_killed(KILL_CONNECTION); #ifdef WITH_WSREP if (wsrep_cs().state() != wsrep::client_state::s_none) - { - if (have_mutex) - { - mysql_mutex_assert_owner(static_cast<mysql_mutex_t*> - (m_wsrep_mutex.native())); - // Below wsrep-lib function will not acquire any mutexes - wsrep::unique_lock<wsrep::mutex> lock(m_wsrep_mutex, std::adopt_lock); - wsrep_cs().cleanup(lock); - lock.release(); - } - else - wsrep_cs().cleanup(); - } + wsrep_cs().cleanup(); wsrep_client_thread= false; #endif /* WITH_WSREP */ @@ -1627,28 +1614,6 @@ void THD::cleanup(bool have_mutex) void THD::free_connection() { DBUG_ASSERT(free_connection_done == 0); - /* Make sure threads are not available via server_threads. */ - assert_not_linked(); - - /* - Other threads may have a lock on THD::LOCK_thd_data or - THD::LOCK_thd_kill to ensure that this THD is not deleted - while they access it. The following mutex_lock ensures - that no one else is using this THD and it's now safe to - continue. - - For example consider KILL-statement execution on - sql_parse.cc kill_one_thread() that will use - THD::LOCK_thd_data to protect victim thread during - THD::awake(). - */ - mysql_mutex_lock(&LOCK_thd_data); - mysql_mutex_lock(&LOCK_thd_kill); - -#ifdef WITH_WSREP - delete wsrep_rgi; - wsrep_rgi= nullptr; -#endif /* WITH_WSREP */ my_free(const_cast<char*>(db.str)); db= null_clex_str; #ifndef EMBEDDED_LIBRARY @@ -1657,8 +1622,8 @@ void THD::free_connection() net.vio= nullptr; net_end(&net); #endif - if (!cleanup_done) - cleanup(true); // We have locked THD::LOCK_thd_kill + if (!cleanup_done) + cleanup(); ha_close_connection(this); plugin_thdvar_cleanup(this); mysql_audit_free_thd(this); @@ -1670,8 +1635,6 @@ void THD::free_connection() profiling.restart(); // Reset profiling #endif debug_sync_reset_thread(this); - mysql_mutex_unlock(&LOCK_thd_kill); - mysql_mutex_unlock(&LOCK_thd_data); } /* @@ -1727,6 +1690,17 @@ THD::~THD() if (!status_in_global) add_status_to_global(); + /* + Other threads may have a lock on LOCK_thd_kill to ensure that this + THD is not deleted while they access it. The following mutex_lock + ensures that no one else is using this THD and it's now safe to delete + */ + mysql_mutex_lock(&LOCK_thd_kill); + mysql_mutex_unlock(&LOCK_thd_kill); + +#ifdef WITH_WSREP + delete wsrep_rgi; +#endif if (!free_connection_done) free_connection(); @@ -1917,7 +1891,7 @@ void THD::awake_no_mutex(killed_state state_to_set) DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d", this, current_thd, (int) state_to_set)); THD_CHECK_SENTRY(this); - if (WSREP_NNULL(this)) mysql_mutex_assert_owner(&LOCK_thd_data); + mysql_mutex_assert_owner(&LOCK_thd_data); mysql_mutex_assert_owner(&LOCK_thd_kill); print_aborted_warning(3, "KILLED"); @@ -1950,15 +1924,21 @@ void THD::awake_no_mutex(killed_state state_to_set) } /* Interrupt target waiting inside a storage engine. */ - if (IF_WSREP(state_to_set != NOT_KILLED && !wsrep_is_bf_aborted(this), - state_to_set != NOT_KILLED)) + if (state_to_set != NOT_KILLED && !wsrep_is_bf_aborted(this)) ha_kill_query(this, thd_kill_level(this)); - /* Broadcast a condition to kick the target if it is waiting on it. */ + abort_current_cond_wait(false); + DBUG_VOID_RETURN; +} + +/* Broadcast a condition to kick the target if it is waiting on it. */ +void THD::abort_current_cond_wait(bool force) +{ + mysql_mutex_assert_owner(&LOCK_thd_kill); if (mysys_var) { mysql_mutex_lock(&mysys_var->mutex); - if (!system_thread) // Don't abort locks + if (!system_thread || force) // Don't abort locks mysys_var->abort=1; /* @@ -2016,7 +1996,6 @@ void THD::awake_no_mutex(killed_state state_to_set) } mysql_mutex_unlock(&mysys_var->mutex); } - DBUG_VOID_RETURN; } @@ -2070,16 +2049,7 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, mysql_mutex_lock(&in_use->LOCK_thd_kill); if (in_use->killed < KILL_CONNECTION) in_use->set_killed_no_mutex(KILL_CONNECTION); - if (in_use->mysys_var) - { - mysql_mutex_lock(&in_use->mysys_var->mutex); - if (in_use->mysys_var->current_cond) - mysql_cond_broadcast(in_use->mysys_var->current_cond); - - /* Abort if about to wait in thr_upgrade_write_delay_lock */ - in_use->mysys_var->abort= 1; - mysql_mutex_unlock(&in_use->mysys_var->mutex); - } + in_use->abort_current_cond_wait(true); mysql_mutex_unlock(&in_use->LOCK_thd_kill); signalled= TRUE; } @@ -5229,6 +5199,18 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd) DBUG_EXECUTE_IF("disable_thd_need_ordering_with", return 1;); if (!thd || !other_thd) return 1; +#ifdef WITH_WSREP + /* wsrep applier, replayer and TOI processing threads are ordered + by replication provider, relaxed GAP locking protocol can be used + between high priority wsrep threads. + Note that wsrep_thd_is_BF() doesn't take LOCK_thd_data for either thd, + the caller should guarantee that the BF state won't change. + (e.g. InnoDB does it by keeping lock_sys.mutex locked) + */ + if (WSREP_ON && wsrep_thd_is_BF(thd, false) && + wsrep_thd_is_BF(other_thd, false)) + return 0; +#endif /* WITH_WSREP */ rgi= thd->rgi_slave; other_rgi= other_thd->rgi_slave; if (!rgi || !other_rgi) |