/* Free the memory reserved by the undo graph. */
que_graph_free(static_cast<que_t*>(roll_node->undo_thr->common.parent));
}
if (!savept)
{
rollback_finish();
MONITOR_INC(MONITOR_TRX_ROLLBACK);
} else
{ /* There must not be partial rollback if transaction was chosen as deadlock
victim. Galera transaction abort can be invoked during partial rollback. */
ut_ad(!(lock.was_chosen_as_deadlock_victim & 1));
ut_a(error_state == DB_SUCCESS); const undo_no_t limit{*savept};
apply_online_log= false; for (trx_mod_tables_t::iterator i= mod_tables.begin();
i != mod_tables.end(); )
{
trx_mod_tables_t::iterator j= i++;
ut_ad(j->second.valid()); if (j->second.rollback(limit))
{
j->second.clear_bulk_buffer();
mod_tables.erase(j);
} elseif (!apply_online_log)
apply_online_log= j->first->is_native_online_ddl();
}
MONITOR_INC(MONITOR_TRX_ROLLBACK_SAVEPOINT);
}
dberr_t trx_t::rollback(const undo_no_t *savept) noexcept
{
ut_ad(!mutex_is_owner()); switch (state) { case TRX_STATE_ABORTED:
ut_ad(!savept);
state= TRX_STATE_NOT_STARTED; /* fall through */ case TRX_STATE_NOT_STARTED:
error_state= DB_SUCCESS; return DB_SUCCESS; case TRX_STATE_PREPARED: case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY:
ut_ad("invalid state" == 0); /* fall through */ case TRX_STATE_ACTIVE: break;
} #ifdef WITH_WSREP if (!savept && is_wsrep() && wsrep_thd_is_SR(mysql_thd))
wsrep_handle_SR_rollback(nullptr, mysql_thd); #endif/* WITH_WSREP */ return rollback_low(savept);
}
/** Rollback a transaction used in MySQL @param[in,out]trxtransaction
@return error code or DB_SUCCESS */
dberr_t trx_rollback_for_mysql(trx_t* trx)
{ /* We are reading trx->state without holding trx->mutex here,becausetherollbackshouldbeinvokedforarunning activeMySQLtransaction(orrecoveredpreparedtransaction)
that is associated with the current thread. */
switch (trx->state) { case TRX_STATE_ABORTED:
trx->state = TRX_STATE_NOT_STARTED; /* fall through */ case TRX_STATE_NOT_STARTED:
trx->will_lock = false;
ut_ad(trx->mysql_thd); /* Galera transaction abort can be invoked from MDL acquisition code,sotrx->lock.was_chosen_as_deadlock_victimcanbeset
even if trx->state is TRX_STATE_NOT_STARTED. */
ut_ad(!(trx->lock.was_chosen_as_deadlock_victim & 1)); #ifdef WITH_WSREP
ut_ad(!trx->is_wsrep());
trx->lock.was_chosen_as_deadlock_victim= false; #endif
ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); return(DB_SUCCESS); case TRX_STATE_ACTIVE:
ut_ad(trx->mysql_thd);
ut_ad(!trx->is_recovered);
ut_ad(!trx->is_autocommit_non_locking() || trx->read_only); return trx->rollback_low();
case TRX_STATE_PREPARED: case TRX_STATE_PREPARED_RECOVERED:
ut_ad(!trx->is_autocommit_non_locking()); if (trx->rsegs.m_redo.undo) { /* The XA ROLLBACK of a XA PREPARE transaction willconsistofmultiplemini-transactions.
/** Report progress when rolling back a row of a recovered transaction. */ void trx_roll_report_progress()
{
time_t now = time(NULL);
mysql_mutex_lock(&recv_sys.mutex); bool report = recv_sys.report(now);
mysql_mutex_unlock(&recv_sys.mutex);
if (report) {
trx_roll_count_callback_arg arg;
/* Get number of recovered active transactions and number of rowstheymodified.Numbersmustbeaccurate,becauseonlythis
thread is allowed to touch recovered transactions. */
trx_sys.rw_trx_hash.iterate_no_dups(
trx_roll_count_callback, &arg);
/*******************************************************************//**
Rollback or clean up any incomplete transactions which were
encountered in crash recovery. If the transaction already was
committed, then we clean up a possible insert undo log. If the
transaction was not yet committed, then we roll it back.
Note: this is done in a background thread. */ void trx_rollback_all_recovered(void*)
{
ut_ad(!srv_read_only_mode);
ut_ad(!recv_sys.rpo);
if (trx_sys.rw_trx_hash.size()) {
ib::info() << "Starting in background the rollback of" " recovered transactions";
trx_rollback_recovered(true);
ib::info() << "Rollback of non-prepared transactions" " completed";
}
trx_rollback_is_active = false;
}
/****************************************************************//**
Builds an undo 'query' graph for a transaction. The actual rollback is
performed by executing this query graph like a query subprocedure call.
The reply about the completion of the rollback will be sent by this
graph.
@return own: the query graph */ static
que_t*
trx_roll_graph_build( /*=================*/
trx_t* trx) /*!< in/out: transaction */
{
mem_heap_t* heap;
que_fork_t* fork;
que_thr_t* thr;
/*********************************************************************//**
Starts a rollback operation, creates the UNDO graph that will do the
actual undo operation.
@return query graph thread that will perform the UNDO operations. */ static
que_thr_t*
trx_rollback_start( /*===============*/
trx_t* trx, /*!< in: transaction */
undo_no_t roll_limit) /*!< in: rollback to undo no (for partialundo),0ifwearerollingback
the entire transaction */
{ /* Initialize the rollback field in the transaction */
/***********************************************************//**
Performs an execution step for a rollback command node in a query graph.
@return query thread to run next, or NULL */
que_thr_t*
trx_rollback_step( /*==============*/
que_thr_t* thr) /*!< in: query thread */
{
roll_node_t* node;
¤ 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.0.18Bemerkung:
(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.