summaryrefslogtreecommitdiff
path: root/storage/innobase/include/trx0rseg.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/trx0rseg.h')
-rw-r--r--storage/innobase/include/trx0rseg.h285
1 files changed, 150 insertions, 135 deletions
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index 96655c7020f..1d95b7d2e7a 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2021, MariaDB Corporation.
+Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -24,67 +24,28 @@ Rollback segment
Created 3/26/1996 Heikki Tuuri
*******************************************************/
-#ifndef trx0rseg_h
-#define trx0rseg_h
-
-#include "trx0sys.h"
+#pragma once
+#include "trx0types.h"
#include "fut0lst.h"
-/** Gets a rollback segment header.
-@param[in] space space where placed
-@param[in] page_no page number of the header
-@param[in,out] mtr mini-transaction
-@return rollback segment header, page x-latched */
-UNIV_INLINE
-buf_block_t*
-trx_rsegf_get(fil_space_t* space, uint32_t page_no, mtr_t* mtr);
-
-/** Gets a newly created rollback segment header.
-@param[in] space space where placed
-@param[in] page_no page number of the header
-@param[in,out] mtr mini-transaction
-@return rollback segment header, page x-latched */
-UNIV_INLINE
-buf_block_t*
-trx_rsegf_get_new(
- ulint space,
- uint32_t page_no,
- mtr_t* mtr);
-
/** Create a rollback segment header.
-@param[in,out] space system, undo, or temporary tablespace
-@param[in] rseg_id rollback segment identifier
-@param[in] max_trx_id new value of TRX_RSEG_MAX_TRX_ID
-@param[in,out] sys_header the TRX_SYS page (NULL for temporary rseg)
-@param[in,out] mtr mini-transaction
+@param[in,out] space system, undo, or temporary tablespace
+@param[in] rseg_id rollback segment identifier
+@param[in] max_trx_id new value of TRX_RSEG_MAX_TRX_ID
+@param[in,out] mtr mini-transaction
+@param[out] err error code
@return the created rollback segment
-@retval NULL on failure */
-buf_block_t*
-trx_rseg_header_create(
- fil_space_t* space,
- ulint rseg_id,
- trx_id_t max_trx_id,
- buf_block_t* sys_header,
- mtr_t* mtr);
+@retval nullptr on failure */
+buf_block_t *trx_rseg_header_create(fil_space_t *space, ulint rseg_id,
+ trx_id_t max_trx_id, mtr_t *mtr,
+ dberr_t *err)
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Initialize or recover the rollback segments at startup. */
dberr_t trx_rseg_array_init();
-/** Free a rollback segment in memory. */
-void
-trx_rseg_mem_free(trx_rseg_t* rseg);
-
-/** Create a persistent rollback segment.
-@param[in] space_id system or undo tablespace id
-@return pointer to new rollback segment
-@retval NULL on failure */
-trx_rseg_t*
-trx_rseg_create(ulint space_id)
- MY_ATTRIBUTE((warn_unused_result));
-
/** Create the temporary rollback segments. */
-void
-trx_temp_rseg_create();
+dberr_t trx_temp_rseg_create(mtr_t *mtr);
/* Number of undo log slots in a rollback segment file copy */
#define TRX_RSEG_N_SLOTS (srv_page_size / 16)
@@ -93,34 +54,117 @@ trx_temp_rseg_create();
#define TRX_RSEG_MAX_N_TRXS (TRX_RSEG_N_SLOTS / 2)
/** The rollback segment memory object */
-struct trx_rseg_t {
- /*--------------------------------------------------------*/
- /** rollback segment id == the index of its slot in the trx
- system file copy */
- ulint id;
+struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
+{
+ /** tablespace containing the rollback segment; constant after init() */
+ fil_space_t *space;
+ /** latch protecting everything except page_no, space */
+ srw_spin_lock latch;
+ /** rollback segment header page number; constant after init() */
+ uint32_t page_no;
+ /** length of the TRX_RSEG_HISTORY list (number of transactions) */
+ uint32_t history_size;
- /** mutex protecting the fields in this struct except id,space,page_no
- which are constant */
- RsegMutex mutex;
+ /** Last known transaction that has not been purged yet,
+ or 0 if everything has been purged. */
+ trx_id_t needs_purge;
- /** space where the rollback segment header is placed */
- fil_space_t* space;
+private:
+ /** Reference counter to track is_persistent() transactions,
+ with SKIP flag. */
+ std::atomic<uint32_t> ref;
- /** page number of the rollback segment header */
- uint32_t page_no;
+ /** Whether undo tablespace truncation is pending */
+ static constexpr uint32_t SKIP= 1;
+ /** Transaction reference count multiplier */
+ static constexpr uint32_t REF= 2;
- /** current size in pages */
- uint32_t curr_size;
+ uint32_t ref_load() const { return ref.load(std::memory_order_relaxed); }
- /*--------------------------------------------------------*/
- /* Fields for undo logs */
- /** List of undo logs */
- UT_LIST_BASE_NODE_T(trx_undo_t) undo_list;
+ /** Set the SKIP bit */
+ void ref_set_skip()
+ {
+ static_assert(SKIP == 1U, "compatibility");
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+ __asm__ __volatile__("lock btsl $0, %0" : "+m" (ref));
+#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
+ _interlockedbittestandset(reinterpret_cast<volatile long*>(&ref), 0);
+#else
+ ref.fetch_or(SKIP, std::memory_order_relaxed);
+#endif
+ }
+ /** Clear a bit in ref */
+ void ref_reset_skip()
+ {
+ static_assert(SKIP == 1U, "compatibility");
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+ __asm__ __volatile__("lock btrl $0, %0" : "+m" (ref));
+#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
+ _interlockedbittestandreset(reinterpret_cast<volatile long*>(&ref), 0);
+#else
+ ref.fetch_and(~SKIP, std::memory_order_relaxed);
+#endif
+ }
+
+public:
- /** List of undo log segments cached for fast reuse */
- UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached;
+ /** Initialize the fields that are not zero-initialized. */
+ void init(fil_space_t *space, uint32_t page);
+ /** Reinitialize the fields on undo tablespace truncation. */
+ void reinit(uint32_t page);
+ /** Clean up. */
+ void destroy();
- /*--------------------------------------------------------*/
+ /** Note that undo tablespace truncation was started. */
+ void set_skip_allocation() { ut_ad(is_persistent()); ref_set_skip(); }
+ /** Note that undo tablespace truncation was completed. */
+ void clear_skip_allocation()
+ {
+ ut_ad(is_persistent());
+#if defined DBUG_OFF
+ ref_reset_skip();
+#else
+ ut_d(auto r=) ref.fetch_and(~SKIP, std::memory_order_relaxed);
+ ut_ad(r == SKIP);
+#endif
+ }
+ /** @return whether the segment is marked for undo truncation */
+ bool skip_allocation() const
+ { return ref.load(std::memory_order_acquire) & SKIP; }
+ /** Increment the reference count */
+ void acquire()
+ { ut_d(auto r=) ref.fetch_add(REF); ut_ad(!(r & SKIP)); }
+ /** Increment the reference count if possible
+ @retval true if the reference count was incremented
+ @retval false if skip_allocation() holds */
+ bool acquire_if_available()
+ {
+ uint32_t r= 0;
+ while (!ref.compare_exchange_weak(r, r + REF,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed))
+ if (r & SKIP)
+ return false;
+ return true;
+ }
+
+ /** Decrement the reference count */
+ void release()
+ {
+ ut_d(const auto r=)
+ ref.fetch_sub(REF, std::memory_order_relaxed);
+ ut_ad(r >= REF);
+ }
+ /** @return whether references exist */
+ bool is_referenced() const { return ref_load() >= REF; }
+
+ /** current size in pages */
+ uint32_t curr_size;
+
+ /** List of undo logs (transactions) */
+ UT_LIST_BASE_NODE_T(trx_undo_t) undo_list;
+ /** List of undo log segments cached for fast reuse */
+ UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached;
/** Last not yet purged undo log header; FIL_NULL if all purged */
uint32_t last_page_no;
@@ -128,20 +172,6 @@ struct trx_rseg_t {
/** trx_t::no | last_offset << 48 */
uint64_t last_commit_and_offset;
- /** Last known transaction that has not been purged yet,
- or 0 if everything has been purged. */
- trx_id_t needs_purge;
-
- /** Number of active (non-committed) transactions associated with a
- an is_persistent() rollback segment. Needed for protecting
- trx->rsegs.m_redo.rseg assignments
- before trx->rsegs.m_redo.undo has been assigned. */
- ulint trx_ref_count;
-
- /** whether undo log truncation was initiated, and transactions
- cannot be allocated in this is_persistent() rollback segment */
- bool skip_allocation;
-
/** @return the commit ID of the last committed transaction */
trx_id_t last_trx_no() const
{ return last_commit_and_offset & ((1ULL << 48) - 1); }
@@ -154,24 +184,27 @@ struct trx_rseg_t {
last_commit_and_offset= static_cast<uint64_t>(last_offset) << 48 | trx_no;
}
- /** @return whether the rollback segment is persistent */
- bool is_persistent() const
- {
- ut_ad(space == fil_system.temp_space
- || space == fil_system.sys_space
- || (srv_undo_space_id_start > 0
- && space->id >= srv_undo_space_id_start
- && space->id <= srv_undo_space_id_start
- + TRX_SYS_MAX_UNDO_SPACES));
- ut_ad(space == fil_system.temp_space
- || space == fil_system.sys_space
- || (srv_undo_space_id_start > 0
- && space->id >= srv_undo_space_id_start
- && space->id <= srv_undo_space_id_start
- + srv_undo_tablespaces_open)
- || !srv_was_started);
- return(space->id != SRV_TMP_SPACE_ID);
- }
+ /** @return the page identifier */
+ page_id_t page_id() const { return page_id_t{space->id, page_no}; }
+
+ /** @return the rollback segment header page, exclusively latched */
+ buf_block_t *get(mtr_t *mtr, dberr_t *err) const;
+
+ /** @return whether the rollback segment is persistent */
+ bool is_persistent() const
+ {
+ ut_ad(space == fil_system.temp_space || space == fil_system.sys_space ||
+ (srv_undo_space_id_start > 0 &&
+ space->id >= srv_undo_space_id_start &&
+ space->id <= srv_undo_space_id_start + TRX_SYS_MAX_UNDO_SPACES));
+ ut_ad(space == fil_system.temp_space || space == fil_system.sys_space ||
+ !srv_was_started ||
+ (srv_undo_space_id_start > 0 &&
+ space->id >= srv_undo_space_id_start
+ && space->id <= srv_undo_space_id_start +
+ srv_undo_tablespaces_open));
+ return space->id != SRV_TMP_SPACE_ID;
+ }
};
/* Undo log segment slot in a rollback segment header */
@@ -212,32 +245,8 @@ If no binlog information is present, the first byte is NUL. */
#define TRX_RSEG_BINLOG_NAME_LEN 512
#ifdef WITH_WSREP
-/** The offset to WSREP XID headers */
-#define TRX_RSEG_WSREP_XID_INFO TRX_RSEG_MAX_TRX_ID + 16 + 512
-
-/** WSREP XID format (1 if present and valid, 0 if not present) */
-#define TRX_RSEG_WSREP_XID_FORMAT TRX_RSEG_WSREP_XID_INFO
-/** WSREP XID GTRID length */
-#define TRX_RSEG_WSREP_XID_GTRID_LEN TRX_RSEG_WSREP_XID_INFO + 4
-/** WSREP XID bqual length */
-#define TRX_RSEG_WSREP_XID_BQUAL_LEN TRX_RSEG_WSREP_XID_INFO + 8
-/** WSREP XID data (XIDDATASIZE bytes) */
-#define TRX_RSEG_WSREP_XID_DATA TRX_RSEG_WSREP_XID_INFO + 12
-#endif /* WITH_WSREP*/
-
-/*-------------------------------------------------------------*/
+# include "trx0xa.h"
-/** Read the page number of an undo log slot.
-@param[in] rseg_header rollback segment header
-@param[in] n slot number */
-inline uint32_t trx_rsegf_get_nth_undo(const buf_block_t *rseg_header, ulint n)
-{
- ut_ad(n < TRX_RSEG_N_SLOTS);
- return mach_read_from_4(TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
- n * TRX_RSEG_SLOT_SIZE + rseg_header->frame);
-}
-
-#ifdef WITH_WSREP
/** Update the WSREP XID information in rollback segment header.
@param[in,out] rseg_header rollback segment header
@param[in] xid WSREP XID
@@ -263,6 +272,16 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid);
bool trx_rseg_read_wsrep_checkpoint(XID& xid);
#endif /* WITH_WSREP */
+/** Read the page number of an undo log slot.
+@param[in] rseg_header rollback segment header
+@param[in] n slot number */
+inline uint32_t trx_rsegf_get_nth_undo(const buf_block_t *rseg_header, ulint n)
+{
+ ut_ad(n < TRX_RSEG_N_SLOTS);
+ return mach_read_from_4(TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
+ n * TRX_RSEG_SLOT_SIZE + rseg_header->page.frame);
+}
+
/** Upgrade a rollback segment header page to MariaDB 10.3 format.
@param[in,out] rseg_header rollback segment header page
@param[in,out] mtr mini-transaction */
@@ -277,7 +296,3 @@ up to which replication has proceeded.
@param[in,out] mtr mini-transaction */
void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
mtr_t *mtr);
-
-#include "trx0rseg.inl"
-
-#endif