diff options
Diffstat (limited to 'storage/innobase/include/trx0rseg.h')
-rw-r--r-- | storage/innobase/include/trx0rseg.h | 285 |
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 |