Created 3/26/1996 Heikki Tuuri
*******************************************************/
#ifndef trx0undo_h #define trx0undo_h
#include"trx0sys.h" #ifndef UNIV_INNOCHECKSUM /** The LSB of the "is insert" flag in DB_ROLL_PTR */ #define ROLL_PTR_INSERT_FLAG_POS 55 /** The LSB of the 7-bit trx_rseg_t::id in DB_ROLL_PTR */ #define ROLL_PTR_RSEG_ID_POS 48 /** The LSB of the 32-bit undo log page number in DB_ROLL_PTR */ #define ROLL_PTR_PAGE_POS 16 /** The LSB of the 16-bit byte offset within an undo log page in DB_ROLL_PTR */ #define ROLL_PTR_BYTE_POS 0
/***********************************************************************//**
Builds a roll pointer.
@return roll pointer */
UNIV_INLINE
roll_ptr_t
trx_undo_build_roll_ptr( /*====================*/ bool is_insert, /*!< in: TRUE if insert undo log */
ulint rseg_id, /*!< in: rollback segment id */
uint32_t page_no, /*!< in: page number */
uint16_t offset); /*!< in: offset of the undo entry within page */ /***********************************************************************//**
Decodes a roll pointer. */
UNIV_INLINE void
trx_undo_decode_roll_ptr( /*=====================*/
roll_ptr_t roll_ptr, /*!< in: roll pointer */ bool* is_insert, /*!< out: TRUE if insert undo log */
ulint* rseg_id, /*!< out: rollback segment id */
uint32_t* page_no, /*!< out: page number */
uint16_t* offset); /*!< out: offset of the undo
entry within page */ /***********************************************************************//**
Determine if DB_ROLL_PTR is of the insert type.
@returntrueif insert */
UNIV_INLINE bool
trx_undo_roll_ptr_is_insert( /*========================*/
roll_ptr_t roll_ptr); /*!< in: roll pointer */ /***********************************************************************//**
Returns trueif the record is of the insert type.
@returntrueif the record was freshly inserted (not updated). */
UNIV_INLINE bool
trx_undo_trx_id_is_insert( /*======================*/ const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */
MY_ATTRIBUTE((warn_unused_result)); /** Write DB_ROLL_PTR. @param[out]ptrbuffer
@param[in] roll_ptr DB_ROLL_PTR value */ inlinevoid trx_write_roll_ptr(byte* ptr, roll_ptr_t roll_ptr)
{
compile_time_assert(DATA_ROLL_PTR_LEN == 7);
mach_write_to_7(ptr, roll_ptr);
} /** Read DB_ROLL_PTR. @param[in]ptrbuffer
@return roll ptr */ inline roll_ptr_t trx_read_roll_ptr(const byte* ptr)
{
compile_time_assert(DATA_ROLL_PTR_LEN == 7); return mach_read_from_7(ptr);
}
/** Get the next record in an undo log. @param[in]undo_pageundologpage @param[in]recundorecordoffsetinthepage @param[in]page_noundologheaderpagenumber @param[in]offsetundologheaderoffsetonpage
@return undo log record, the page latched, NULL if none */ inline trx_undo_rec_t*
trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec,
uint32_t page_no, uint16_t offset); /** Get the previous record in an undo log. @param[in,out]blockundologpage @param[in]recundorecordoffsetinthepage @param[in]page_noundologheaderpagenumber @param[in]offsetundologheaderoffsetonpage @param[in]sharedlatchingmode:true=RW_S_LATCH,false=RW_X_LATCH @param[in,out]mtrmini-transaction
@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
trx_undo_get_prev_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
uint16_t offset, bool shared, mtr_t *mtr);
/** Get the first undo log record on a page. @param[in]blockundologpage @param[in]page_noundologheaderpagenumber @param[in]offsetundologheaderpageoffset @returnpointertofirstrecord
@retval nullptr if none exists */
trx_undo_rec_t*
trx_undo_page_get_first_rec(const buf_block_t *block, uint32_t page_no,
uint16_t offset);
/** Free the last undo log page. The caller must hold the rseg mutex. @param[in,out]undoundolog @param[in,out]mtrmini-transactionthatdoesnotholdanyundologpage orthathasallocatedtheundologpage
@return error code */
dberr_t trx_undo_free_last_page(trx_undo_t *undo, mtr_t *mtr)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Try to truncate the undo logs. @paramtrxtransaction
@return error code */
dberr_t trx_undo_try_truncate(trx_t *trx);
/** Truncate the head of an undo log. NOTEthatonlywholepagesarefreed;theheaderpageisnot freed,butemptied,ifalltherecordstherearebelowthelimit. @param[in,out]rsegrollbacksegment @param[in]hdr_page_noheaderpagenumber @param[in]hdr_offsetheaderoffsetonthepage @param[in]limitfirstundonumbertopreserve (everythingbelowthelimitwillbetruncated)
@return error code */
dberr_t
trx_undo_truncate_start(
trx_rseg_t* rseg,
uint32_t hdr_page_no,
uint16_t hdr_offset,
undo_no_t limit)
MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Mark that an undo log header belongs to a data dictionary transaction. @param[in,out]undoundolog
@param[in,out] mtr mini-transaction */ void trx_undo_mark_as_dict(trx_undo_t* undo, mtr_t* mtr); /** Assign an undo log for a persistent transaction. Anewundologiscreatedoracachedundologreused. @param[in,out]mtrmini-transaction @param[out]errerrorcode @returntheundologblock
@retval NULL on error */
buf_block_t *trx_undo_assign(mtr_t* mtr, dberr_t *err) noexcept
MY_ATTRIBUTE((nonnull)); /** Assign an undo log for a transaction. Anewundologiscreatedoracachedundologreused. @tparamis_tempwhetherthisistemporaryundolog @param[in]rsegrollbacksegment @param[out]undotheundolog @param[in,out]mtrmini-transaction @param[out]errerrorcode @returntheundologblock
@retval nullptr on error */ template<bool is_temp>
buf_block_t*
trx_undo_assign_low(mtr_t *mtr, dberr_t *err, trx_rseg_t *rseg,
trx_undo_t **undo)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK. @param[in,out]undoundolog @param[in]rollbackfalse=XAPREPARE,true=XAROLLBACK
@param[in,out] mtr mini-transaction */ void trx_undo_set_state_at_prepare(trx_undo_t *undo, bool rollback, mtr_t *mtr)
noexcept MY_ATTRIBUTE((nonnull));
/** At shutdown, frees the undo logs of a transaction. */ void
trx_undo_free_at_shutdown(trx_t *trx);
/** Read an undo log when starting up the database. @param[in,out]rsegrollbacksegment @param[in]idrollbacksegmentslot @param[in]page_noundologsegmentpagenumber @returntheundolog
@retval nullptr on error */
trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no);
#endif/* !UNIV_INNOCHECKSUM */
/** the only rollback segment type since MariaDB 10.3.1 */
constexpr uint16_t TRX_UNDO_UPDATE= 2; /* TRX_UNDO_STATE values of an undo log segment */ /** contains an undo log of an active transaction */
constexpr uint16_t TRX_UNDO_ACTIVE = 1; /** cached for quick reuse */
constexpr uint16_t TRX_UNDO_CACHED = 2; /** can be freed in purge when all undo data in it is removed */
constexpr uint16_t TRX_UNDO_TO_PURGE = 4; /** contains an undo log of a prepared transaction */
constexpr uint16_t TRX_UNDO_PREPARED = 5;
#ifndef UNIV_INNOCHECKSUM
/** Transaction undo log memory object; modified by the thread associated
with the transaction. */
struct trx_undo_t { /*-----------------------------*/
ulint id; /*!< undo log slot number within the
rollback segment */
ulint state; /*!< state of the corresponding undo log
segment */
trx_id_t trx_id; /*!< id of the trx assigned to the undo
log */
XID xid; /*!< X/Open XA transaction
identification */ bool dict_operation; /*!< TRUE if a dict operation trx */
trx_rseg_t* rseg; /*!< rseg where the undo log belongs */ /*-----------------------------*/
uint32_t hdr_page_no; /*!< page number of the header page in
the undo log */
uint32_t last_page_no; /*!< page number of the last page in the undolog;thismaydifferfrom
top_page_no during a rollback */
uint16_t hdr_offset; /*!< header offset of the undo log on
the page */
uint32_t size; /*!< current size in pages */ /*-----------------------------*/
uint32_t top_page_no; /*!< page number where the latest undo logrecordwascatenated;during rollbackthepagefromwhichthelatest
undo record was chosen */
uint16_t top_offset; /*!< offset of the latest undo record, i.e.,thetopmostelementintheundo
log if we think of it as a stack */
uint16_t old_offset; /*!< previous undo record offset
for ALTER IGNORE */
undo_no_t top_undo_no; /*!< undo number of the latest record
(IB_ID_MAX if the undo log is empty) */
buf_block_t* guess_block; /*!< guess for the buffer block where
the top page might reside */
/** @return whether the undo log is empty */ bool empty() const { return top_undo_no == IB_ID_MAX; }
/*-----------------------------*/
UT_LIST_NODE_T(trx_undo_t) undo_list; /*!< undo log objects in the rollback
segment are chained into lists */
};
/** Cache a pointer to an undo record in a latched buffer pool page, parsetheundologrecordandstoretherecordtype,updatevector
and compiler information */ class UndorecApplier
{ /** Undo log block page id */
page_id_t page_id; /** Pointer to within undo log record */ const trx_undo_rec_t *undo_rec; /** Undo log record type */
byte type; /** compiler information */
byte cmpl_info; /** page_offset(undo_rec) of the start of undo_rec */
uint16_t offset; /** Transaction id of the undo log */ const trx_id_t trx_id; /** Update vector */
upd_t *update; /** memory heap which can be used to build previous version of
the index record and its offsets */
mem_heap_t *heap; /** mini-transaction for accessing B-tree pages */
mtr_t mtr;
/** Assign the next page id */ void assign_next(const page_id_t next_page_id)
{
page_id= next_page_id;
}
page_id_t get_page_id() const { return page_id; }
/** Handle the DML undo log and apply it on online indexes */ inlinevoid apply_undo_rec(const trx_undo_rec_t *rec, uint16_t offset);
~UndorecApplier()
{
mem_heap_free(heap);
}
private: /** Handle the insert undo log and apply it on online indexes @paramtuplerowreferencefromundologrecord
@param clust_index clustered index */ void log_insert(const dtuple_t &tuple, dict_index_t *clust_index);
/** Handle the update, delete undo log and apply it on online indexes. @paramtuplerowreferencefromundologrecord
@param clust_index clustered index */ void log_update(const dtuple_t &tuple, dict_index_t *clust_index);
/** Check whether the given roll pointer is generated by thecurrentundologrecordinformationstored.
@return true if roll pointer matches with current undo log info */ inlinebool is_same(roll_ptr_t roll_ptr) const;
/** Clear the undo log record information */ void clear_undo_rec()
{
undo_rec= nullptr;
cmpl_info= 0;
type= 0;
update= nullptr;
mem_heap_empty(heap);
}
/** Get the correct version of the clustered index record that wasmodifiedbythecurrentundologrecord.Becausetherecould bethemultiplesuccessiveupdatesofthesamerecordwithinthe sametransaction. @paramtupletuplecontainsprimarykeyvalue @paramindexclusteredindex @param[out]clust_reccurrentclusteredindexrecord @paramoffsetsoffsetspointstotherecord @returnclusteredindexrecordwhichwaschangedby theundologrecordornullptrwhenthereisnoclustered
index record changed by undo log record */ const rec_t* get_old_rec(const dtuple_t &tuple, dict_index_t *index, const rec_t **clust_rec, rec_offs **offsets);
};
#endif/* !UNIV_INNOCHECKSUM */
/** The offset of the undo log page header on pages of the undo log */ #define TRX_UNDO_PAGE_HDR FSEG_PAGE_DATA /*-------------------------------------------------------------*/ /** Transaction undo log page header offsets */ /* @{ */ #define TRX_UNDO_PAGE_TYPE 0/*!< unused; 0 (before MariaDB 10.3.1: 1=TRX_UNDO_INSERTor
2=TRX_UNDO_UPDATE) */ #define TRX_UNDO_PAGE_START 2/*!< Byte offset where the undo log recordsfortheLATESTtransaction startonthispage(rememberthat inanupdateundolog,thefirstpage
can contain several undo logs) */ #define TRX_UNDO_PAGE_FREE 4/*!< On each page of the undo log this fieldcontainsthebyteoffsetofthe
first free byte on the page */ #define TRX_UNDO_PAGE_NODE 6/*!< The file list node in the chain
of undo log pages */ /*-------------------------------------------------------------*/ #define TRX_UNDO_PAGE_HDR_SIZE (6 + FLST_NODE_SIZE) /*!< Size of the transaction undo
log page header, in bytes */ /* @} */
/** An update undo segment with just one page can be reused if it has atmostthismanybytesused;wemustleavespaceatleastforonenewundo
log header on the page */
/* An update undo log segment may contain several undo logs on its first page iftheundologstooksolittlespacethatthesegmentcouldbecachedand reused.Alltheundologheadersarethenonthefirstpage,andthelastone ownstheundologrecordsonsubsequentpagesifthesegmentisbiggerthan onepage.Ifanundologisstoredinasegment,thenonthefirstpageitis allowedtohavezeroundorecords,butifthesegmentextendstoseveral pages,thenalltherestofthepagesmustcontainatleastoneundolog
record. */
/** The offset of the undo log segment header on the first page of the undo
log segment */
#define TRX_UNDO_LAST_LOG 2/*!< Offset of the last undo log header onthesegmentheaderpage,0if
none */ #define TRX_UNDO_FSEG_HEADER 4/*!< Header for the file segment which
the undo log segment occupies */ #define TRX_UNDO_PAGE_LIST (4 + FSEG_HEADER_SIZE) /*!< Base node for the list of pages in theundologsegment;definedonlyon
the undo log segment's first page */ /*-------------------------------------------------------------*/ /** Size of the undo log segment header */ #define TRX_UNDO_SEG_HDR_SIZE (4 + FSEG_HEADER_SIZE + FLST_BASE_NODE_SIZE) /* @} */
/** The undo log header. There can be several undo log headers on the first
page of an update undo log segment. */ /* @{ */ /*-------------------------------------------------------------*/ /** Transaction start identifier, or 0 if the undo log segment has been
completely purged and trx_purge_free_segment() has started freeing it */ #define TRX_UNDO_TRX_ID 0 /** Transaction end identifier (if the log is in a history list),
or 0 if the transaction has not been committed */ #define TRX_UNDO_TRX_NO 8 /* Before MariaDB 10.3.1, when purge did not reset DB_TRX_ID of survivinguserrecords,thisusedtobecalledTRX_UNDO_DEL_MARKS.
BeforeMariaDB10.3.1,alogsegmentmaycarrythevalue0evenbefore trx_purge_free_segment()wascalled,forthoseundologrecordsfor
which purge would not result in removing delete-marked records. */ /*#define TRX_UNDO_NEEDS_PURGE 16*/ #define TRX_UNDO_LOG_START 18/*!< Offset of the first undo log record ofthislogontheheaderpage;purge mayremoveundologrecordfromthe logstart,andthereforethisisnot necessarilythesameasthislog
header end offset */ #define TRX_UNDO_XID_EXISTS 20/*!< TRUE if undo log header includes X/OpenXAtransactionidentification
XID */ #define TRX_UNDO_DICT_TRANS 21/*!< TRUE if the transaction is a table create,indexcreate,ordrop transaction:inrecovery thetransactioncannotberolledback intheusualway:a'rollback'rather meansdroppingthecreatedordropped
table, if it still exists */ #define TRX_UNDO_TABLE_ID 22/*!< Id of the table if the preceding
field is TRUE */ #define TRX_UNDO_NEXT_LOG 30/*!< Offset of the next undo log header
on this page, 0 if none */ #define TRX_UNDO_PREV_LOG 32/*!< Offset of the previous undo log
header on this page, 0 if none */ #define TRX_UNDO_HISTORY_NODE 34/*!< If the log is put to the history
list, the file list node is here */ /*-------------------------------------------------------------*/ /** Size of the undo log header without XID information */ #define TRX_UNDO_LOG_OLD_HDR_SIZE (34 + FLST_NODE_SIZE)
/** X/Open XA Transaction Identification (XID) */ /* @{ */ /** xid_t::formatID */ #define TRX_UNDO_XA_FORMAT (TRX_UNDO_LOG_OLD_HDR_SIZE) /** xid_t::gtrid_length */ #define TRX_UNDO_XA_TRID_LEN (TRX_UNDO_XA_FORMAT + 4) /** xid_t::bqual_length */ #define TRX_UNDO_XA_BQUAL_LEN (TRX_UNDO_XA_TRID_LEN + 4) /** Distributed transaction identifier data */ #define TRX_UNDO_XA_XID (TRX_UNDO_XA_BQUAL_LEN + 4) /*--------------------------------------------------------------*/ #define TRX_UNDO_LOG_XA_HDR_SIZE (TRX_UNDO_XA_XID + XIDDATASIZE) /*!< Total size of the undo log header
with the XA XID */ /* @} */
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.