summaryrefslogtreecommitdiffstats
path: root/storage/innobase/include/trx0purge.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--storage/innobase/include/trx0purge.h181
1 files changed, 101 insertions, 80 deletions
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index 0f4f8afa..1fb6cd68 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -55,80 +55,74 @@ Run a purge batch.
@return number of undo log pages handled in the batch */
ulint trx_purge(ulint n_tasks, ulint history_size);
-/** Rollback segements from a given transaction with trx-no
-scheduled for purge. */
-class TrxUndoRsegs {
-private:
- typedef std::vector<trx_rseg_t*, ut_allocator<trx_rseg_t*> >
- trx_rsegs_t;
-public:
- typedef trx_rsegs_t::iterator iterator;
- typedef trx_rsegs_t::const_iterator const_iterator;
-
- TrxUndoRsegs() = default;
-
- /** Constructor */
- TrxUndoRsegs(trx_rseg_t& rseg)
- : trx_no(rseg.last_trx_no()), m_rsegs(1, &rseg) {}
- /** Constructor */
- TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg)
- : trx_no(trx_no), m_rsegs(1, &rseg) {}
-
- bool operator!=(const TrxUndoRsegs& other) const
- { return trx_no != other.trx_no; }
- bool empty() const { return m_rsegs.empty(); }
- void erase(iterator& it) { m_rsegs.erase(it); }
- iterator begin() { return(m_rsegs.begin()); }
- iterator end() { return(m_rsegs.end()); }
- const_iterator begin() const { return m_rsegs.begin(); }
- const_iterator end() const { return m_rsegs.end(); }
-
- /** Compare two TrxUndoRsegs based on trx_no.
- @param elem1 first element to compare
- @param elem2 second element to compare
- @return true if elem1 > elem2 else false.*/
- bool operator()(const TrxUndoRsegs& lhs, const TrxUndoRsegs& rhs)
- {
- return(lhs.trx_no > rhs.trx_no);
- }
-
- /** Copy of trx_rseg_t::last_trx_no() */
- trx_id_t trx_no= 0;
-private:
- /** Rollback segments of a transaction, scheduled for purge. */
- trx_rsegs_t m_rsegs{};
-};
-
-typedef std::priority_queue<
- TrxUndoRsegs,
- std::vector<TrxUndoRsegs, ut_allocator<TrxUndoRsegs> >,
- TrxUndoRsegs> purge_pq_t;
-
-/** Chooses the rollback segment with the oldest committed transaction */
-struct TrxUndoRsegsIterator {
- /** Constructor */
- TrxUndoRsegsIterator();
- /** Sets the next rseg to purge in purge_sys.
- Executed in the purge coordinator thread.
- @retval false when nothing is to be purged
- @retval true when purge_sys.rseg->latch was locked */
- inline bool set_next();
-
-private:
- // Disable copying
- TrxUndoRsegsIterator(const TrxUndoRsegsIterator&);
- TrxUndoRsegsIterator& operator=(const TrxUndoRsegsIterator&);
-
- /** The current element to process */
- TrxUndoRsegs m_rsegs;
- /** Track the current element in m_rsegs */
- TrxUndoRsegs::const_iterator m_iter;
-};
-
/** The control structure used in the purge operation */
class purge_sys_t
{
- friend TrxUndoRsegsIterator;
+ /** Min-heap based priority queue of (trx_no, trx_sys.rseg_array index)
+ pairs, ordered on trx_no. The highest 64-TRX_NO_SHIFT bits of each element is
+ trx_no, the lowest 8 bits is rseg's index in trx_sys.rseg_array. */
+ class purge_queue
+ {
+ public:
+ typedef std::vector<uint64_t, ut_allocator<uint64_t>> container_type;
+ /** Number of bits reseved to shift trx_no in purge queue element */
+ static constexpr unsigned TRX_NO_SHIFT= 8;
+
+ bool empty() const { return m_array.empty(); }
+ void clear() { m_array.clear(); }
+
+ /** Push (trx_no, trx_sys.rseg_array index) into min-heap.
+ @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index)) */
+ void push_trx_no_rseg(container_type::value_type trx_no_rseg)
+ {
+ m_array.push_back(trx_no_rseg);
+ std::push_heap(m_array.begin(), m_array.end(),
+ std::greater<container_type::value_type>());
+ }
+
+ /** Push rseg to priority queue.
+ @param trx_no trx_no of committed transaction
+ @param rseg rseg of committed transaction*/
+ void push(trx_id_t trx_no, const trx_rseg_t &rseg)
+ {
+ ut_ad(trx_no < 1ULL << (DATA_TRX_ID_LEN * CHAR_BIT));
+ ut_ad(&rseg >= trx_sys.rseg_array);
+ ut_ad(&rseg < trx_sys.rseg_array + TRX_SYS_N_RSEGS);
+ push_trx_no_rseg(trx_no << TRX_NO_SHIFT |
+ byte(&rseg - trx_sys.rseg_array));
+ }
+
+ /** Extracts rseg from (trx_no, trx_sys.rseg_array index) pair.
+ @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index)
+ @return pointer to rseg in trx_sys.rseg_array */
+ static trx_rseg_t *rseg(container_type::value_type trx_no_rseg) {
+ byte i= static_cast<byte>(trx_no_rseg);
+ ut_ad(i < TRX_SYS_N_RSEGS);
+ return &trx_sys.rseg_array[i];
+ }
+
+ /** Pop rseg from priority queue.
+ @return pointer to popped trx_rseg_t object */
+ trx_rseg_t *pop()
+ {
+ ut_ad(!empty());
+ std::pop_heap(m_array.begin(), m_array.end(),
+ std::greater<container_type::value_type>());
+ trx_rseg_t *r = rseg(m_array.back());
+ m_array.pop_back();
+ return r;
+ }
+
+ /** Clone m_array.
+ @return m_array clone */
+ container_type clone_container() const{ return m_array; }
+
+ private:
+ /** Array of (trx_no, trx_sys.rseg_array index) pairs. */
+ container_type m_array;
+ };
+
+
public:
/** latch protecting view, m_enabled */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mutable srw_spin_lock latch;
@@ -244,15 +238,36 @@ private:
record */
uint16_t hdr_offset; /*!< Header byte offset on the page */
+ /** Binary min-heap of (trx_no, trx_sys.rseg_array index) pairs, ordered on
+ trx_no. It is protected by the pq_mutex */
+ purge_queue purge_queue;
+
+ /** Mutex protecting purge_queue */
+ mysql_mutex_t pq_mutex;
- TrxUndoRsegsIterator
- rseg_iter; /*!< Iterator to get the next rseg
- to process */
public:
- purge_pq_t purge_queue; /*!< Binary min-heap, ordered on
- TrxUndoRsegs::trx_no. It is protected
- by the pq_mutex */
- mysql_mutex_t pq_mutex; /*!< Mutex protecting purge_queue */
+
+ void enqueue(trx_id_t trx_no, const trx_rseg_t &rseg) {
+ mysql_mutex_assert_owner(&pq_mutex);
+ purge_queue.push(trx_no, rseg);
+ }
+
+ /** Push to purge queue without acquiring pq_mutex.
+ @param rseg rseg to push */
+ void enqueue(const trx_rseg_t &rseg) { enqueue(rseg.last_trx_no(), rseg); }
+
+ /** Clone purge queue container.
+ @return purge queue container clone */
+ purge_queue::container_type clone_queue_container() const {
+ mysql_mutex_assert_owner(&pq_mutex);
+ return purge_queue.clone_container();
+ }
+
+ /** Acquare purge_queue_mutex */
+ void queue_lock() { mysql_mutex_lock(&pq_mutex); }
+
+ /** Release purge queue mutex */
+ void queue_unlock() { mysql_mutex_unlock(&pq_mutex); }
/** innodb_undo_log_truncate=ON state;
only modified by purge_coordinator_callback() */
@@ -332,8 +347,9 @@ private:
/** Update the last not yet purged history log info in rseg when
we have purged a whole undo log. Advances also purge_trx_no
- past the purged log. */
- void rseg_get_next_history_log();
+ past the purged log.
+ @return whether anything is to be purged */
+ bool rseg_get_next_history_log();
public:
/**
@@ -438,6 +454,11 @@ public:
@param already_stopped True indicates purge threads were
already stopped */
void stop_FTS(const dict_table_t &table, bool already_stopped=false);
+
+ /** Cleanse purge queue to remove the rseg that reside in undo-tablespace
+ marked for truncate.
+ @param space undo tablespace being truncated */
+ void cleanse_purge_queue(const fil_space_t &space);
};
/** The global data structure coordinating a purge */