diff options
Diffstat (limited to 'storage/innobase/trx/trx0trx.cc')
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 307 |
1 files changed, 56 insertions, 251 deletions
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index c9616023d85..52b3d559982 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -729,8 +729,6 @@ void trx_resurrect_table_locks( /*======================*/ trx_t* trx, /*!< in/out: transaction */ - const trx_undo_ptr_t* undo_ptr, - /*!< in: pointer to undo segment. */ const trx_undo_t* undo) /*!< in: undo log */ { mtr_t mtr; @@ -738,8 +736,6 @@ trx_resurrect_table_locks( trx_undo_rec_t* undo_rec; table_id_set tables; - ut_ad(undo == undo_ptr->insert_undo || undo == undo_ptr->update_undo); - if (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) || undo->empty) { return; @@ -800,27 +796,22 @@ trx_resurrect_table_locks( DBUG_PRINT("ib_trx", ("resurrect" TRX_ID_FMT - " table '%s' IX lock from %s undo", + " table '%s' IX lock", trx_get_id_for_print(trx), - table->name.m_name, - undo == undo_ptr->insert_undo - ? "insert" : "update")); + table->name.m_name)); dict_table_close(table, FALSE, FALSE); } } } -/****************************************************************//** -Resurrect the transactions that were doing inserts the time of the -crash, they need to be undone. -@return trx_t instance */ +/** Resurrect the transactions that exited at the time of the +previous crash or shutdown. +@param[in,out] undo undo log +@return transaction instance */ static trx_t* -trx_resurrect_insert( -/*=================*/ - trx_undo_t* undo, /*!< in: entry to UNDO */ - trx_rseg_t* rseg) /*!< in: rollback segment */ +trx_resurrect(trx_undo_t* undo) { trx_t* trx; @@ -829,71 +820,45 @@ trx_resurrect_insert( ut_d(trx->start_file = __FILE__); ut_d(trx->start_line = __LINE__); - trx->rsegs.m_redo.rseg = rseg; - /* For transactions with active data will not have rseg size = 1 - or will not qualify for purge limit criteria. So it is safe to increment - this trx_ref_count w/o mutex protection. */ - ++trx->rsegs.m_redo.rseg->trx_ref_count; + trx->rsegs.m_redo.rseg = undo->rseg; + trx->rsegs.m_redo.undo = undo; + /* It is safe to skip the mutex protection, because purge is + not running and transactions cannot be created yet. */ + ++undo->rseg->trx_ref_count; *trx->xid = undo->xid; trx->id = undo->trx_id; - trx->rsegs.m_redo.insert_undo = undo; trx->is_recovered = true; - /* This is single-threaded startup code, we do not need the - protection of trx->mutex or trx_sys->mutex here. */ - - if (undo->state != TRX_UNDO_ACTIVE) { + /* We assign a dummy value for the commit number; this should + have no relevance since purge is not interested in committed + transaction numbers, unless they are in the history list, in + which case it looks the number from the disk based undo log + structure */ + trx->no = trx->id; + switch (undo->state) { + case TRX_UNDO_PREPARED: /* Prepared transactions are left in the prepared state waiting for a commit or abort decision from MySQL */ - if (undo->state == TRX_UNDO_PREPARED) { - - ib::info() << "Transaction " - << trx_get_id_for_print(trx) - << " was in the XA prepared state."; - - if (srv_force_recovery == 0) { - - trx->state = TRX_STATE_PREPARED; - ++trx_sys->n_prepared_trx; - ++trx_sys->n_prepared_recovered_trx; - } else { - - ib::info() << "Since innodb_force_recovery" - " > 0, we will force a rollback."; - - trx->state = TRX_STATE_ACTIVE; - } - } else { - trx->state = TRX_STATE_COMMITTED_IN_MEMORY; - } - - /* We give a dummy value for the trx no; this should have no - relevance since purge is not interested in committed - transaction numbers, unless they are in the history - list, in which case it looks the number from the disk based - undo log structure */ + ib::info() << "Transaction " << ib::hex(trx->id) + << " was in the XA prepared state."; - trx->no = trx->id; + trx->state = TRX_STATE_PREPARED; + ++trx_sys->n_prepared_trx; + ++trx_sys->n_prepared_recovered_trx; + break; + default: + trx->state = TRX_STATE_COMMITTED_IN_MEMORY; + break; - } else { + case TRX_UNDO_ACTIVE: trx->state = TRX_STATE_ACTIVE; - /* A running transaction always has the number field inited to TRX_ID_MAX */ - trx->no = TRX_ID_MAX; } - /* trx_start_low() is not called with resurrect, so need to initialize - start time here.*/ - if (trx->state == TRX_STATE_ACTIVE - || trx->state == TRX_STATE_PREPARED) { - - trx->start_time = ut_time(); - } - if (undo->dict_operation) { trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx->table_id = undo->table_id; @@ -907,105 +872,6 @@ trx_resurrect_insert( return(trx); } -/****************************************************************//** -Prepared transactions are left in the prepared state waiting for a -commit or abort decision from MySQL */ -static -void -trx_resurrect_update_in_prepared_state( -/*===================================*/ - trx_t* trx, /*!< in,out: transaction */ - const trx_undo_t* undo) /*!< in: update UNDO record */ -{ - /* This is single-threaded startup code, we do not need the - protection of trx->mutex or trx_sys->mutex here. */ - - if (undo->state == TRX_UNDO_PREPARED) { - ib::info() << "Transaction " << trx_get_id_for_print(trx) - << " was in the XA prepared state."; - - if (srv_force_recovery == 0) { - - ut_ad(trx->state != TRX_STATE_FORCED_ROLLBACK); - - if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) { - ++trx_sys->n_prepared_trx; - ++trx_sys->n_prepared_recovered_trx; - } else { - ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED)); - } - - trx->state = TRX_STATE_PREPARED; - } else { - ib::info() << "Since innodb_force_recovery > 0, we" - " will rollback it anyway."; - - trx->state = TRX_STATE_ACTIVE; - } - } else { - trx->state = TRX_STATE_COMMITTED_IN_MEMORY; - } -} - -/****************************************************************//** -Resurrect the transactions that were doing updates the time of the -crash, they need to be undone. */ -static -void -trx_resurrect_update( -/*=================*/ - trx_t* trx, /*!< in/out: transaction */ - trx_undo_t* undo, /*!< in/out: update UNDO record */ - trx_rseg_t* rseg) /*!< in/out: rollback segment */ -{ - trx->rsegs.m_redo.rseg = rseg; - /* For transactions with active data will not have rseg size = 1 - or will not qualify for purge limit criteria. So it is safe to increment - this trx_ref_count w/o mutex protection. */ - ++trx->rsegs.m_redo.rseg->trx_ref_count; - *trx->xid = undo->xid; - trx->id = undo->trx_id; - trx->rsegs.m_redo.update_undo = undo; - trx->is_recovered = true; - - /* This is single-threaded startup code, we do not need the - protection of trx->mutex or trx_sys->mutex here. */ - - if (undo->state != TRX_UNDO_ACTIVE) { - trx_resurrect_update_in_prepared_state(trx, undo); - - /* We give a dummy value for the trx number */ - - trx->no = trx->id; - - } else { - trx->state = TRX_STATE_ACTIVE; - - /* A running transaction always has the number field inited to - TRX_ID_MAX */ - - trx->no = TRX_ID_MAX; - } - - /* trx_start_low() is not called with resurrect, so need to initialize - start time here.*/ - if (trx->state == TRX_STATE_ACTIVE - || trx->state == TRX_STATE_PREPARED) { - trx->start_time = ut_time(); - } - - if (undo->dict_operation) { - trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); - trx->table_id = undo->table_id; - } - - if (!undo->empty && undo->top_undo_no >= trx->undo_no) { - - trx->undo_no = undo->top_undo_no + 1; - trx->undo_rseg_space = undo->rseg->space; - } -} - /** Initialize (resurrect) transactions at startup. */ void trx_lists_init_at_db_start() @@ -1022,9 +888,9 @@ trx_lists_init_at_db_start() /* Look from the rollback segments if there exist undo logs for transactions. */ + ib_time_t start_time = ut_time(); for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { - trx_undo_t* undo; trx_rseg_t* rseg = trx_sys->rseg_array[i]; /* At this stage non-redo rseg slots are all NULL as they are @@ -1033,46 +899,16 @@ trx_lists_init_at_db_start() continue; } - /* Resurrect transactions that were doing inserts. */ - for (undo = UT_LIST_GET_FIRST(rseg->insert_undo_list); - undo != NULL; - undo = UT_LIST_GET_NEXT(undo_list, undo)) { - - trx_t* trx; - - trx = trx_resurrect_insert(undo, rseg); - - trx_sys_rw_trx_add(trx); - - trx_resurrect_table_locks( - trx, &trx->rsegs.m_redo, undo); - } - - /* Ressurrect transactions that were doing updates. */ - for (undo = UT_LIST_GET_FIRST(rseg->update_undo_list); + /* Resurrect transactions. */ + for (trx_undo_t* undo = UT_LIST_GET_FIRST(rseg->undo_list); undo != NULL; undo = UT_LIST_GET_NEXT(undo_list, undo)) { - /* Check the trx_sys->rw_trx_set first. */ - trx_sys_mutex_enter(); - - trx_t* trx = trx_get_rw_trx_by_id(undo->trx_id); - - trx_sys_mutex_exit(); - - if (trx == NULL) { - trx = trx_allocate_for_background(); - - ut_d(trx->start_file = __FILE__); - ut_d(trx->start_line = __LINE__); - } - - trx_resurrect_update(trx, undo, rseg); - + ut_ad(undo->rseg == rseg); + trx_t* trx = trx_resurrect(undo); + trx->start_time = start_time; trx_sys_rw_trx_add(trx); - - trx_resurrect_table_locks( - trx, &trx->rsegs.m_redo, undo); + trx_resurrect_table_locks(trx, undo); } } @@ -1489,7 +1325,7 @@ trx_start_low( /** Set the serialisation number for a persistent committed transaction. @param[in,out] trx committed transaction with persistent changes -@param[in,out] rseg rollback segment for update_undo, or NULL */ +@param[in,out] rseg rollback segment for undo, or NULL */ static void trx_serialise(trx_t* trx, trx_rseg_t* rseg) @@ -1564,39 +1400,32 @@ trx_write_serialisation_history( } if (!trx->rsegs.m_redo.rseg) { - ut_ad(!trx->rsegs.m_redo.insert_undo); - ut_ad(!trx->rsegs.m_redo.update_undo); + ut_ad(!trx->rsegs.m_redo.undo); return false; } - trx_undo_t* insert = trx->rsegs.m_redo.insert_undo; - trx_undo_t* update = trx->rsegs.m_redo.update_undo; + trx_undo_t* undo = trx->rsegs.m_redo.undo; - if (!insert && !update) { + if (!undo) { return false; } ut_ad(!trx->read_only); - trx_rseg_t* update_rseg = update ? trx->rsegs.m_redo.rseg : NULL; + trx_rseg_t* undo_rseg = undo ? undo->rseg : NULL; + ut_ad(!undo || undo->rseg == trx->rsegs.m_redo.rseg); mutex_enter(&trx->rsegs.m_redo.rseg->mutex); /* Assign the transaction serialisation number and add any - update_undo log to the purge queue. */ - trx_serialise(trx, update_rseg); + undo log to the purge queue. */ + trx_serialise(trx, undo_rseg); /* It is not necessary to acquire trx->undo_mutex here because only a single OS thread is allowed to commit this transaction. */ - if (insert) { - trx_undo_set_state_at_finish(insert, mtr); - } - if (update) { - /* The undo logs and possible delete-marked records - for updates and deletes will be purged later. */ - page_t* undo_hdr_page = trx_undo_set_state_at_finish( - update, mtr); - trx_undo_update_cleanup(trx, undo_hdr_page, mtr); - } + /* The undo logs and possible delete-marked records for + updates and deletes will be purged later. */ + page_t* undo_hdr_page = trx_undo_set_state_at_finish(undo, mtr); + trx_undo_update_cleanup(trx, undo_hdr_page, mtr); mutex_exit(&trx->rsegs.m_redo.rseg->mutex); @@ -1912,27 +1741,19 @@ trx_commit_in_memory( } } - ut_ad(!trx->rsegs.m_redo.update_undo); + ut_ad(!trx->rsegs.m_redo.undo); if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) { mutex_enter(&rseg->mutex); ut_ad(rseg->trx_ref_count > 0); --rseg->trx_ref_count; mutex_exit(&rseg->mutex); - - if (trx_undo_t*& insert = trx->rsegs.m_redo.insert_undo) { - ut_ad(insert->rseg == rseg); - trx_undo_commit_cleanup(insert, false); - insert = NULL; - } } - ut_ad(!trx->rsegs.m_redo.insert_undo); - if (mtr != NULL) { if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) { ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); - trx_undo_commit_cleanup(undo, true); + trx_undo_commit_cleanup(undo); undo = NULL; } @@ -2159,13 +1980,7 @@ trx_cleanup_at_db_startup( { ut_ad(trx->is_recovered); ut_ad(!trx->rsegs.m_noredo.undo); - ut_ad(!trx->rsegs.m_redo.update_undo); - - if (trx_undo_t*& undo = trx->rsegs.m_redo.insert_undo) { - ut_ad(undo->rseg == trx->rsegs.m_redo.rseg); - trx_undo_commit_cleanup(undo, false); - undo = NULL; - } + ut_ad(!trx->rsegs.m_redo.undo); memset(&trx->rsegs, 0x0, sizeof(trx->rsegs)); trx->undo_no = 0; @@ -2707,15 +2522,15 @@ trx_prepare_low(trx_t* trx) mtr.commit(); } - trx_undo_t* insert = trx->rsegs.m_redo.insert_undo; - trx_undo_t* update = trx->rsegs.m_redo.update_undo; + trx_undo_t* undo = trx->rsegs.m_redo.undo; - if (!insert && !update) { + if (!undo) { /* There were no changes to persistent tables. */ return(0); } trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; + ut_ad(undo->rseg == rseg); mtr.start(true); @@ -2725,17 +2540,7 @@ trx_prepare_low(trx_t* trx) world, at the serialization point of lsn. */ mutex_enter(&rseg->mutex); - - if (insert) { - ut_ad(insert->rseg == rseg); - trx_undo_set_state_at_prepare(trx, insert, false, &mtr); - } - - if (update) { - ut_ad(update->rseg == rseg); - trx_undo_set_state_at_prepare(trx, update, false, &mtr); - } - + trx_undo_set_state_at_prepare(trx, undo, false, &mtr); mutex_exit(&rseg->mutex); /* Make the XA PREPARE durable. */ |