summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2017-12-20 14:59:36 +0400
committerSergey Vojtovich <svoj@mariadb.org>2018-01-10 21:10:42 +0400
commite6933ee1018ef7644752e6489ebde42eb88f6c21 (patch)
tree1604e0ce14b32a853a9d56eaba9c4e5ac244495a
parent01c4327fdd7eca151b757e2721850c85c9116f4d (diff)
downloadmariadb-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.h2
-rw-r--r--storage/innobase/include/trx0sys.h4
-rw-r--r--storage/innobase/include/trx0trx.h68
-rw-r--r--storage/innobase/include/trx0trx.ic28
-rw-r--r--storage/innobase/lock/lock0lock.cc12
-rw-r--r--storage/innobase/row/row0sel.cc2
-rw-r--r--storage/innobase/row/row0vers.cc10
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);