/** Checks if a page address is the trx sys header page. @param[in]page_idpageid
@return true if trx sys header page */ inlinebool trx_sys_hdr_page(const page_id_t page_id)
{ return page_id == page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO);
}
/*****************************************************************//**
Creates and initializes the transaction system at the database creation. */
dberr_t trx_sys_create_sys_pages(mtr_t *mtr);
/** Find an available rollback segment. @param[in]sys_header @returnanunallocatedrollbacksegmentslotintheTRX_SYSheader
@retval ULINT_UNDEFINED if not found */
ulint
trx_sys_rseg_find_free(const buf_block_t* sys_header); /** Request the TRX_SYS page. @param[in]rwwhethertolockthepageforwriting @returntheTRX_SYSpage
@retval NULL if the page cannot be read */ inline buf_block_t *trx_sysf_get(mtr_t* mtr, bool rw= true)
{ return buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), 0, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
}
/** Read a transaction identifier.
@return id */ inline
trx_id_t
trx_read_trx_id(const byte* ptr)
{
compile_time_assert(DATA_TRX_ID_LEN == 6); return(mach_read_from_6(ptr));
}
#ifdef UNIV_DEBUG /** Check that the DB_TRX_ID in a record is valid. @param[in]db_trx_idtheDB_TRX_IDcolumntovalidate
@param[in] trx_id the id of the ALTER TABLE transaction */ inlinebool trx_id_check(constvoid* db_trx_id, trx_id_t trx_id)
{
trx_id_t id = trx_read_trx_id(static_cast<const byte*>(db_trx_id));
ut_ad(id == 0 || id > trx_id); returntrue;
} #endif
/*****************************************************************//**
Updates the offset information about the end of the MySQL binlog entry
which corresponds to the transaction just being committed. In a MySQL
replication slave updates the latest master binlog position up to which
replication has proceeded. */ void
trx_sys_update_mysql_binlog_offset( /*===============================*/ constchar* file_name,/*!< in: MySQL log file name */
int64_t offset, /*!< in: position in that log file */
buf_block_t* sys_header, /*!< in,out: trx sys header */
mtr_t* mtr); /*!< in,out: mini-transaction */ /** Display the MySQL binlog offset info if it is present in the trx
system header. */ void
trx_sys_print_mysql_binlog_offset();
/** Create the rollback segments.
@return whether the creation succeeded */ bool
trx_sys_create_rsegs();
/** The offset of the transaction system header on the page */ #define TRX_SYS FSEG_PAGE_DATA
/** Transaction system header */ /*------------------------------------------------------------- @{ */ /** In old versions of InnoDB, this persisted the value of trx_sys.get_max_trx_id().StartingwithMariaDB10.3.5, thefieldTRX_RSEG_MAX_TRX_IDinrollbacksegmentheaderpages andthefieldsTRX_UNDO_TRX_ID,TRX_UNDO_TRX_NOinundologpages areusedinstead.Thefieldonlyexistsforthepurposeofupgrading
from older MySQL or MariaDB versions. */ #define TRX_SYS_TRX_ID_STORE 0 #define TRX_SYS_FSEG_HEADER 8/*!< segment header for the tablespacesegmentthetrx
system is created into */ #define TRX_SYS_RSEGS (8 + FSEG_HEADER_SIZE) /*!< the start of the array of rollbacksegmentspecification
slots */
/* Rollback segment specification slot offsets */
/** the tablespace ID of an undo log header; starting with
MySQL/InnoDB 5.1.7, this is FIL_NULL if the slot is unused */ #define TRX_SYS_RSEG_SPACE 0 /** the page number of an undo log header, or FIL_NULL if unused */ #define TRX_SYS_RSEG_PAGE_NO 4 /** Size of a rollback segment specification slot */ #define TRX_SYS_RSEG_SLOT_SIZE 8
/** Read the tablespace ID of a rollback segment slot. @param[in]sys_headerTRX_SYSpage @param[in]rseg_idrollbacksegmentidentifier
@return undo tablespace id */ inline
uint32_t
trx_sysf_rseg_get_space(const buf_block_t* sys_header, ulint rseg_id)
{
ut_ad(rseg_id < TRX_SYS_N_RSEGS); return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_SPACE
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ sys_header->page.frame);
}
/** Read the page number of a rollback segment slot. @param[in]sys_headerTRX_SYSpage @param[in]rseg_idrollbacksegmentidentifier
@return undo page number */ inline uint32_t
trx_sysf_rseg_get_page_no(const buf_block_t *sys_header, ulint rseg_id)
{
ut_ad(rseg_id < TRX_SYS_N_RSEGS); return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO +
rseg_id * TRX_SYS_RSEG_SLOT_SIZE +
sys_header->page.frame);
}
/** Maximum length of MySQL binlog file name, in bytes.
(Used before MariaDB 10.3.5.) */ #define TRX_SYS_MYSQL_LOG_NAME_LEN 512 /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */ #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
#if UNIV_PAGE_SIZE_MIN < 4096 # error "UNIV_PAGE_SIZE_MIN < 4096" #endif /** The offset of the MySQL binlog offset info in the trx system header */ #define TRX_SYS_MYSQL_LOG_INFO (srv_page_size - 1000) #define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0/*!< magic number which is TRX_SYS_MYSQL_LOG_MAGIC_N ifwehavevaliddatainthe
MySQL binlog info */ #define TRX_SYS_MYSQL_LOG_OFFSET 4/*!< the 64-bit offset
within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12/*!< MySQL log file name */
/** Memory map TRX_SYS_PAGE_NO = 5 when srv_page_size = 4096
/** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ #define TRX_SYS_DOUBLEWRITE (srv_page_size - 200) /*-------------------------------------------------------------*/ #define TRX_SYS_DOUBLEWRITE_FSEG 0/*!< fseg header of the fseg containingthedoublewrite
buffer */ #define TRX_SYS_DOUBLEWRITE_MAGIC FSEG_HEADER_SIZE /*!< 4-byte magic number which showsifwealreadyhave createdthedoublewrite
buffer */ #define TRX_SYS_DOUBLEWRITE_BLOCK1 (4 + FSEG_HEADER_SIZE) /*!< page number of the firstpageinthefirst sequenceof64 (=FSP_EXTENT_SIZE)consecutive pagesinthedoublewrite
buffer */ #define TRX_SYS_DOUBLEWRITE_BLOCK2 (8 + FSEG_HEADER_SIZE) /*!< page number of the firstpageinthesecond sequenceof64consecutive pagesinthedoublewrite
buffer */ #define TRX_SYS_DOUBLEWRITE_REPEAT 12/*!< we repeat TRX_SYS_DOUBLEWRITE_MAGIC, TRX_SYS_DOUBLEWRITE_BLOCK1, TRX_SYS_DOUBLEWRITE_BLOCK2 sothatifthetrxsys headerishalf-written todisk,westillmay beabletorecoverthe
information */ /** If this is not yet set to TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N, wemustresetthedoublewritebuffer,becausestartingfrom4.1.xthe spaceidofadatapageisstoredinto
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID. */ #define TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED (24 + FSEG_HEADER_SIZE)
rw_trx_hash_element_t *element= reinterpret_cast<rw_trx_hash_element_t*>
(lf_hash_search(&hash, pins, reinterpret_cast<constvoid*>(&trx_id), sizeof(trx_id_t))); if (element)
{ /* rw_trx_hash_t::erase() sets element->trx to nullptr under element->mutexprotectionbeforeremovingtheelementfromhashtable. Iftheelementwasremovedbeforethemutexacquisition,element->trx
will be equal to nullptr. */
DEBUG_SYNC_C("before_trx_hash_find_element_mutex_enter");
element->mutex.wr_lock(); /* element_trx can't point to reused object now. If transaction was deregisteredbeforeelement->mutexacquisition,element->trxisnullptr.
It can't be deregistered while element->mutex is held. */
trx_t *element_trx = element->trx;
lf_hash_search_unpin(pins); /* The *element can be reused now, as element->trx value is stored
locally in element_trx. */
DEBUG_SYNC_C("after_trx_hash_find_element_mutex_enter"); if ((trx= element_trx)) {
DBUG_ASSERT(trx_id == trx->id);
ut_d(validate_element(trx)); if (do_ref_count)
{ /* Wehaveanearlystatecheckheretoavoidcommitter starvationinawaitloopfortransactionreferences, whenthere'sastreamoftrx_sys.find()callsfromother threads.Thetrx->statemaychangetoCOMMITTEDafter trx->mutexisreleased,anditwillhavetoberechecked bythecallerafterreacquiringthemutex.
*/ /* trx_t::commit_in_memory() sets the state to TRX_STATE_COMMITTED_IN_MEMORYbeforederegisteringthetransaction. Italsowaitsforanyimplicit-to-explicitlockconversionstocease
after deregistering. */ if (trx->state == TRX_STATE_COMMITTED_IN_MEMORY)
trx= nullptr; else
trx->reference();
}
} /* element's lifetime is equal to the hash lifetime, that's why element->mutexisvalidheredespitetheelementisunpinned.Inthe
worst case some thread will wait for element->mutex releasing. */
element->mutex.wr_unlock();
} if (!caller_trx)
lf_hash_put_pins(pins); return trx;
}
/** The transaction system central memory data structure. */ class trx_sys_t
{ /** Thesmallestnumbernotyetassignedasatransactionidortransaction number.Accessedandupdatedwithatomicoperations.
*/
alignas(CPU_LEVEL1_DCACHE_LINESIZE) Atomic_counter<trx_id_t> m_max_trx_id;
Thiscomplementsrw_trx_hashwithatraversal-friendlyrepresentation optimizedforcollectingactivetransactionids.
*/
rw_trx_vector rw_trx_ids; public: /** List of all transactions. */
thread_safe_trx_ilist_t trx_list;
/** @return the number of active views */
size_t view_count() const
{
size_t count= 0;
trx_list.for_each([&count](const trx_t &trx) { if (trx.read_view.is_open())
++count;
});
return count;
}
/** Disable further allocation of transactions in a rollback segment thataresubjecttoinnodb_undo_log_truncate=ON
@param space undo tablespace that will be truncated */ inlinevoid undo_truncate_start(fil_space_t &space);
/** Set the undo log empty value */ void set_undo_non_empty(bool val)
{ if (!undo_log_nonempty)
undo_log_nonempty= val;
}
/** Get the undo log empty value */ bool is_undo_empty() const { return !undo_log_nonempty; }
/** @return whether XA transaction is in PREPARED state */ staticbool is_xa_exist() noexcept;
/* Reset the trx_sys page and retain the dblwr information, systemrollbacksegmentheaderpage
@return error code */ inline dberr_t reset_page(mtr_t *mtr); private: static my_bool find_same_or_older_callback(void *el, void *i) noexcept;
/** Getter for m_rw_trx_hash_version, must issue ACQUIRE memory barrier. */
trx_id_t get_rw_trx_hash_version() const noexcept
{ return m_rw_trx_hash_version.load(std::memory_order_acquire);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.