diff options
Diffstat (limited to 'storage/innobase/trx')
-rw-r--r-- | storage/innobase/trx/trx0i_s.cc | 14 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 42 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rec.cc | 101 | ||||
-rw-r--r-- | storage/innobase/trx/trx0roll.cc | 190 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 74 | ||||
-rw-r--r-- | storage/innobase/trx/trx0sys.cc | 9 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 27 | ||||
-rw-r--r-- | storage/innobase/trx/trx0undo.cc | 56 |
8 files changed, 169 insertions, 344 deletions
diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 663f39d8b7e..965faaba478 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -29,16 +29,7 @@ table cache" for later retrieval. Created July 17, 2007 Vasil Dimov *******************************************************/ -/* Found during the build of 5.5.3 on Linux 2.4 and early 2.6 kernels: - The includes "univ.i" -> "my_global.h" cause a different path - to be taken further down with pthread functions and types, - so they must come first. - From the symptoms, this is related to bug#46587 in the MySQL bug DB. -*/ - -#include "ha_prototypes.h" -#include <sql_class.h> - +#include "trx0i_s.h" #include "buf0buf.h" #include "dict0dict.h" #include "ha0storage.h" @@ -52,10 +43,7 @@ Created July 17, 2007 Vasil Dimov #include "srv0srv.h" #include "sync0rw.h" #include "sync0sync.h" -#include "trx0i_s.h" #include "trx0sys.h" -#include "trx0trx.h" -#include "ut0mem.h" #include "que0que.h" #include "trx0purge.h" diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 0802805e281..4a5204f299b 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -24,8 +24,6 @@ Purge old versions Created 3/26/1996 Heikki Tuuri *******************************************************/ -#include "ha_prototypes.h" - #include "trx0purge.h" #include "fsp0fsp.h" #include "fut0fut.h" @@ -36,7 +34,6 @@ Created 3/26/1996 Heikki Tuuri #include "row0purge.h" #include "row0upd.h" #include "srv0mon.h" -#include "fsp0sysspace.h" #include "srv0srv.h" #include "srv0start.h" #include "sync0sync.h" @@ -167,8 +164,6 @@ void purge_sys_t::create() ut_ad(event); m_paused= 0; query= purge_graph_build(); - n_submitted= 0; - n_completed= 0; next_stored= false; rseg= NULL; page_no= 0; @@ -187,7 +182,8 @@ void purge_sys_t::close() ut_ad(this == &purge_sys); if (!event) return; - m_enabled= false; + ut_ad(!enabled()); + ut_ad(n_tasks.load(std::memory_order_relaxed) == 0); trx_t* trx = query->trx; que_graph_free(query); ut_ad(!trx->id); @@ -318,7 +314,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) rseg->needs_purge = true; } - trx_sys.history_insert(); + trx_sys.rseg_history_len++; if (undo->state == TRX_UNDO_CACHED) { UT_LIST_ADD_FIRST(rseg->undo_cached, undo); @@ -344,7 +340,7 @@ trx_purge_remove_log_hdr( { flst_remove(rseg_hdr + TRX_RSEG_HISTORY, log_hdr + TRX_UNDO_HISTORY_NODE, mtr); - trx_sys.history_remove(); + trx_sys.rseg_history_len--; } /** Free an undo log segment, and remove the header from the history list. @@ -783,7 +779,7 @@ not_free: os_offset_t(size) << srv_page_size_shift, true); - /* This is only executed by the srv_coordinator_thread. */ + /* This is only executed by srv_purge_coordinator_thread. */ export_vars.innodb_undo_truncations++; /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */ @@ -1243,7 +1239,7 @@ trx_purge_dml_delay(void) if (srv_max_purge_lag > 0) { float ratio; - ratio = float(trx_sys.history_size()) / srv_max_purge_lag; + ratio = float(trx_sys.rseg_history_len) / srv_max_purge_lag; if (ratio > 1.0) { /* If the history list length exceeds the @@ -1269,8 +1265,7 @@ void trx_purge_wait_for_workers_to_complete() { /* Ensure that the work queue empties out. */ - while (my_atomic_loadlint(&purge_sys.n_completed) - != purge_sys.n_submitted) { + while (purge_sys.n_tasks.load(std::memory_order_acquire)) { if (srv_get_task_queue_length() > 0) { srv_release_threads(SRV_WORKER, 1); @@ -1301,9 +1296,8 @@ trx_purge( srv_dml_needed_delay = trx_purge_dml_delay(); - /* The number of tasks submitted should be completed. */ - ut_a(purge_sys.n_submitted - == my_atomic_loadlint(&purge_sys.n_completed)); + /* All submitted tasks should be completed. */ + ut_ad(purge_sys.n_tasks.load(std::memory_order_relaxed) == 0); rw_lock_x_lock(&purge_sys.latch); trx_sys.clone_oldest_view(); @@ -1317,7 +1311,7 @@ trx_purge( /* Fetch the UNDO recs that need to be purged. */ n_pages_handled = trx_purge_attach_undo_recs(n_purge_threads); - purge_sys.n_submitted += n_purge_threads; + purge_sys.n_tasks.store(n_purge_threads - 1, std::memory_order_relaxed); /* Submit tasks to workers queue if using multi-threaded purge. */ for (ulint i = n_purge_threads; --i; ) { @@ -1330,14 +1324,9 @@ trx_purge( que_run_threads(thr); - my_atomic_addlint(&purge_sys.n_completed, 1); - - if (n_purge_threads > 1) { - trx_purge_wait_for_workers_to_complete(); - } + trx_purge_wait_for_workers_to_complete(); - ut_a(purge_sys.n_submitted - == my_atomic_loadlint(&purge_sys.n_completed)); + ut_ad(purge_sys.n_tasks.load(std::memory_order_relaxed) == 0); if (truncate) { trx_purge_truncate_history(); @@ -1354,7 +1343,7 @@ void purge_sys_t::stop() { rw_lock_x_lock(&latch); - if (!enabled_latched()) + if (!enabled()) { /* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */ ut_ad(!srv_undo_sources); @@ -1364,7 +1353,7 @@ void purge_sys_t::stop() ut_ad(srv_n_purge_threads > 0); - if (0 == my_atomic_add32_explicit(&m_paused, 1, MY_MEMORY_ORDER_RELAXED)) + if (m_paused++ == 0) { /* We need to wakeup the purge thread in case it is suspended, so that it can acknowledge the state change. */ @@ -1398,8 +1387,7 @@ void purge_sys_t::resume() return; } - int32_t paused= my_atomic_add32_explicit(&m_paused, -1, - MY_MEMORY_ORDER_RELAXED); + int32_t paused= m_paused--; ut_a(paused); if (paused == 1) diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index a2f08fdb074..595c2a15fb3 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -37,7 +37,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0purge.h" #include "trx0rseg.h" #include "row0row.h" -#include "fsp0sysspace.h" #include "row0mysql.h" /** The search tuple corresponding to TRX_UNDO_INSERT_METADATA. */ @@ -954,9 +953,7 @@ trx_undo_page_report_modify( *ptr++ = (byte) rec_get_info_bits(rec, dict_table_is_comp(table)); /* Store the values of the system columns */ - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_TRX_ID), &flen); + field = rec_get_nth_field(rec, offsets, index->db_trx_id(), &flen); ut_ad(flen == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); @@ -970,9 +967,7 @@ trx_undo_page_report_modify( } ptr += mach_u64_write_compressed(ptr, trx_id); - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_ROLL_PTR), &flen); + field = rec_get_nth_field(rec, offsets, index->db_roll_ptr(), &flen); ut_ad(flen == DATA_ROLL_PTR_LEN); ut_ad(memcmp(field, field_ref_zero, DATA_ROLL_PTR_LEN)); @@ -1340,6 +1335,8 @@ store_len: table, col); ut_a(prefix_len < sizeof ext_buf); + const page_size_t& page_size + = dict_table_page_size(table); /* If there is a spatial index on it, log its MBR */ @@ -1348,9 +1345,7 @@ store_len: col->mtype)); trx_undo_get_mbr_from_ext( - mbr, - dict_table_page_size( - table), + mbr, page_size, field, &flen); } @@ -1359,7 +1354,7 @@ store_len: flen < REC_ANTELOPE_MAX_INDEX_COL_LEN && !ignore_prefix ? ext_buf : NULL, prefix_len, - dict_table_page_size(table), + page_size, &field, &flen, spatial_status); } else { @@ -1553,7 +1548,6 @@ trx_undo_update_rec_get_update( upd_t* update; ulint n_fields; byte* buf; - ulint i; bool first_v_col = true; bool is_undo_log = true; ulint n_skip_field = 0; @@ -1566,7 +1560,7 @@ trx_undo_update_rec_get_update( n_fields = 0; } - update = upd_create(n_fields + 2, heap); + *upd = update = upd_create(n_fields + 2, heap); update->info_bits = info_bits; @@ -1578,9 +1572,7 @@ trx_undo_update_rec_get_update( mach_write_to_6(buf, trx_id); - upd_field_set_field_no(upd_field, - dict_index_get_sys_col_pos(index, DATA_TRX_ID), - index); + upd_field_set_field_no(upd_field, index->db_trx_id(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); upd_field = upd_get_nth_field(update, n_fields + 1); @@ -1589,15 +1581,12 @@ trx_undo_update_rec_get_update( trx_write_roll_ptr(buf, roll_ptr); - upd_field_set_field_no( - upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), - index); + upd_field_set_field_no(upd_field, index->db_roll_ptr(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); /* Store then the updated ordinary columns to the update vector */ - for (i = 0; i < n_fields; i++) { - + for (ulint i = 0; i < n_fields; i++) { const byte* field; ulint len; ulint orig_len; @@ -1630,23 +1619,53 @@ trx_undo_update_rec_get_update( upd_field_set_v_field_no(upd_field, field_no, index); } else if (UNIV_UNLIKELY((update->info_bits & ~REC_INFO_DELETED_FLAG) - == REC_INFO_MIN_REC_FLAG) - && index->is_instant()) { + == REC_INFO_MIN_REC_FLAG)) { + ut_ad(type == TRX_UNDO_UPD_EXIST_REC); const ulint uf = index->first_user_field(); ut_ad(field_no >= uf); if (update->info_bits != REC_INFO_MIN_REC_FLAG) { + /* Generic instant ALTER TABLE */ if (field_no == uf) { upd_field->new_val.type .metadata_blob_init(); + } else if (field_no >= index->n_fields) { + /* This is reachable during + purge if the table was emptied + and converted to the canonical + format on a later ALTER TABLE. + In this case, + row_purge_upd_exist_or_extern() + would only be interested in + freeing any BLOBs that were + updated, that is, the metadata + BLOB above. Other BLOBs in + the metadata record are never + updated; they are for the + initial DEFAULT values of the + instantly added columns, and + they will never change. + + Note: if the table becomes + empty during ROLLBACK or is + empty during subsequent ALTER + TABLE, and btr_page_empty() is + called to re-create the root + page without the metadata + record, in that case we should + only free the latest version + of BLOBs in the record, + which purge would never touch. */ + field_no = REC_MAX_N_FIELDS; + n_skip_field++; } else { - ut_ad(field_no > uf); dict_col_copy_type( dict_index_get_nth_col( index, field_no - 1), &upd_field->new_val.type); } } else { + /* Instant ADD COLUMN...LAST */ dict_col_copy_type( dict_index_get_nth_col(index, field_no), @@ -1710,31 +1729,23 @@ trx_undo_update_rec_get_update( } } - /* In rare scenario, we could have skipped virtual column (as they - are dropped. We will regenerate a update vector and skip them */ - if (n_skip_field > 0) { - ulint n = 0; - ut_ad(n_skip_field <= n_fields); + /* We may have to skip dropped indexed virtual columns. + Also, we may have to trim the update vector of a metadata record + if dict_index_t::clear_instant_alter() was invoked on the table + later, and the number of fields no longer matches. */ - upd_t* new_update = upd_create( - n_fields + 2 - n_skip_field, heap); + if (n_skip_field) { + upd_field_t* d = upd_get_nth_field(update, 0); + const upd_field_t* const end = d + n_fields + 2; - for (i = 0; i < n_fields + 2; i++) { - upd_field = upd_get_nth_field(update, i); - - if (upd_field->field_no == REC_MAX_N_FIELDS) { - continue; + for (const upd_field_t* s = d; s != end; s++) { + if (s->field_no != REC_MAX_N_FIELDS) { + *d++ = *s; } - - upd_field_t* new_upd_field - = upd_get_nth_field(new_update, n); - *new_upd_field = *upd_field; - n++; } - ut_ad(n == n_fields + 2 - n_skip_field); - *upd = new_update; - } else { - *upd = update; + + ut_ad(d + n_skip_field == end); + update->n_fields = d - upd_get_nth_field(update, 0); } return(const_cast<byte*>(ptr)); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index f7f6dff4380..22b72a14304 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -24,12 +24,9 @@ Transaction rollback Created 3/26/1996 Heikki Tuuri *******************************************************/ -#include "my_config.h" -#include <my_service_manager.h> - -#include "ha_prototypes.h" #include "trx0roll.h" +#include <my_service_manager.h> #include <mysql/service_wsrep.h> #include "fsp0fsp.h" @@ -46,11 +43,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0sys.h" #include "trx0trx.h" #include "trx0undo.h" -#include "ha_prototypes.h" - -/** This many pages must be undone before a truncate is tried within -rollback */ -static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1; /** true if trx_rollback_all_recovered() thread is active */ bool trx_rollback_is_active; @@ -186,6 +178,11 @@ trx_rollback_to_savepoint( partial rollback requested, or NULL for complete rollback */ { +#ifdef WITH_WSREP + if (savept == NULL && wsrep_on(trx->mysql_thd)) { + wsrep_handle_SR_rollback(NULL, trx->mysql_thd); + } +#endif /* WITH_WSREP */ ut_ad(!trx_mutex_own(trx)); trx_start_if_not_started_xa(trx, true); @@ -454,12 +451,8 @@ trx_rollback_to_savepoint_for_mysql_low( trx_mark_sql_stat_end(trx); trx->op_info = ""; - #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif return(err); } @@ -878,175 +871,6 @@ DECLARE_THREAD(trx_rollback_all_recovered)(void*) OS_THREAD_DUMMY_RETURN; } -/** Try to truncate the undo logs. -@param[in,out] trx transaction */ -static -void -trx_roll_try_truncate(trx_t* trx) -{ - trx->pages_undone = 0; - - undo_no_t undo_no = trx->undo_no; - - if (trx_undo_t* undo = trx->rsegs.m_redo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_redo.rseg); - mutex_enter(&undo->rseg->mutex); - trx_undo_truncate_end(undo, undo_no, false); - mutex_exit(&undo->rseg->mutex); - } - - if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); - mutex_enter(&undo->rseg->mutex); - trx_undo_truncate_end(undo, undo_no, true); - mutex_exit(&undo->rseg->mutex); - } - -#ifdef WITH_WSREP_OUT - if (wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif /* WITH_WSREP */ -} - -/***********************************************************************//** -Pops the topmost undo log record in a single undo log and updates the info -about the topmost record in the undo log memory struct. -@return undo log record, the page s-latched */ -static -trx_undo_rec_t* -trx_roll_pop_top_rec( -/*=================*/ - trx_t* trx, /*!< in: transaction */ - trx_undo_t* undo, /*!< in: undo log */ - mtr_t* mtr) /*!< in: mtr */ -{ - page_t* undo_page = trx_undo_page_get_s_latched( - page_id_t(undo->rseg->space->id, undo->top_page_no), mtr); - - ulint offset = undo->top_offset; - - trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec( - undo_page + offset, undo->hdr_page_no, undo->hdr_offset, - true, mtr); - - if (prev_rec == NULL) { - undo->top_undo_no = IB_ID_MAX; - ut_ad(undo->empty()); - } else { - page_t* prev_rec_page = page_align(prev_rec); - - if (prev_rec_page != undo_page) { - - trx->pages_undone++; - } - - undo->top_page_no = page_get_page_no(prev_rec_page); - undo->top_offset = ulint(prev_rec - prev_rec_page); - undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); - ut_ad(!undo->empty()); - } - - return(undo_page + offset); -} - -/** Get the last undo log record of a transaction (for rollback). -@param[in,out] trx transaction -@param[out] roll_ptr DB_ROLL_PTR to the undo record -@param[in,out] heap memory heap for allocation -@return undo log record copied to heap -@retval NULL if none left or the roll_limit (savepoint) was reached */ -trx_undo_rec_t* -trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap) -{ - if (trx->pages_undone >= TRX_ROLL_TRUNC_THRESHOLD) { - trx_roll_try_truncate(trx); - } - - trx_undo_t* undo = NULL; - trx_undo_t* insert = trx->rsegs.m_redo.old_insert; - trx_undo_t* update = trx->rsegs.m_redo.undo; - trx_undo_t* temp = trx->rsegs.m_noredo.undo; - const undo_no_t limit = trx->roll_limit; - - ut_ad(!insert || !update || insert->empty() || update->empty() - || insert->top_undo_no != update->top_undo_no); - ut_ad(!insert || !temp || insert->empty() || temp->empty() - || insert->top_undo_no != temp->top_undo_no); - ut_ad(!update || !temp || update->empty() || temp->empty() - || update->top_undo_no != temp->top_undo_no); - - if (UNIV_LIKELY_NULL(insert) - && !insert->empty() && limit <= insert->top_undo_no) { - undo = insert; - } - - if (update && !update->empty() && update->top_undo_no >= limit) { - if (!undo) { - undo = update; - } else if (undo->top_undo_no < update->top_undo_no) { - undo = update; - } - } - - if (temp && !temp->empty() && temp->top_undo_no >= limit) { - if (!undo) { - undo = temp; - } else if (undo->top_undo_no < temp->top_undo_no) { - undo = temp; - } - } - - if (undo == NULL) { - trx_roll_try_truncate(trx); - /* Mark any ROLLBACK TO SAVEPOINT completed, so that - if the transaction object is committed and reused - later, we will default to a full ROLLBACK. */ - trx->roll_limit = 0; - trx->in_rollback = false; - return(NULL); - } - - ut_ad(!undo->empty()); - ut_ad(limit <= undo->top_undo_no); - - *roll_ptr = trx_undo_build_roll_ptr( - false, undo->rseg->id, undo->top_page_no, undo->top_offset); - - mtr_t mtr; - mtr.start(); - - trx_undo_rec_t* undo_rec = trx_roll_pop_top_rec(trx, undo, &mtr); - const undo_no_t undo_no = trx_undo_rec_get_undo_no(undo_rec); - switch (trx_undo_rec_get_type(undo_rec)) { - case TRX_UNDO_INSERT_METADATA: - /* This record type was introduced in MDEV-11369 - instant ADD COLUMN, which was implemented after - MDEV-12288 removed the insert_undo log. There is no - instant ADD COLUMN for temporary tables. Therefore, - this record can only be present in the main undo log. */ - ut_ad(undo == update); - /* fall through */ - case TRX_UNDO_RENAME_TABLE: - ut_ad(undo == insert || undo == update); - /* fall through */ - case TRX_UNDO_INSERT_REC: - ut_ad(undo == insert || undo == update || undo == temp); - *roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS; - break; - default: - ut_ad(undo == update || undo == temp); - break; - } - - trx->undo_no = undo_no; - - trx_undo_rec_t* undo_rec_copy = trx_undo_rec_copy(undo_rec, heap); - mtr.commit(); - - return(undo_rec_copy); -} - /****************************************************************//** Builds an undo 'query' graph for a transaction. The actual rollback is performed by executing this query graph like a query subprocedure call. diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index bfa49b88d1d..239df440c2b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -30,7 +30,6 @@ Created 3/26/1996 Heikki Tuuri #include "srv0srv.h" #include "trx0purge.h" #include "srv0mon.h" -#include "fsp0sysspace.h" #include <algorithm> @@ -44,6 +43,33 @@ static long long wsrep_seqno = -1; /** The latest known WSREP XID UUID */ static unsigned char wsrep_uuid[16]; +/** Write the WSREP XID information into rollback segment header. +@param[in,out] rseg_header rollback segment header +@param[in] xid WSREP XID +@param[in,out] mtr mini transaction */ +static void +trx_rseg_write_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + const XID* xid, + mtr_t* mtr) +{ + mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, + uint32_t(xid->formatID), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, + uint32_t(xid->gtrid_length), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, + uint32_t(xid->bqual_length), + MLOG_4BYTES, mtr); + + mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, + reinterpret_cast<const byte*>(xid->data), + XIDDATASIZE, mtr); +} + /** Update the WSREP XID information in rollback segment header. @param[in,out] rseg_header rollback segment header @param[in] xid WSREP XID @@ -61,29 +87,15 @@ trx_rseg_update_wsrep_checkpoint( long long xid_seqno = wsrep_xid_seqno(xid); const byte* xid_uuid = wsrep_xid_uuid(xid); - if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { + if (xid_seqno != -1 + && !memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { ut_ad(xid_seqno > wsrep_seqno); } else { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); } wsrep_seqno = xid_seqno; #endif /* UNIV_DEBUG */ - - mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, - uint32_t(xid->formatID), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, - uint32_t(xid->gtrid_length), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, - uint32_t(xid->bqual_length), - MLOG_4BYTES, mtr); - - mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, - reinterpret_cast<const byte*>(xid->data), - XIDDATASIZE, mtr); + trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr); } /** Update WSREP checkpoint XID in first rollback segment header @@ -98,6 +110,13 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) mtr_t mtr; mtr.start(); + const byte* xid_uuid = wsrep_xid_uuid(xid); + /* We must make check against wsrep_uuid here, the + trx_rseg_update_wsrep_checkpoint() writes over wsrep_uuid with + xid contents in debug mode and the memcmp() will never give nonzero + result. */ + const bool must_clear_rsegs = memcmp(wsrep_uuid, xid_uuid, + sizeof wsrep_uuid); const trx_rseg_t* rseg = trx_sys.rseg_array[0]; trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, @@ -108,10 +127,11 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); - const byte* xid_uuid = wsrep_xid_uuid(xid); - if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) { + if (must_clear_rsegs) { + XID null_xid; + memset(&null_xid, 0, sizeof null_xid); + null_xid.null(); memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); - /* Because the UUID part of the WSREP XID differed from current_xid_uuid, the WSREP group UUID was changed, and we must reset the XID in all rollback @@ -119,10 +139,12 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) { if (const trx_rseg_t* rseg = trx_sys.rseg_array[rseg_id]) { - trx_rseg_update_wsrep_checkpoint( + trx_rseg_write_wsrep_checkpoint( trx_rsegf_get(rseg->space, - rseg->page_no, &mtr), - xid, &mtr); + rseg->page_no, + &mtr), + &null_xid, + &mtr); } } } @@ -469,8 +491,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE) + 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header); - if (ulint len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { - trx_sys.history_add(int32(len)); + if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { + trx_sys.rseg_history_len += len; fil_addr_t node_addr = trx_purge_get_log_from_hist( flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr)); diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 003a2e70f93..6a19332a6b6 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -24,10 +24,8 @@ Transaction system Created 3/26/1996 Heikki Tuuri *******************************************************/ -#include "ha_prototypes.h" - -#include "mysqld.h" #include "trx0sys.h" +#include "mysqld.h" #include "sql_error.h" #include "fsp0fsp.h" @@ -42,9 +40,6 @@ Created 3/26/1996 Heikki Tuuri #include "log0log.h" #include "log0recv.h" #include "os0file.h" -#include "fsp0sysspace.h" - -#include <mysql/service_wsrep.h> /** The transaction system */ trx_sys_t trx_sys; @@ -217,7 +212,7 @@ trx_sys_t::create() m_initialised = true; mutex_create(LATCH_ID_TRX_SYS, &mutex); UT_LIST_INIT(trx_list, &trx_t::trx_list); - my_atomic_store32(&rseg_history_len, 0); + rseg_history_len= 0; rw_trx_hash.init(); } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 0177623f908..7be760c6221 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -24,8 +24,6 @@ The transaction Created 3/26/1996 Heikki Tuuri *******************************************************/ -#include "ha_prototypes.h" - #include "trx0trx.h" #ifdef WITH_WSREP @@ -41,7 +39,6 @@ Created 3/26/1996 Heikki Tuuri #include "que0que.h" #include "srv0mon.h" #include "srv0srv.h" -#include "fsp0sysspace.h" #include "srv0start.h" #include "trx0purge.h" #include "trx0rec.h" @@ -49,7 +46,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0rseg.h" #include "trx0undo.h" #include "trx0xa.h" -#include "ut0new.h" #include "ut0pool.h" #include "ut0vec.h" @@ -788,9 +784,7 @@ trx_lists_init_at_db_start() evenly distributed between 0 and innodb_undo_logs-1 @return persistent rollback segment @retval NULL if innodb_read_only */ -static -trx_rseg_t* -trx_assign_rseg_low() +static trx_rseg_t* trx_assign_rseg_low() { if (srv_read_only_mode) { ut_ad(srv_undo_logs == ULONG_UNDEFINED); @@ -841,8 +835,8 @@ trx_assign_rseg_low() ut_ad(rseg->is_persistent()); if (rseg->space != fil_system.sys_space) { - ut_ad(srv_undo_tablespaces > 1); - if (rseg->skip_allocation) { + if (rseg->skip_allocation + || !srv_undo_tablespaces) { continue; } } else if (trx_rseg_t* next @@ -1447,11 +1441,8 @@ trx_commit_in_memory( trx_mutex_enter(trx); trx->dict_operation = TRX_DICT_OP_NONE; - #ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif DBUG_LOG("trx", "Commit in memory: " << trx); @@ -1464,7 +1455,9 @@ trx_commit_in_memory( trx_mutex_exit(trx); ut_a(trx->error_state == DB_SUCCESS); - srv_wake_purge_thread_if_not_active(); + if (!srv_read_only_mode) { + srv_wake_purge_thread_if_not_active(); + } } /** Commit a transaction and a mini-transaction. @@ -2154,6 +2147,12 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, if (trx->is_recovered && trx_state_eq(trx, TRX_STATE_PREPARED) && arg->xid->eq(reinterpret_cast<XID*>(trx->xid))) { +#ifdef WITH_WSREP + /* The commit of a prepared recovered Galera + transaction needs a valid trx->xid for + invoking trx_sys_update_wsrep_checkpoint(). */ + if (!wsrep_is_wsrep_xid(trx->xid)) +#endif /* WITH_WSREP */ /* Invalidate the XID, so that subsequent calls will not find it. */ trx->xid->null(); arg->trx= trx; diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 0c31299486b..e084b0b67bf 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -24,8 +24,6 @@ Transaction undo log Created 3/26/1996 Heikki Tuuri *******************************************************/ -#include "ha_prototypes.h" - #include "trx0undo.h" #include "fsp0fsp.h" #include "mach0data.h" @@ -36,7 +34,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0purge.h" #include "trx0rec.h" #include "trx0rseg.h" -#include "trx0trx.h" /* How should the old versions in the history list be managed? ---------------------------------------------------------- @@ -891,54 +888,55 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr) @param[in,out] undo undo log @param[in] limit all undo logs after this limit will be discarded @param[in] is_temp whether this is temporary undo log */ -void -trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp) +void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp) { - ut_ad(mutex_own(&undo->rseg->mutex)); - ut_ad(is_temp == !undo->rseg->is_persistent()); + mtr_t mtr; + ut_ad(is_temp == !undo.rseg->is_persistent()); for (;;) { - mtr_t mtr; mtr.start(); if (is_temp) { mtr.set_log_mode(MTR_LOG_NO_REDO); } trx_undo_rec_t* trunc_here = NULL; + mutex_enter(&undo.rseg->mutex); page_t* undo_page = trx_undo_page_get( - page_id_t(undo->rseg->space->id, undo->last_page_no), + page_id_t(undo.rseg->space->id, undo.last_page_no), &mtr); trx_undo_rec_t* rec = trx_undo_page_get_last_rec( - undo_page, undo->hdr_page_no, undo->hdr_offset); + undo_page, undo.hdr_page_no, undo.hdr_offset); while (rec) { - if (trx_undo_rec_get_undo_no(rec) >= limit) { - /* Truncate at least this record off, maybe - more */ - trunc_here = rec; - } else { - goto function_exit; + if (trx_undo_rec_get_undo_no(rec) < limit) { + goto func_exit; } + /* Truncate at least this record off, maybe more */ + trunc_here = rec; rec = trx_undo_page_get_prev_rec(rec, - undo->hdr_page_no, - undo->hdr_offset); + undo.hdr_page_no, + undo.hdr_offset); } - if (undo->last_page_no == undo->hdr_page_no) { -function_exit: - if (trunc_here) { - mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE, - ulint(trunc_here - undo_page), - MLOG_2BYTES, &mtr); - } - + if (undo.last_page_no != undo.hdr_page_no) { + trx_undo_free_last_page(&undo, &mtr); + mutex_exit(&undo.rseg->mutex); mtr.commit(); - return; + continue; + } + +func_exit: + mutex_exit(&undo.rseg->mutex); + + if (trunc_here) { + mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR + + TRX_UNDO_PAGE_FREE, + ulint(trunc_here - undo_page), + MLOG_2BYTES, &mtr); } - trx_undo_free_last_page(undo, &mtr); mtr.commit(); + return; } } |