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.
This commit is contained in:
parent
380069c235
commit
0ca2ea1a65
@ -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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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:
|
|||||||
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(
|
|||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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 @@ wrong_offs:
|
|||||||
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.
|
|||||||
@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(
|
|||||||
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 @@ result_check:
|
|||||||
/* 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.
|
|||||||
@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(
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user