diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2017-12-20 14:59:36 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2018-01-10 21:10:42 +0400 |
commit | e6933ee1018ef7644752e6489ebde42eb88f6c21 (patch) | |
tree | 1604e0ce14b32a853a9d56eaba9c4e5ac244495a | |
parent | 01c4327fdd7eca151b757e2721850c85c9116f4d (diff) | |
download | mariadb-git-bb-10.3-MDEV14638-push.tar.gz |
MDEV-14638 - Replace trx_sys_t::rw_trx_set with LF_HASHbb-10.3-MDEV14638-push
trx reference counter was updated under mutex and read without any
protection. This is both slow and unsafe. Use atomic operations for
reference counter accesses.
-rw-r--r-- | storage/innobase/include/row0vers.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/trx0sys.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/trx0trx.h | 68 | ||||
-rw-r--r-- | storage/innobase/include/trx0trx.ic | 28 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 12 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0vers.cc | 10 |
7 files changed, 55 insertions, 71 deletions
diff --git a/storage/innobase/include/row0vers.h b/storage/innobase/include/row0vers.h index ee0b1528683..645f11faaad 100644 --- a/storage/innobase/include/row0vers.h +++ b/storage/innobase/include/row0vers.h @@ -45,7 +45,7 @@ index record. @param[in] rec secondary index record @param[in] index secondary index @param[in] offsets rec_get_offsets(rec, index) -@return the active transaction; trx_release_reference() must be invoked +@return the active transaction; trx->release_reference() must be invoked @retval NULL if the record was committed */ trx_t* row_vers_impl_x_locked( diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 2e87d500896..e87aa1bef6c 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -598,7 +598,7 @@ public: With do_ref_count == true caller may dereference trx even if it is not holding lock_sys->mutex. Caller is responsible for calling - trx_release_reference() when it is done playing with trx. + trx->release_reference() when it is done playing with trx. Ideally this method should get caller rw_trx_hash_pins along with trx object as a parameter, similar to insert() and erase(). However most @@ -646,7 +646,7 @@ public: if ((trx= element->trx)) { if (do_ref_count) - trx_reference(trx); + trx->reference(); #ifdef UNIV_DEBUG mutex_enter(&trx->mutex); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 9366d20b1f5..f6a997b8a0f 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -533,26 +533,6 @@ trx_set_rw_mode( trx_t* trx); /** -Increase the reference count. -@param trx Transaction that is being referenced */ -UNIV_INLINE -void -trx_reference( - trx_t* trx); - -/** -Release the transaction. Decrease the reference count. -@param trx Transaction that is being released */ -UNIV_INLINE -void -trx_release_reference( - trx_t* trx); - -/** -Check if the transaction is being referenced. */ -#define trx_is_referenced(t) ((t)->n_ref > 0) - -/** @param[in] requestor Transaction requesting the lock @param[in] holder Transaction holding the lock @return the transaction that will be rolled back, null don't care */ @@ -889,6 +869,19 @@ struct TrxVersion { typedef std::list<TrxVersion, ut_allocator<TrxVersion> > hit_list_t; struct trx_t { +private: + /** + Count of references. + + We can't release the locks nor commit the transaction until this reference + is 0. We can change the state to TRX_STATE_COMMITTED_IN_MEMORY to signify + that it is no longer "active". + */ + + int32_t n_ref; + + +public: TrxMutex mutex; /*!< Mutex protecting the fields state and lock (except some fields of lock, which are protected by @@ -1235,14 +1228,6 @@ struct trx_t { const char* start_file; /*!< Filename where it was started */ #endif /* UNIV_DEBUG */ - lint n_ref; /*!< Count of references, protected - by trx_t::mutex. We can't release the - locks nor commit the transaction until - this reference is 0. We can change - the state to COMMITTED_IN_MEMORY to - signify that it is no longer - "active". */ - /** Version of this instance. It is incremented each time the instance is re-used in trx_start_low(). It is used to track whether a transaction has been restarted since it was tagged @@ -1311,6 +1296,33 @@ struct trx_t { return(assign_temp_rseg()); } + + bool is_referenced() + { + return my_atomic_load32_explicit(&n_ref, MY_MEMORY_ORDER_RELAXED) > 0; + } + + + void reference() + { +#ifdef UNIV_DEBUG + int32_t old_n_ref= +#endif + my_atomic_add32_explicit(&n_ref, 1, MY_MEMORY_ORDER_RELAXED); + ut_ad(old_n_ref >= 0); + } + + + void release_reference() + { +#ifdef UNIV_DEBUG + int32_t old_n_ref= +#endif + my_atomic_add32_explicit(&n_ref, -1, MY_MEMORY_ORDER_RELAXED); + ut_ad(old_n_ref > 0); + } + + private: /** Assign a rollback segment for modifying temporary tables. @return the assigned rollback segment */ diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic index cd0b812869d..c288da8bf0b 100644 --- a/storage/innobase/include/trx0trx.ic +++ b/storage/innobase/include/trx0trx.ic @@ -214,34 +214,6 @@ ok: } /** -Increase the reference count. -@param trx Transaction that is being referenced */ -UNIV_INLINE void trx_reference(trx_t *trx) -{ - trx_mutex_enter(trx); - ut_ad(trx->n_ref >= 0); - ++trx->n_ref; - trx_mutex_exit(trx); -} - -/** -Release the transaction. Decrease the reference count. -@param trx Transaction that is being released */ -UNIV_INLINE -void -trx_release_reference( - trx_t* trx) -{ - trx_mutex_enter(trx); - - ut_ad(trx->n_ref > 0); - --trx->n_ref; - - trx_mutex_exit(trx); -} - - -/** @param trx Get the active view for this transaction, if one exists @return the transaction's read view or NULL if one not assigned. */ UNIV_INLINE diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 9a137d6ab08..911cf829c6f 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -6818,7 +6818,7 @@ lock_rec_convert_impl_to_expl_for_trx( trx_t* trx, /*!< in/out: active transaction */ ulint heap_no)/*!< in: rec heap number to lock */ { - ut_ad(trx_is_referenced(trx)); + ut_ad(trx->is_referenced()); ut_ad(page_rec_is_leaf(rec)); ut_ad(!rec_is_default_row(rec, index)); @@ -6842,7 +6842,7 @@ lock_rec_convert_impl_to_expl_for_trx( lock_mutex_exit(); - trx_release_reference(trx); + trx->release_reference(); DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx"); } @@ -6889,7 +6889,7 @@ lock_rec_convert_impl_to_expl( if (trx != 0) { ulint heap_no = page_rec_get_heap_no(rec); - ut_ad(trx_is_referenced(trx)); + ut_ad(trx->is_referenced()); /* If the transaction is still active and has no explicit x-lock set on the record, set one for it. @@ -7661,13 +7661,13 @@ lock_trx_release_locks( trx->state = TRX_STATE_COMMITTED_IN_MEMORY; /*--------------------------------------*/ - if (trx_is_referenced(trx)) { + if (trx->is_referenced()) { ut_a(release_lock); lock_mutex_exit(); - while (trx_is_referenced(trx)) { + while (trx->is_referenced()) { trx_mutex_exit(trx); @@ -7687,7 +7687,7 @@ lock_trx_release_locks( trx_mutex_enter(trx); } - ut_ad(!trx_is_referenced(trx)); + ut_ad(!trx->is_referenced()); /* If the background thread trx_rollback_or_clean_recovered() is still active then there is a chance that the rollback diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index eeb52bfeee3..1395faaad96 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4982,7 +4982,7 @@ wrong_offs: trx, rec, index, offsets)) { /* The record belongs to an active transaction. We must acquire a lock. */ - trx_release_reference(t); + t->release_reference(); } else { /* The secondary index record does not point to a delete-marked clustered index diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 0b8cf63f940..fc8b1b2ec81 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -73,7 +73,7 @@ index record. @param[in] index secondary index @param[in] offsets rec_get_offsets(rec, index) @param[in,out] mtr mini-transaction -@return the active transaction; trx_release_reference() must be invoked +@return the active transaction; trx->release_reference() must be invoked @retval NULL if the record was committed */ UNIV_INLINE trx_t* @@ -217,7 +217,7 @@ row_vers_impl_x_locked_low( or updated, the leaf page record always is created with a clear delete-mark flag. (We never insert a delete-marked record.) */ - trx_release_reference(trx); + trx->release_reference(); trx = 0; } @@ -328,7 +328,7 @@ result_check: /* prev_version was the first version modified by the trx_id transaction: no implicit x-lock */ - trx_release_reference(trx); + trx->release_reference(); trx = 0; break; } @@ -350,7 +350,7 @@ index record. @param[in] rec secondary index record @param[in] index secondary index @param[in] offsets rec_get_offsets(rec, index) -@return the active transaction; trx_release_reference() must be invoked +@return the active transaction; trx->release_reference() must be invoked @retval NULL if the record was committed */ trx_t* row_vers_impl_x_locked( @@ -398,7 +398,7 @@ row_vers_impl_x_locked( caller_trx, clust_rec, clust_index, rec, index, offsets, &mtr); - ut_ad(trx == 0 || trx_is_referenced(trx)); + ut_ad(trx == 0 || trx->is_referenced()); } mtr_commit(&mtr); |