Howtodothepurge?Arecordcanberemovedfromtheclusteredindex ifitslinkedlistbecomesempty,i.e.,therowhasbeenmarkeddeleted anditsrollptrpointstotherecordintheundologwearegoingthrough, doingthepurge.Similarly,duringarollback,arecordcanberemoved ifthestoredrollptrintheundologpointstoatrxalready(being)purged,
or if the roll ptr is NULL, i.e., it was a fresh insert. */
/********************************************************************//**
Creates a row undo node to a query graph.
@return own: undo node */
undo_node_t*
row_undo_node_create( /*=================*/
trx_t* trx, /*!< in/out: transaction */
que_thr_t* parent, /*!< in: parent node, i.e., a thr node */
mem_heap_t* heap) /*!< in: memory heap where created */
{
undo_node_t* undo;
/***********************************************************//**
Looks for the clustered index record when node has the row reference.
The pcur in node is used in the search. If found, stores the row to node, and stores the position of pcur, and detaches it. The pcur must be closed
by the caller in any case.
@returntrueif found; NOTE the node->pcur must be closed by the
caller, regardless of the return value */ bool
row_undo_search_clust_to_pcur( /*==========================*/
undo_node_t* node) /*!< in/out: row undo node */
{
dict_index_t* clust_index; bool found;
mtr_t mtr{node->trx};
row_ext_t** ext; const rec_t* rec;
mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
found = row_get_rec_roll_ptr(rec, clust_index, offsets)
== node->roll_ptr;
if (found) {
ut_ad(row_get_rec_trx_id(rec, clust_index, offsets)
== node->trx->id || node->table->is_temporary());
if (dict_table_has_atomic_blobs(node->table)) { /* There is no prefix of externally stored columnsintheclusteredindexrecord.Builda
cache of column prefixes. */
ext = &node->ext;
} else { /* REDUNDANT and COMPACT formats store a local 768-byteprefixofeachexternallystored
column. No cache is needed. */
ext = NULL;
node->ext = NULL;
}
/* We will need to parse out virtual column info from undo log,firstmarkthemDATA_MISSING.Sowewillknowifthe
value gets updated */ if (node->table->n_v_cols
&& !trx_undo_roll_ptr_is_insert(node->roll_ptr)
&& !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { for (ulint i = 0;
i < dict_table_get_n_v_cols(node->table); i++) {
dfield_get_type(dtuple_get_nth_v_field(
node->row, i))->mtype = DATA_MISSING;
}
}
/** Get the latest undo log record for rollback. @param[in,out]noderollbackcontext @returnundoblockfortheundologrecord
@retval nullptr if no undo log record was fetched */ static buf_block_t* row_undo_rec_get(undo_node_t* node)
{
trx_t* trx = node->trx;
if (trx->pages_undone) {
trx->pages_undone = 0;
trx_undo_try_truncate(trx);
}
if (undo == NULL) {
trx_undo_try_truncate(trx); /* Mark any ROLLBACK TO SAVEPOINT completed, so that ifthetransactionobjectiscommittedandreused
later, we will default to a full ROLLBACK. */
trx->roll_limit = 0;
trx->in_rollback = false; return nullptr;
}
const size_t end = mach_read_from_2(node->undo_rec); if (UNIV_UNLIKELY(end <= offset
|| end >= srv_page_size - FIL_PAGE_DATA_END)) {
undo_page->unfix();
node->undo_rec = nullptr; return nullptr;
}
switch (node->undo_rec[2] & (TRX_UNDO_CMPL_INFO_MULT - 1)) { case TRX_UNDO_INSERT_METADATA: /* This record type was introduced in MDEV-11369 instantADDCOLUMN,whichwasimplementedafter MDEV-12288removedtheinsert_undolog.Thereisno instantADDCOLUMNfortemporarytables.Therefore,
this record can only be present in the main undo log. */ /* fall through */ case TRX_UNDO_RENAME_TABLE:
ut_ad(undo == update); /* fall through */ case TRX_UNDO_INSERT_REC: case TRX_UNDO_EMPTY:
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
}
/***********************************************************//**
Fetches an undo log record and does the undo for the recorded operation. If none left, or a partial rollback completed, returns control to the
parent node, which is always a query thread node.
@return DB_SUCCESS if operation successfully completed, else error code */ static MY_ATTRIBUTE((warn_unused_result))
dberr_t
row_undo( /*=====*/
undo_node_t* node, /*!< in: row undo node */
que_thr_t* thr) /*!< in: query thread */
{
ut_ad(node->trx->in_rollback);
buf_block_t* undo_page = row_undo_rec_get(node);
if (!undo_page) { /* Rollback completed for this query thread */
thr->run_node = que_node_get_parent(node); return DB_SUCCESS;
}
/***********************************************************//**
Undoes a row operation in a table. This is a high-level function used
in SQL execution graphs.
@return query thread to run next or NULL */
que_thr_t*
row_undo_step( /*==========*/
que_thr_t* thr) /*!< in: query thread */
{
dberr_t err;
undo_node_t* node;
trx_t* trx = thr_get_trx(thr);
node = static_cast<undo_node_t*>(thr->run_node);
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
if (UNIV_UNLIKELY(!trx->dict_operation
&& !srv_undo_sources
&& srv_shutdown_state != SRV_SHUTDOWN_NONE)
&& (srv_fast_shutdown == 3 || trx == trx_roll_crash_recv_trx)) { /* Shutdown has been initiated. */
trx->error_state = DB_INTERRUPTED; return NULL;
}
if (UNIV_UNLIKELY(trx == trx_roll_crash_recv_trx)) {
trx_roll_report_progress();
}
err = row_undo(node, thr);
#ifdef ENABLED_DEBUG_SYNC if (trx->mysql_thd) {
DEBUG_SYNC_C("trx_after_rollback_row");
} #endif/* ENABLED_DEBUG_SYNC */
trx->error_state = err;
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
ib::fatal() << "Error (" << err << ") in rollback.";
}
return(thr);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-10-08)
¤
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.