Commit 0ca2ea1a authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-14638 - Replace trx_sys_t::rw_trx_set with LF_HASH

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.
parent 380069c2
...@@ -45,7 +45,7 @@ index record. ...@@ -45,7 +45,7 @@ index record.
@param[in] rec secondary index record @param[in] rec secondary index record
@param[in] index secondary index @param[in] index secondary index
@param[in] offsets rec_get_offsets(rec, 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 */ @retval NULL if the record was committed */
trx_t* trx_t*
row_vers_impl_x_locked( row_vers_impl_x_locked(
......
...@@ -598,7 +598,7 @@ class rw_trx_hash_t ...@@ -598,7 +598,7 @@ class rw_trx_hash_t
With do_ref_count == true caller may dereference trx even if it is not With do_ref_count == true caller may dereference trx even if it is not
holding lock_sys->mutex. Caller is responsible for calling 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 Ideally this method should get caller rw_trx_hash_pins along with trx
object as a parameter, similar to insert() and erase(). However most object as a parameter, similar to insert() and erase(). However most
...@@ -646,7 +646,7 @@ class rw_trx_hash_t ...@@ -646,7 +646,7 @@ class rw_trx_hash_t
if ((trx= element->trx)) if ((trx= element->trx))
{ {
if (do_ref_count) if (do_ref_count)
trx_reference(trx); trx->reference();
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
mutex_enter(&trx->mutex); mutex_enter(&trx->mutex);
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
......
...@@ -532,26 +532,6 @@ void ...@@ -532,26 +532,6 @@ void
trx_set_rw_mode( trx_set_rw_mode(
trx_t* trx); 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] requestor Transaction requesting the lock
@param[in] holder Transaction holding the lock @param[in] holder Transaction holding the lock
...@@ -889,6 +869,19 @@ struct TrxVersion { ...@@ -889,6 +869,19 @@ struct TrxVersion {
typedef std::list<TrxVersion, ut_allocator<TrxVersion> > hit_list_t; typedef std::list<TrxVersion, ut_allocator<TrxVersion> > hit_list_t;
struct trx_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 TrxMutex mutex; /*!< Mutex protecting the fields
state and lock (except some fields state and lock (except some fields
of lock, which are protected by of lock, which are protected by
...@@ -1235,14 +1228,6 @@ struct trx_t { ...@@ -1235,14 +1228,6 @@ struct trx_t {
const char* start_file; /*!< Filename where it was started */ const char* start_file; /*!< Filename where it was started */
#endif /* UNIV_DEBUG */ #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 /** Version of this instance. It is incremented each time the
instance is re-used in trx_start_low(). It is used to track instance is re-used in trx_start_low(). It is used to track
whether a transaction has been restarted since it was tagged whether a transaction has been restarted since it was tagged
...@@ -1311,6 +1296,33 @@ struct trx_t { ...@@ -1311,6 +1296,33 @@ struct trx_t {
return(assign_temp_rseg()); 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: private:
/** Assign a rollback segment for modifying temporary tables. /** Assign a rollback segment for modifying temporary tables.
@return the assigned rollback segment */ @return the assigned rollback segment */
......
...@@ -213,34 +213,6 @@ ok: ...@@ -213,34 +213,6 @@ ok:
trx->dict_operation = op; trx->dict_operation = op;
} }
/**
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 @param trx Get the active view for this transaction, if one exists
@return the transaction's read view or NULL if one not assigned. */ @return the transaction's read view or NULL if one not assigned. */
......
...@@ -6813,7 +6813,7 @@ lock_rec_convert_impl_to_expl_for_trx( ...@@ -6813,7 +6813,7 @@ lock_rec_convert_impl_to_expl_for_trx(
trx_t* trx, /*!< in/out: active transaction */ trx_t* trx, /*!< in/out: active transaction */
ulint heap_no)/*!< in: rec heap number to lock */ 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(page_rec_is_leaf(rec));
ut_ad(!rec_is_default_row(rec, index)); ut_ad(!rec_is_default_row(rec, index));
...@@ -6837,7 +6837,7 @@ lock_rec_convert_impl_to_expl_for_trx( ...@@ -6837,7 +6837,7 @@ lock_rec_convert_impl_to_expl_for_trx(
lock_mutex_exit(); lock_mutex_exit();
trx_release_reference(trx); trx->release_reference();
DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx"); DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx");
} }
...@@ -6883,7 +6883,7 @@ lock_rec_convert_impl_to_expl( ...@@ -6883,7 +6883,7 @@ lock_rec_convert_impl_to_expl(
if (trx != 0) { if (trx != 0) {
ulint heap_no = page_rec_get_heap_no(rec); 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 /* If the transaction is still active and has no
explicit x-lock set on the record, set one for it. explicit x-lock set on the record, set one for it.
...@@ -7655,13 +7655,13 @@ lock_trx_release_locks( ...@@ -7655,13 +7655,13 @@ lock_trx_release_locks(
trx->state = TRX_STATE_COMMITTED_IN_MEMORY; trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
/*--------------------------------------*/ /*--------------------------------------*/
if (trx_is_referenced(trx)) { if (trx->is_referenced()) {
ut_a(release_lock); ut_a(release_lock);
lock_mutex_exit(); lock_mutex_exit();
while (trx_is_referenced(trx)) { while (trx->is_referenced()) {
trx_mutex_exit(trx); trx_mutex_exit(trx);
...@@ -7681,7 +7681,7 @@ lock_trx_release_locks( ...@@ -7681,7 +7681,7 @@ lock_trx_release_locks(
trx_mutex_enter(trx); trx_mutex_enter(trx);
} }
ut_ad(!trx_is_referenced(trx)); ut_ad(!trx->is_referenced());
/* If the background thread trx_rollback_or_clean_recovered() /* If the background thread trx_rollback_or_clean_recovered()
is still active then there is a chance that the rollback is still active then there is a chance that the rollback
......
...@@ -4982,7 +4982,7 @@ row_search_mvcc( ...@@ -4982,7 +4982,7 @@ row_search_mvcc(
trx, rec, index, offsets)) { trx, rec, index, offsets)) {
/* The record belongs to an active /* The record belongs to an active
transaction. We must acquire a lock. */ transaction. We must acquire a lock. */
trx_release_reference(t); t->release_reference();
} else { } else {
/* The secondary index record does not /* The secondary index record does not
point to a delete-marked clustered index point to a delete-marked clustered index
......
...@@ -73,7 +73,7 @@ index record. ...@@ -73,7 +73,7 @@ index record.
@param[in] index secondary index @param[in] index secondary index
@param[in] offsets rec_get_offsets(rec, index) @param[in] offsets rec_get_offsets(rec, index)
@param[in,out] mtr mini-transaction @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 */ @retval NULL if the record was committed */
UNIV_INLINE UNIV_INLINE
trx_t* trx_t*
...@@ -217,7 +217,7 @@ row_vers_impl_x_locked_low( ...@@ -217,7 +217,7 @@ row_vers_impl_x_locked_low(
or updated, the leaf page record always is or updated, the leaf page record always is
created with a clear delete-mark flag. created with a clear delete-mark flag.
(We never insert a delete-marked record.) */ (We never insert a delete-marked record.) */
trx_release_reference(trx); trx->release_reference();
trx = 0; trx = 0;
} }
...@@ -328,7 +328,7 @@ row_vers_impl_x_locked_low( ...@@ -328,7 +328,7 @@ row_vers_impl_x_locked_low(
/* prev_version was the first version modified by /* prev_version was the first version modified by
the trx_id transaction: no implicit x-lock */ the trx_id transaction: no implicit x-lock */
trx_release_reference(trx); trx->release_reference();
trx = 0; trx = 0;
break; break;
} }
...@@ -350,7 +350,7 @@ index record. ...@@ -350,7 +350,7 @@ index record.
@param[in] rec secondary index record @param[in] rec secondary index record
@param[in] index secondary index @param[in] index secondary index
@param[in] offsets rec_get_offsets(rec, 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 */ @retval NULL if the record was committed */
trx_t* trx_t*
row_vers_impl_x_locked( row_vers_impl_x_locked(
...@@ -398,7 +398,7 @@ row_vers_impl_x_locked( ...@@ -398,7 +398,7 @@ row_vers_impl_x_locked(
caller_trx, clust_rec, clust_index, rec, index, caller_trx, clust_rec, clust_index, rec, index,
offsets, &mtr); offsets, &mtr);
ut_ad(trx == 0 || trx_is_referenced(trx)); ut_ad(trx == 0 || trx->is_referenced());
} }
mtr_commit(&mtr); mtr_commit(&mtr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment