From 55277e8840f359ed36a99359a7e21f03af72a78a Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 25 Jan 2018 18:29:59 +0400 Subject: [PATCH] MDEV-15059 - Misc small InnoDB scalability fixes Form better trx_sys API. --- storage/innobase/btr/btr0cur.cc | 7 ++++--- storage/innobase/include/trx0sys.h | 29 ++++++++++++++++++++------ storage/innobase/lock/lock0lock.cc | 4 ++-- storage/innobase/read/read0read.cc | 4 ++-- storage/innobase/row/row0row.cc | 5 +++-- storage/innobase/row/row0sel.cc | 2 +- storage/innobase/row/row0vers.cc | 6 +++--- storage/innobase/trx/trx0trx.cc | 33 +++++------------------------- 8 files changed, 43 insertions(+), 47 deletions(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 777feb42f2a26..aa3d3165709ba 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -482,10 +482,11 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr) /* In fact, because we only ever append fields to the 'default value' record, it is also OK to perform READ UNCOMMITTED and then ignore any extra fields, provided that - trx_sys.rw_trx_hash.find(DB_TRX_ID). */ + trx_sys.is_registered(DB_TRX_ID). */ if (rec_offs_n_fields(offsets) > index->n_fields - && !trx_sys.rw_trx_hash.find(row_get_rec_trx_id(rec, index, - offsets))) { + && !trx_sys.is_registered(current_trx(), + row_get_rec_trx_id(rec, index, + offsets))) { goto inconsistent; } diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 47ea505ca54f4..7b339e10591c9 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -682,12 +682,6 @@ class rw_trx_hash_t } - trx_t *find(trx_id_t trx_id, bool do_ref_count= false) - { - return find(current_trx(), trx_id, do_ref_count); - } - - /** Inserts trx to lock-free hash. @@ -974,6 +968,29 @@ struct trx_sys_t { ulint any_active_transactions(); + /** Registers read-write transaction. */ + void register_rw(trx_t *trx) + { + mutex_enter(&mutex); + trx->id= get_new_trx_id(); + rw_trx_ids.push_back(trx->id); + mutex_exit(&mutex); + rw_trx_hash.insert(trx); + } + + + bool is_registered(trx_t *caller_trx, trx_id_t id) + { + return rw_trx_hash.find(caller_trx, id); + } + + + trx_t *find(trx_t *caller_trx, trx_id_t id) + { + return rw_trx_hash.find(caller_trx, id, true); + } + + private: static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element, trx_id_t *id) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index eb6cf784b4aa5..9d7f6d61fc4af 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5742,7 +5742,7 @@ lock_rec_queue_validate( /* Unlike the non-debug code, this invariant can only succeed if the check and assertion are covered by the lock mutex. */ - const trx_t *impl_trx = trx_sys.rw_trx_hash.find( + const trx_t *impl_trx = trx_sys.rw_trx_hash.find(current_trx(), lock_clust_rec_some_has_impl(rec, index, offsets)); ut_ad(lock_mutex_own()); @@ -6387,7 +6387,7 @@ lock_rec_convert_impl_to_expl( trx_id = lock_clust_rec_some_has_impl(rec, index, offsets); - trx = trx_sys.rw_trx_hash.find(caller_trx, trx_id, true); + trx = trx_sys.find(caller_trx, trx_id); } else { ut_ad(!dict_index_is_online_ddl(index)); diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc index 8eca93f329a94..c018ab170d0d5 100644 --- a/storage/innobase/read/read0read.cc +++ b/storage/innobase/read/read0read.cc @@ -222,7 +222,7 @@ void ReadView::clone() rw_trx_hash are in sync and they hold either ACTIVE or PREPARED transaction. - Now rw_trx_hash.find() does + Now rw_trx_hash_t::find() does ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || trx_state_eq(trx, TRX_STATE_PREPARED)). No need to repeat it here. We even can't repeat it here: it'll be race @@ -235,7 +235,7 @@ void ReadView::clone() protection. Thus we need repeat this lookup. */ for (trx_ids_t::const_iterator it = trx_sys.rw_trx_ids.begin(); it != trx_sys.rw_trx_ids.end(); ++it) { - while (!trx_sys.rw_trx_hash.find(*it)); + while (!trx_sys.is_registered(current_trx(), *it)); } #endif /* UNIV_DEBUG */ m_up_limit_id = m_ids.empty() ? m_low_limit_id : m_ids.front(); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index ced1c363458ce..a3248dc19ee46 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -415,8 +415,9 @@ row_build_low( times, and the cursor restore can happen multiple times for single insert or update statement. */ ut_a(!rec_offs_any_null_extern(rec, offsets) - || trx_sys.rw_trx_hash.find(row_get_rec_trx_id(rec, index, - offsets))); + || trx_sys.is_registered(current_trx(), + row_get_rec_trx_id(rec, index, + offsets))); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ if (type != ROW_COPY_POINTERS) { diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 0f9daa2a17ea5..4888a4e7500e9 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4870,7 +4870,7 @@ row_search_mvcc( /* In delete-marked records, DB_TRX_ID must always refer to an existing undo log record. */ ut_ad(trx_id); - if (!trx_sys.rw_trx_hash.find(trx, trx_id)) { + if (!trx_sys.is_registered(trx, trx_id)) { /* The clustered index record was delete-marked in a committed transaction. Ignore the record. */ diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index ad8242fffbe82..11624068d2b27 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -121,7 +121,7 @@ row_vers_impl_x_locked_low( DBUG_RETURN(0); } - trx_t* trx = trx_sys.rw_trx_hash.find(caller_trx, trx_id, true); + trx_t* trx = trx_sys.find(caller_trx, trx_id); if (trx == 0) { /* The transaction that modified or inserted clust_rec is no @@ -186,7 +186,7 @@ row_vers_impl_x_locked_low( inserting a delete-marked record. */ ut_ad(prev_version || !rec_get_deleted_flag(version, comp) - || !trx_sys.rw_trx_hash.find(caller_trx, trx_id)); + || !trx_sys.is_registered(caller_trx, trx_id)); /* Free version and clust_offsets. */ mem_heap_free(old_heap); @@ -1280,7 +1280,7 @@ row_vers_build_for_semi_consistent_read( rec_trx_id = version_trx_id; } - if (!trx_sys.rw_trx_hash.find(caller_trx, version_trx_id)) { + if (!trx_sys.is_registered(caller_trx, version_trx_id)) { committed_version_trx: /* We found a version that belongs to a committed transaction: return it. */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 90409eef7788c..99993e5fb4632 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -937,7 +937,7 @@ trx_lists_init_at_db_start() for (undo = UT_LIST_GET_FIRST(rseg->undo_list); undo != NULL; undo = UT_LIST_GET_NEXT(undo_list, undo)) { - trx_t *trx = trx_sys.rw_trx_hash.find(undo->trx_id); + trx_t *trx = trx_sys.rw_trx_hash.find(0, undo->trx_id); if (!trx) { trx_resurrect(undo, rseg, start_time, &rows_to_undo, false); @@ -1094,11 +1094,7 @@ trx_t::assign_temp_rseg() rsegs.m_noredo.rseg = rseg; if (id == 0) { - mutex_enter(&trx_sys.mutex); - id = trx_sys.get_new_trx_id(); - trx_sys.rw_trx_ids.push_back(id); - mutex_exit(&trx_sys.mutex); - trx_sys.rw_trx_hash.insert(this); + trx_sys.register_rw(this); } ut_ad(!rseg->is_persistent()); @@ -1186,12 +1182,7 @@ trx_start_low( || srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); - mutex_enter(&trx_sys.mutex); - trx->id = trx_sys.get_new_trx_id(); - trx_sys.rw_trx_ids.push_back(trx->id); - mutex_exit(&trx_sys.mutex); - trx_sys.rw_trx_hash.insert(trx); - + trx_sys.register_rw(trx); } else { trx->id = 0; @@ -1202,17 +1193,8 @@ trx_start_low( to write to the temporary table. */ if (read_write) { - - mutex_enter(&trx_sys.mutex); - ut_ad(!srv_read_only_mode); - - trx->id = trx_sys.get_new_trx_id(); - - trx_sys.rw_trx_ids.push_back(trx->id); - - mutex_exit(&trx_sys.mutex); - trx_sys.rw_trx_hash.insert(trx); + trx_sys.register_rw(trx); } } else { ut_ad(!read_write); @@ -2721,14 +2703,9 @@ trx_set_rw_mode( based on in-consistent view formed during promotion. */ trx->rsegs.m_redo.rseg = trx_assign_rseg_low(); - ut_ad(trx->rsegs.m_redo.rseg != 0); - mutex_enter(&trx_sys.mutex); - trx->id = trx_sys.get_new_trx_id(); - trx_sys.rw_trx_ids.push_back(trx->id); - mutex_exit(&trx_sys.mutex); - trx_sys.rw_trx_hash.insert(trx); + trx_sys.register_rw(trx); /* So that we can see our own changes. */ if (trx->read_view.is_open()) {