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
Let trx_rollback_recovered() iterate rw_trx_hash instead of rw_trx_list.
  • Loading branch information
svoj committed Jan 20, 2018
1 parent 02270b4 commit 886af39
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 136 deletions.
2 changes: 1 addition & 1 deletion storage/innobase/include/trx0sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ class rw_trx_hash_t
(!srv_was_started ||
srv_read_only_mode ||
srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
trx_free_prepared(trx);
trx_free_at_shutdown(trx);
}
element->~rw_trx_hash_element_t();
}
Expand Down
7 changes: 2 additions & 5 deletions storage/innobase/include/trx0trx.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,9 @@ trx_free_resurrected(trx_t* trx);
void
trx_free_for_background(trx_t* trx);

/********************************************************************//**
At shutdown, frees a transaction object that is in the PREPARED state. */
/** At shutdown, frees a transaction object. */
void
trx_free_prepared(
/*==============*/
trx_t* trx); /*!< in, own: trx object */
trx_free_at_shutdown(trx_t *trx);

/** Free a transaction object for MySQL.
@param[in,out] trx transaction */
Expand Down
8 changes: 2 additions & 6 deletions storage/innobase/include/trx0undo.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,9 @@ the data can be discarded.
void
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp);

/********************************************************************//**
At shutdown, frees the undo logs of a PREPARED transaction. */
/** At shutdown, frees the undo logs of a transaction. */
void
trx_undo_free_prepared(
/*===================*/
trx_t* trx) /*!< in/out: PREPARED transaction */
ATTRIBUTE_COLD __attribute__((nonnull));
trx_undo_free_at_shutdown(trx_t *trx);

/* Forward declaration. */
namespace undo {
Expand Down
168 changes: 67 additions & 101 deletions storage/innobase/trx/trx0roll.cc
Original file line number Diff line number Diff line change
Expand Up @@ -723,74 +723,6 @@ trx_rollback_active(
trx_roll_crash_recv_trx = NULL;
}

/*******************************************************************//**
Rollback or clean up any resurrected incomplete transactions. It assumes
that the caller holds the trx_sys_t::mutex and it will release the
lock if it does a clean up or rollback.
@return TRUE if the transaction was cleaned up or rolled back
and trx_sys->mutex was released. */
static
ibool
trx_rollback_resurrected(
/*=====================*/
trx_t* trx, /*!< in: transaction to rollback or clean */
bool* all) /*!< in/out: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
{
ut_ad(trx_sys_mutex_own());

/* The trx->is_recovered flag and trx->state are set
atomically under the protection of the trx->mutex (and
lock_sys->mutex) in lock_trx_release_locks(). We do not want
to accidentally clean up a non-recovered transaction here. */

trx_mutex_enter(trx);
if (!trx->is_recovered) {
func_exit:
trx_mutex_exit(trx);
return(FALSE);
}

switch (trx->state) {
case TRX_STATE_ACTIVE:
if (!srv_is_being_started
&& !srv_undo_sources && srv_fast_shutdown) {
fake_prepared:
trx->state = TRX_STATE_PREPARED;
*all = false;
goto func_exit;
}
trx_mutex_exit(trx);

if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
trx_sys_mutex_exit();
trx_rollback_active(trx);
if (trx->error_state != DB_SUCCESS) {
ut_ad(trx->error_state == DB_INTERRUPTED);
trx->error_state = DB_SUCCESS;
ut_ad(!srv_undo_sources);
ut_ad(srv_fast_shutdown);
mutex_enter(&trx_sys->mutex);
trx_mutex_enter(trx);
goto fake_prepared;
}
trx_free_for_background(trx);
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:
case TRX_STATE_FORCED_ROLLBACK:
break;
}

ut_error;
goto func_exit;
}


struct trx_roll_count_callback_arg
{
Expand Down Expand Up @@ -856,54 +788,88 @@ trx_roll_must_shutdown()
return false;
}

/*******************************************************************//**
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.
@param all true=roll back all recovered active transactions;
false=roll back any incomplete dictionary transaction */
void
trx_rollback_recovered(bool all)

static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element,
trx_ut_list_t *trx_list)
{
trx_t* trx;
mutex_enter(&element->mutex);
if (trx_t *trx= element->trx)
{
mutex_enter(&trx->mutex);
assert_trx_in_rw_list(trx);
if (trx->is_recovered && trx_state_eq(trx, TRX_STATE_ACTIVE))
UT_LIST_ADD_FIRST(*trx_list, trx);
mutex_exit(&trx->mutex);
}
mutex_exit(&element->mutex);
return 0;
}

ut_a(srv_force_recovery < SRV_FORCE_NO_TRX_UNDO);

/* Note: For XA recovered transactions, we rely on MySQL to
do rollback. They will be in TRX_STATE_PREPARED state. If the server
is shutdown and they are still lingering in trx_sys_t::trx_list
then the shutdown will hang. */
/**
Rollback any incomplete transactions which were encountered in crash recovery.
/* Loop over the transaction list as long as there are
recovered transactions to clean up or recover. */
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.
do {
trx_sys_mutex_enter();
Note: For XA recovered transactions, we rely on MySQL to
do rollback. They will be in TRX_STATE_PREPARED state. If the server
is shutdown and they are still lingering in trx_sys_t::trx_list
then the shutdown will hang.
for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
trx != NULL;
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
@param[in] all true=roll back all recovered active transactions;
false=roll back any incomplete dictionary transaction
*/

assert_trx_in_rw_list(trx);
void trx_rollback_recovered(bool all)
{
trx_ut_list_t trx_list;

/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
we need to reacquire it before retrying the loop. */
ut_a(srv_force_recovery < SRV_FORCE_NO_TRX_UNDO);
UT_LIST_INIT(trx_list, &trx_t::mysql_trx_list);

if (trx_rollback_resurrected(trx, &all)) {
/*
Collect list of recovered ACTIVE transaction ids first. Once collected, no
other thread is allowed to modify or remove these transactions from
rw_trx_hash.
*/
trx_sys->rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(trx_rollback_recovered_callback), &trx_list);

trx_sys_mutex_enter();
while (trx_t *trx= UT_LIST_GET_FIRST(trx_list))
{
UT_LIST_REMOVE(trx_list, trx);

break;
}
}
#ifdef UNIV_DEBUG
ut_ad(trx);
trx_mutex_enter(trx);
ut_ad(trx->is_recovered && trx_state_eq(trx, TRX_STATE_ACTIVE));
trx_mutex_exit(trx);
#endif

trx_sys_mutex_exit();
if (!srv_is_being_started && !srv_undo_sources && srv_fast_shutdown)
goto discard;

} while (trx != NULL);
if (all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE)
{
trx_rollback_active(trx);
if (trx->error_state != DB_SUCCESS)
{
ut_ad(trx->error_state == DB_INTERRUPTED);
trx->error_state= DB_SUCCESS;
ut_ad(!srv_undo_sources);
ut_ad(srv_fast_shutdown);
discard:
trx_sys->rw_trx_hash.erase(trx);
trx_free_at_shutdown(trx);
}
else
trx_free_for_background(trx);
}
}
}


/*******************************************************************//**
Rollback or clean up any incomplete transactions which were
encountered in crash recovery. If the transaction already was
Expand Down
18 changes: 8 additions & 10 deletions storage/innobase/trx/trx0trx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -623,26 +623,24 @@ trx_free_for_background(trx_t* trx)
trx_free(trx);
}

/********************************************************************//**
At shutdown, frees a transaction object that is in the PREPARED state. */
/** At shutdown, frees a transaction object. */
void
trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
trx_free_at_shutdown(trx_t *trx)
{
ut_ad(trx->is_recovered);
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED)
|| (trx->is_recovered
&& (trx_state_eq(trx, TRX_STATE_ACTIVE)
|| trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY))
|| (trx_state_eq(trx, TRX_STATE_ACTIVE)
&& (!srv_was_started
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|| (!srv_is_being_started
&& !srv_undo_sources && srv_fast_shutdown))));
ut_a(trx->magic_n == TRX_MAGIC_N);

lock_trx_release_locks(trx);
trx_undo_free_prepared(trx);
trx_undo_free_at_shutdown(trx);

assert_trx_in_rw_list(trx);
UT_LIST_REMOVE(trx_sys->rw_trx_list, trx);
Expand Down
17 changes: 4 additions & 13 deletions storage/innobase/trx/trx0undo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1622,15 +1622,10 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
mutex_exit(&rseg->mutex);
}

/********************************************************************//**
At shutdown, frees the undo logs of a PREPARED transaction. */
/** At shutdown, frees the undo logs of a transaction. */
void
trx_undo_free_prepared(
/*===================*/
trx_t* trx) /*!< in/out: PREPARED transaction */
trx_undo_free_at_shutdown(trx_t *trx)
{
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);

if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) {
switch (undo->state) {
case TRX_UNDO_PREPARED:
Expand All @@ -1643,9 +1638,7 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
trx->state = TRX_STATE_COMMITTED_IN_MEMORY. */
ut_a(!srv_was_started
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
Expand All @@ -1672,9 +1665,7 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
trx->state = TRX_STATE_COMMITTED_IN_MEMORY. */
ut_a(!srv_was_started
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
Expand Down

0 comments on commit 886af39

Please sign in to comment.