From 900b07908bf9dbd2c79c3a66fc471e6be4cf0d13 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 27 Dec 2017 01:04:08 +0400 Subject: [PATCH] MDEV-14756 - Remove trx_sys_t::rw_trx_list Removed trx_sys_t::n_prepared_recovered_trx: never used. Removed trx_sys_t::n_prepared_trx: used only at shutdown, we can perfectly get this value from rw_trx_hash. --- storage/innobase/include/trx0sys.h | 44 ++++++++++++++++++++++++++++++ storage/innobase/lock/lock0lock.cc | 23 ++-------------- storage/innobase/trx/trx0roll.cc | 2 -- storage/innobase/trx/trx0sys.cc | 31 +++++++++++++++++---- storage/innobase/trx/trx0trx.cc | 8 ------ 5 files changed, 72 insertions(+), 36 deletions(-) diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 6684def347c..65d4765f715 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -561,6 +561,29 @@ class rw_trx_hash_t } + struct eliminate_duplicates_arg + { + trx_ids_t ids; + my_hash_walk_action action; + void *argument; + eliminate_duplicates_arg(size_t size, my_hash_walk_action act, void* arg): + action(act), argument(arg) { ids.reserve(size); } + }; + + + static my_bool eliminate_duplicates(rw_trx_hash_element_t *element, + eliminate_duplicates_arg *arg) + { + for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++) + { + if (*it == element->id) + return 0; + } + arg->ids.push_back(element->id); + return arg->action(element, arg->argument); + } + + public: void init() { @@ -765,6 +788,27 @@ public: { return iterate(current_trx(), action, argument); } + + + /** + Iterates the hash and eliminates duplicate elements. + + @sa iterate() + */ + + int iterate_no_dups(trx_t *caller_trx, my_hash_walk_action action, + void *argument) + { + eliminate_duplicates_arg arg(size() + 32, action, argument); + return iterate(caller_trx, reinterpret_cast + (eliminate_duplicates), &arg); + } + + + int iterate_no_dups(my_hash_walk_action action, void *argument) + { + return iterate_no_dups(current_trx(), action, argument); + } }; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 95cf37c56b1..fe8138df332 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -7601,27 +7601,10 @@ lock_trx_release_locks( trx_t* trx) /*!< in/out: transaction */ { check_trx_state(trx); + ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED) + || trx_state_eq(trx, TRX_STATE_ACTIVE)); - if (trx_state_eq(trx, TRX_STATE_PREPARED)) { - - mutex_enter(&trx_sys->mutex); - - ut_a(trx_sys->n_prepared_trx > 0); - --trx_sys->n_prepared_trx; - - if (trx->is_recovered) { - ut_a(trx_sys->n_prepared_recovered_trx > 0); - trx_sys->n_prepared_recovered_trx--; - } - - mutex_exit(&trx_sys->mutex); - } else { - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); - } - - bool release_lock; - - release_lock = (UT_LIST_GET_LEN(trx->lock.trx_locks) > 0); + bool release_lock = UT_LIST_GET_LEN(trx->lock.trx_locks) > 0; /* Don't take lock_sys mutex if trx didn't acquire any lock. */ if (release_lock) { diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 7886e9d34a9..c516792b40a 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -757,8 +757,6 @@ func_exit: && !srv_undo_sources && srv_fast_shutdown) { fake_prepared: trx->state = TRX_STATE_PREPARED; - trx_sys->n_prepared_trx++; - trx_sys->n_prepared_recovered_trx++; *all = false; goto func_exit; } diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 25b212fe115..002a7e1bf4b 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -621,6 +621,23 @@ trx_sys_close(void) trx_sys = NULL; } + +static my_bool active_count_callback(rw_trx_hash_element_t *element, + uint32_t *count) +{ + mutex_enter(&element->mutex); + if (trx_t *trx= element->trx) + { + mutex_enter(&trx->mutex); + if (trx_state_eq(trx, TRX_STATE_ACTIVE)) + ++*count; + mutex_exit(&trx->mutex); + } + mutex_exit(&element->mutex); + return 0; +} + + /********************************************************************* Check if there are any active (non-prepared) transactions. This is only used to check if it's safe to shutdown. @@ -629,18 +646,20 @@ ulint trx_sys_any_active_transactions(void) /*=================================*/ { - ulint total_trx = trx_sys->rw_trx_hash.size(); + uint32_t total_trx = 0; + + trx_sys->rw_trx_hash.iterate_no_dups( + reinterpret_cast + (active_count_callback), &total_trx); trx_sys_mutex_enter(); for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); trx != NULL; trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) { - total_trx += trx->state != TRX_STATE_NOT_STARTED; + if (trx->state != TRX_STATE_NOT_STARTED && !trx->id) { + total_trx++; + } } - - ut_a(total_trx >= trx_sys->n_prepared_trx); - total_trx -= trx_sys->n_prepared_trx; - trx_sys_mutex_exit(); return(total_trx); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index d507a9f0f12..e851d5cf99e 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -697,7 +697,6 @@ trx_disconnect_from_mysql( ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED)); trx->is_recovered = true; - trx_sys->n_prepared_recovered_trx++; trx->mysql_thd = NULL; /* todo/fixme: suggest to do it at innodb prepare */ trx->will_lock = 0; @@ -873,8 +872,6 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg, << " was in the XA prepared state."; state= TRX_STATE_PREPARED; - trx_sys->n_prepared_trx++; - trx_sys->n_prepared_recovered_trx++; break; default: if (is_old_insert && srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) @@ -1003,10 +1000,6 @@ trx_lists_init_at_db_start() undo->rseg->space; } trx_resurrect_table_locks(trx, undo); - if (trx_state_eq(trx, TRX_STATE_PREPARED)) { - trx_sys->n_prepared_trx++; - trx_sys->n_prepared_recovered_trx++; - } } } } @@ -2631,7 +2624,6 @@ trx_prepare( ut_a(trx->state == TRX_STATE_ACTIVE); trx_sys_mutex_enter(); trx->state = TRX_STATE_PREPARED; - trx_sys->n_prepared_trx++; trx_sys_mutex_exit(); /*--------------------------------------*/