summaryrefslogtreecommitdiff
path: root/storage/innobase/trx
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/trx')
-rw-r--r--storage/innobase/trx/trx0i_s.cc14
-rw-r--r--storage/innobase/trx/trx0purge.cc42
-rw-r--r--storage/innobase/trx/trx0rec.cc101
-rw-r--r--storage/innobase/trx/trx0roll.cc190
-rw-r--r--storage/innobase/trx/trx0rseg.cc74
-rw-r--r--storage/innobase/trx/trx0sys.cc9
-rw-r--r--storage/innobase/trx/trx0trx.cc27
-rw-r--r--storage/innobase/trx/trx0undo.cc56
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;
}
}