diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2018-01-27 19:30:18 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2018-01-31 15:18:21 +0400 |
commit | 53cc9aa5be63b4dd03aba804aebaa3bd470dab9c (patch) | |
tree | f6ceb3cbd4e2b2e16c575e363f583ecdc8837f41 /storage/innobase/read | |
parent | af566d8a63f908c76d43957e790e861d944486b0 (diff) | |
download | mariadb-git-53cc9aa5be63b4dd03aba804aebaa3bd470dab9c.tar.gz |
MDEV-15104 - Remove trx_sys_t::rw_trx_ids
Take snapshot of registered read-write transaction identifiers directly
from rw_trx_hash. It immediately saves one trx_sys.mutex lock, reduces
size of another critical section protected by this mutex, and makes
further optimisations like removing trx_sys_t::serialisation_list
possible.
Downside of this approach is bigger overhead for view opening, because
iterating LF_HASH is more expensive compared to taking snapshot of an
array. However for low concurrency overhead difference is negligible,
while for high concurrency mutex is much bigger evil.
Currently we still take trx_sys.mutex to serialise ReadView creation.
This is required to keep serialisation_list ordered by trx->no as well
as not to let purge thread to create more recent snapshot while another
thread gets suspended during creation of older snapshot. This will
become completely mutex free along with serialisation_list removal.
Compared to previous implementation removing element from rw_trx_hash
and serialisation_list is not atomic. We disregard all possible bad
consequences (if there're any) since it will be solved along with
serialisation_list removal.
Diffstat (limited to 'storage/innobase/read')
-rw-r--r-- | storage/innobase/read/read0read.cc | 62 |
1 files changed, 19 insertions, 43 deletions
diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc index b2dea25aa9f..93a20f84f67 100644 --- a/storage/innobase/read/read0read.cc +++ b/storage/innobase/read/read0read.cc @@ -207,49 +207,25 @@ MVCC::validate() const } #endif /* UNIV_DEBUG */ -/** -Opens a read view where exactly the transactions serialized before this -point in time are seen in the view. */ - -void ReadView::clone() -{ - ut_ad(mutex_own(&trx_sys.mutex)); - m_low_limit_no = m_low_limit_id = trx_sys.get_max_trx_id(); - m_ids= trx_sys.rw_trx_ids; -#ifdef UNIV_DEBUG - /* Original assertion was here to make sure that rw_trx_ids and - rw_trx_hash are in sync and they hold either ACTIVE or PREPARED - transaction. - - 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 - condition because we need trx->element->mutex locked to perform this - check (see how it is done in find()). - - Now rw_trx_ids and rw_trx_hash may get out of sync for a short while: - when transaction is registered it first gets added into rw_trx_ids - under trx_sys.mutex protection and then to rw_trx_hash without mutex - 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.is_registered(current_trx(), *it)); - } -#endif /* UNIV_DEBUG */ - m_up_limit_id = m_ids.empty() ? m_low_limit_id : m_ids.front(); - ut_ad(m_up_limit_id <= m_low_limit_id); - - if (UT_LIST_GET_LEN(trx_sys.serialisation_list) > 0) { - const trx_t* trx; +/** + Opens a read view where exactly the transactions serialized before this + point in time are seen in the view. - trx = UT_LIST_GET_FIRST(trx_sys.serialisation_list); + @param[in,out] trx transaction +*/ - if (trx->no < m_low_limit_no) { - m_low_limit_no = trx->no; - } - } +void ReadView::open(trx_t *trx) +{ + ut_ad(mutex_own(&trx_sys.mutex)); + trx_sys.snapshot_ids(trx, &m_ids, &m_low_limit_id); + m_low_limit_no= m_low_limit_id; + m_up_limit_id= m_ids.empty() ? m_low_limit_id : m_ids.front(); + ut_ad(m_up_limit_id <= m_low_limit_id); + + if (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys.serialisation_list)) + if (trx->no < m_low_limit_no) + m_low_limit_no= trx->no; } @@ -324,7 +300,7 @@ void MVCC::view_open(trx_t* trx) } mutex_enter(&trx_sys.mutex); - trx->read_view.clone(); + trx->read_view.open(trx); if (trx->read_view.is_registered()) UT_LIST_REMOVE(m_views, &trx->read_view); else @@ -375,7 +351,7 @@ MVCC::clone_oldest_view(ReadView* view) { mutex_enter(&trx_sys.mutex); /* Find oldest view. */ - for (ReadView *oldest_view = UT_LIST_GET_LAST(m_views); + for (const ReadView *oldest_view = UT_LIST_GET_LAST(m_views); oldest_view != NULL; oldest_view = UT_LIST_GET_PREV(m_view_list, oldest_view)) { @@ -387,7 +363,7 @@ MVCC::clone_oldest_view(ReadView* view) } } /* No views in the list: snapshot current state. */ - view->clone(); + view->open(0); mutex_exit(&trx_sys.mutex); } |