Skip to content

Commit

Permalink
MDEV-14756 - Remove trx_sys_t::rw_trx_list
Browse files Browse the repository at this point in the history
Reduce divergence between trx_sys_t::rw_trx_hash and trx_sys_t::rw_trx_list
by not adding recovered COMMITTED transactions to trx_sys_t::rw_trx_list.

Such transactions are discarded immediately without creating trx object.

This also required to split rollback and cleanup phases of recovery. To
reflect these updates the following renames happened:
trx_rollback_or_clean_all_recovered() -> trx_rollback_all_recovered()
trx_rollback_or_clean_is_active -> trx_rollback_is_active
trx_rollback_or_clean_recovered() -> trx_rollback_recovered()
trx_cleanup_at_db_startup() -> trx_cleanup_recovered()

Also removed a hack from lock_trx_release_locks(). Instead let recovery
rollback thread to skip committed XA transactions.
  • Loading branch information
svoj committed Jan 20, 2018
1 parent 07c0bac commit d09f146
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 321 deletions.
2 changes: 1 addition & 1 deletion storage/innobase/btr/btr0cur.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7782,7 +7782,7 @@ btr_free_externally_stored_field(
MLOG_4BYTES, &mtr);
/* Zero out the BLOB length. If the server
crashes during the execution of this function,
trx_rollback_or_clean_all_recovered() could
trx_rollback_all_recovered() could
dereference the half-deleted BLOB, fetching a
wrong prefix for the BLOB. */
mlog_write_ulint(field_ref + BTR_EXTERN_LEN + 4,
Expand Down
17 changes: 6 additions & 11 deletions storage/innobase/include/trx0roll.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"

extern bool trx_rollback_or_clean_is_active;
extern bool trx_rollback_is_active;
extern const trx_t* trx_roll_crash_recv_trx;

/*******************************************************************//**
Expand Down Expand Up @@ -71,12 +71,11 @@ trx_roll_must_shutdown();
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. */
transaction was not yet committed, then we roll it back.
@param all true=roll back all recovered active transactions;
false=roll back any incomplete dictionary transaction */
void
trx_rollback_or_clean_recovered(
/*============================*/
ibool all); /*!< in: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
trx_rollback_recovered(bool all);
/*******************************************************************//**
Rollback or clean up any incomplete transactions which were
encountered in crash recovery. If the transaction already was
Expand All @@ -86,11 +85,7 @@ Note: this is done in a background thread.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
/*================================================*/
void* arg MY_ATTRIBUTE((unused)));
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(trx_rollback_all_recovered)(void*);
/*********************************************************************//**
Creates a rollback command node struct.
@return own: rollback node struct */
Expand Down
8 changes: 0 additions & 8 deletions storage/innobase/include/trx0trx.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,6 @@ trx_commit_low(
trx_t* trx, /*!< in/out: transaction */
mtr_t* mtr); /*!< in/out: mini-transaction (will be committed),
or NULL if trx made no modifications */
/****************************************************************//**
Cleans up a transaction at database startup. The cleanup is needed if
the transaction already got to the middle of a commit when the database
crashed, and we cannot roll it back. */
void
trx_cleanup_at_db_startup(
/*======================*/
trx_t* trx); /*!< in: transaction */
/**********************************************************************//**
Does the transaction commit for MySQL.
@return DB_SUCCESS or error number */
Expand Down
27 changes: 2 additions & 25 deletions storage/innobase/lock/lock0lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7630,8 +7630,6 @@ lock_trx_release_locks(
lock_mutex_enter();
}

trx_mutex_enter(trx);

/* The following assignment makes the transaction committed in memory
and makes its changes to data visible to other transactions.
NOTE that there is a small discrepancy from the strict formal
Expand All @@ -7647,7 +7645,9 @@ lock_trx_release_locks(
committed. */

/*--------------------------------------*/
trx_mutex_enter(trx);
trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
trx_mutex_exit(trx);
/*--------------------------------------*/

if (trx->is_referenced()) {
Expand All @@ -7658,41 +7658,18 @@ lock_trx_release_locks(

while (trx->is_referenced()) {

trx_mutex_exit(trx);

DEBUG_SYNC_C("waiting_trx_is_not_referenced");

/** Doing an implicit to explicit conversion
should not be expensive. */
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));

trx_mutex_enter(trx);
}

trx_mutex_exit(trx);

lock_mutex_enter();

trx_mutex_enter(trx);
}

ut_ad(!trx->is_referenced());

/* If the background thread trx_rollback_or_clean_recovered()
is still active then there is a chance that the rollback
thread may see this trx as COMMITTED_IN_MEMORY and goes ahead
to clean it up calling trx_cleanup_at_db_startup(). This can
happen in the case we are committing a trx here that is left
in PREPARED state during the crash. Note that commit of the
rollback of a PREPARED trx happens in the recovery thread
while the rollback of other transactions happen in the
background thread. To avoid this race we unconditionally unset
the is_recovered flag. */

trx->is_recovered = false;

trx_mutex_exit(trx);

if (release_lock) {

lock_release(trx);
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/log/log0log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,7 @@ logs_empty_and_mark_files_at_shutdown(void)
goto wait_suspend_loop;
} else if (btr_defragment_thread_active) {
thread_name = "btr_defragment_thread";
} else if (srv_fast_shutdown != 2 && trx_rollback_or_clean_is_active) {
} else if (srv_fast_shutdown != 2 && trx_rollback_is_active) {
thread_name = "rollback of recovered transactions";
} else {
thread_name = NULL;
Expand Down
4 changes: 2 additions & 2 deletions storage/innobase/log/log0recv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3426,8 +3426,8 @@ recv_recovery_rollback_active(void)
/* Rollback the uncommitted transactions which have no user
session */

trx_rollback_or_clean_is_active = true;
os_thread_create(trx_rollback_or_clean_all_recovered, 0, 0);
trx_rollback_is_active = true;
os_thread_create(trx_rollback_all_recovered, 0, 0);
}
}

Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/row/row0ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ row_ext_cache_fill(
} else {
/* Fetch at most ext->max_len of the column.
The column should be non-empty. However,
trx_rollback_or_clean_all_recovered() may try to
trx_rollback_all_recovered() may try to
access a half-deleted BLOB if the server previously
crashed during the execution of
btr_free_externally_stored_field(). */
Expand Down
4 changes: 2 additions & 2 deletions storage/innobase/srv/srv0start.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,7 @@ innobase_start_or_create_for_mysql()
+ 1 /* dict_stats_thread */
+ 1 /* fts_optimize_thread */
+ 1 /* recv_writer_thread */
+ 1 /* trx_rollback_or_clean_all_recovered */
+ 1 /* trx_rollback_all_recovered */
+ 128 /* added as margin, for use of
InnoDB Memcached etc. */
+ max_connections
Expand Down Expand Up @@ -2471,7 +2471,7 @@ innobase_start_or_create_for_mysql()
The data dictionary latch should guarantee that there is at
most one data dictionary transaction active at a time. */
if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
trx_rollback_or_clean_recovered(FALSE);
trx_rollback_recovered(false);
}

/* Fix-up truncate of tables in the system tablespace
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/trx/trx0purge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
continue to execute user transactions. */
ut_ad(srv_undo_sources
|| ((srv_startup_is_before_trx_rollback_phase
|| trx_rollback_or_clean_is_active)
|| trx_rollback_is_active)
&& purge_sys->state == PURGE_STATE_INIT)
|| (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
&& purge_sys->state == PURGE_STATE_DISABLED)
Expand Down
37 changes: 13 additions & 24 deletions storage/innobase/trx/trx0roll.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ Created 3/26/1996 Heikki Tuuri
rollback */
static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1;

/** true if trx_rollback_or_clean_all_recovered() thread is active */
bool trx_rollback_or_clean_is_active;
/** true if trx_rollback_all_recovered() thread is active */
bool trx_rollback_is_active;

/** In crash recovery, the current trx to be rolled back; NULL otherwise */
const trx_t* trx_roll_crash_recv_trx;
Expand Down Expand Up @@ -734,7 +734,7 @@ ibool
trx_rollback_resurrected(
/*=====================*/
trx_t* trx, /*!< in: transaction to rollback or clean */
ibool* all) /*!< in/out: FALSE=roll back dictionary transactions;
bool* all) /*!< in/out: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
{
ut_ad(trx_sys_mutex_own());
Expand All @@ -752,22 +752,14 @@ trx_rollback_resurrected(
}

switch (trx->state) {
case TRX_STATE_COMMITTED_IN_MEMORY:
trx_mutex_exit(trx);
trx_sys_mutex_exit();
ib::info() << "Cleaning up trx with id " << ib::hex(trx->id);

trx_cleanup_at_db_startup(trx);
trx_free_resurrected(trx);
return(TRUE);
case TRX_STATE_ACTIVE:
if (!srv_is_being_started
&& !srv_undo_sources && srv_fast_shutdown) {
fake_prepared:
trx->state = TRX_STATE_PREPARED;
trx_sys->n_prepared_trx++;
trx_sys->n_prepared_recovered_trx++;
*all = FALSE;
*all = false;
goto func_exit;
}
trx_mutex_exit(trx);
Expand All @@ -788,6 +780,8 @@ trx_rollback_resurrected(
return(TRUE);
}
return(FALSE);
case TRX_STATE_COMMITTED_IN_MEMORY:
ut_ad(trx->xid);
case TRX_STATE_PREPARED:
goto func_exit;
case TRX_STATE_NOT_STARTED:
Expand Down Expand Up @@ -848,12 +842,11 @@ trx_roll_must_shutdown()
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. */
transaction was not yet committed, then we roll it back.
@param all true=roll back all recovered active transactions;
false=roll back any incomplete dictionary transaction */
void
trx_rollback_or_clean_recovered(
/*============================*/
ibool all) /*!< in: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
trx_rollback_recovered(bool all)
{
trx_t* trx;

Expand Down Expand Up @@ -917,11 +910,7 @@ Note: this is done in a background thread.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
/*================================================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(trx_rollback_all_recovered)(void*)
{
my_thread_init();
ut_ad(!srv_read_only_mode);
Expand All @@ -930,9 +919,9 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
pfs_register_thread(trx_rollback_clean_thread_key);
#endif /* UNIV_PFS_THREAD */

trx_rollback_or_clean_recovered(TRUE);
trx_rollback_recovered(true);

trx_rollback_or_clean_is_active = false;
trx_rollback_is_active = false;

my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
Expand Down
Loading

0 comments on commit d09f146

Please sign in to comment.