Skip to content
Permalink
Browse files
MDEV-15912: Remove traces of insert_undo
Let us simply refuse an upgrade from earlier versions if the
upgrade procedure was not followed. This simplifies the purge,
commit, and rollback of transactions.

Before upgrading to MariaDB 10.3 or later, a clean shutdown
of the server (with innodb_fast_shutdown=1 or 0) is necessary,
to ensure that any incomplete transactions are rolled back.
The undo log format was changed in MDEV-12288. There is only
one persistent undo log for each transaction.
  • Loading branch information
dr-m committed Jun 21, 2021
1 parent 241d30d commit e46f76c
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 380 deletions.
@@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, 2019, MariaDB Corporation.
Copyright (c) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -138,13 +138,10 @@ static ulong write_check;
struct innodb_page_type {
int n_undo_state_active;
int n_undo_state_cached;
int n_undo_state_to_free;
int n_undo_state_to_purge;
int n_undo_state_prepared;
int n_undo_state_other;
int n_undo_insert;
int n_undo_update;
int n_undo_other;
int n_undo;
int n_fil_page_index;
int n_fil_page_undo_log;
int n_fil_page_inode;
@@ -955,21 +952,7 @@ parse_page(
fprintf(file, "#::%llu\t\t|\t\tUndo log page\t\t\t|",
cur_page_num);
}
if (undo_page_type == TRX_UNDO_INSERT) {
page_type.n_undo_insert++;
if (page_type_dump) {
fprintf(file, "\t%s",
"Insert Undo log page");
}

} else if (undo_page_type == TRX_UNDO_UPDATE) {
page_type.n_undo_update++;
if (page_type_dump) {
fprintf(file, "\t%s",
"Update undo log page");
}
}

page_type.n_undo++;
undo_page_type = mach_read_from_2(page + TRX_UNDO_SEG_HDR +
TRX_UNDO_STATE);
switch (undo_page_type) {
@@ -989,14 +972,6 @@ parse_page(
}
break;

case TRX_UNDO_TO_FREE:
page_type.n_undo_state_to_free++;
if (page_type_dump) {
fprintf(file, ", %s", "Insert undo "
"segment that can be freed");
}
break;

case TRX_UNDO_TO_PURGE:
page_type.n_undo_state_to_purge++;
if (page_type_dump) {
@@ -1220,15 +1195,11 @@ print_summary(

fprintf(fil_out, "\n===============================================\n");
fprintf(fil_out, "Additional information:\n");
fprintf(fil_out, "Undo page type: %d insert, %d update, %d other\n",
page_type.n_undo_insert,
page_type.n_undo_update,
page_type.n_undo_other);
fprintf(fil_out, "Undo page state: %d active, %d cached, %d to_free, %d"
fprintf(fil_out, "Undo page type: %d\n", page_type.n_undo);
fprintf(fil_out, "Undo page state: %d active, %d cached, %d"
" to_purge, %d prepared, %d other\n",
page_type.n_undo_state_active,
page_type.n_undo_state_cached,
page_type.n_undo_state_to_free,
page_type.n_undo_state_to_purge,
page_type.n_undo_state_prepared,
page_type.n_undo_state_other);
@@ -109,8 +109,8 @@ File::tab#.ibd

===============================================
Additional information:
Undo page type: # insert, # update, # other
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other
Undo page type: #
Undo page state: # active, # cached, # to_purge, # prepared, # other
index_id #pages #leaf_pages #recs_per_page #bytes_per_page
# # # # #
# # # # #
@@ -144,8 +144,8 @@ File::tab#.ibd

===============================================
Additional information:
Undo page type: # insert, # update, # other
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other
Undo page type: #
Undo page state: # active, # cached, # to_purge, # prepared, # other
index_id #pages #leaf_pages #recs_per_page #bytes_per_page
# # # # #
# # # # #
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -78,20 +78,16 @@ class TrxUndoRsegs {
typedef trx_rsegs_t::iterator iterator;
typedef trx_rsegs_t::const_iterator const_iterator;

/** Default constructor */
TrxUndoRsegs() {}
TrxUndoRsegs() : trx_no(0), m_rsegs() {}
/** Constructor */
TrxUndoRsegs(trx_rseg_t& rseg)
: m_commit(rseg.last_commit), m_rsegs(1, &rseg) {}
: trx_no(rseg.last_trx_no()), m_rsegs(1, &rseg) {}
/** Constructor */
TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg)
: m_commit(trx_no << 1), m_rsegs(1, &rseg) {}

/** @return the transaction commit identifier */
trx_id_t trx_no() const { return m_commit >> 1; }
: trx_no(trx_no), m_rsegs(1, &rseg) {}

bool operator!=(const TrxUndoRsegs& other) const
{ return m_commit != other.m_commit; }
{ return trx_no != other.trx_no; }
bool empty() const { return m_rsegs.empty(); }
void erase(iterator& it) { m_rsegs.erase(it); }
iterator begin() { return(m_rsegs.begin()); }
@@ -105,14 +101,14 @@ class TrxUndoRsegs {
@return true if elem1 > elem2 else false.*/
bool operator()(const TrxUndoRsegs& lhs, const TrxUndoRsegs& rhs)
{
return(lhs.m_commit > rhs.m_commit);
return(lhs.trx_no > rhs.trx_no);
}

/** Copy of trx_rseg_t::last_trx_no() */
trx_id_t trx_no;
private:
/** Copy trx_rseg_t::last_commit */
trx_id_t m_commit;
/** Rollback segments of a transaction, scheduled for purge. */
trx_rsegs_t m_rsegs;
trx_rsegs_t m_rsegs;
};

typedef std::priority_queue<
@@ -370,17 +366,13 @@ class purge_sys_t
{
bool operator<=(const iterator& other) const
{
if (commit < other.commit) return true;
if (commit > other.commit) return false;
if (trx_no < other.trx_no) return true;
if (trx_no > other.trx_no) return false;
return undo_no <= other.undo_no;
}

/** @return the commit number of the transaction */
trx_id_t trx_no() const { return commit >> 1; }
void reset_trx_no(trx_id_t trx_no) { commit = trx_no << 1; }

/** 2 * trx_t::no + old_insert of the committed transaction */
trx_id_t commit;
/** trx_t::no of the committed transaction */
trx_id_t trx_no;
/** The record number within the committed transaction's undo
log, increasing, purged from from 0 onwards */
undo_no_t undo_no;
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -82,9 +82,8 @@ trx_rseg_header_create(
buf_block_t* sys_header,
mtr_t* mtr);

/** Initialize the rollback segments in memory at database startup. */
void
trx_rseg_array_init();
/** Initialize or recover the rollback segments at startup. */
dberr_t trx_rseg_array_init();

/** Free a rollback segment in memory. */
void
@@ -147,21 +146,13 @@ struct trx_rseg_t {
/** List of undo log segments cached for fast reuse */
UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached;

/** List of recovered old insert_undo logs of incomplete
transactions (to roll back or XA COMMIT & purge) */
UT_LIST_BASE_NODE_T(trx_undo_t) old_insert_list;

/*--------------------------------------------------------*/

/** Page number of the last not yet purged log header in the history
list; FIL_NULL if all list purged */
ulint last_page_no;

/** Byte offset of the last not yet purged log header */
ulint last_offset;
/** Last not yet purged undo log header; FIL_NULL if all purged */
uint32_t last_page_no;

/** trx_t::no * 2 + old_insert of the last not yet purged log */
trx_id_t last_commit;
/** trx_t::no | last_offset << 48 */
uint64_t last_commit_and_offset;

/** Whether the log segment needs purge */
bool needs_purge;
@@ -173,13 +164,17 @@ struct trx_rseg_t {
UNDO-tablespace marked for truncate. */
bool skip_allocation;

/** @return the commit ID of the last committed transaction */
trx_id_t last_trx_no() const { return last_commit >> 1; }

void set_last_trx_no(trx_id_t trx_no, bool is_update)
{
last_commit = trx_no << 1 | trx_id_t(is_update);
}
/** @return the commit ID of the last committed transaction */
trx_id_t last_trx_no() const
{ return last_commit_and_offset & ((1ULL << 48) - 1); }
/** @return header offset of the last committed transaction */
uint16_t last_offset() const
{ return static_cast<uint16_t>(last_commit_and_offset >> 48); }

void set_last_commit(ulint last_offset, trx_id_t trx_no)
{
last_commit_and_offset= static_cast<uint64_t>(last_offset) << 48 | trx_no;
}

/** @return whether the rollback segment is persistent */
bool is_persistent() const
@@ -79,7 +79,7 @@ void trx_free_at_shutdown(trx_t *trx);
void trx_disconnect_prepared(trx_t *trx);

/** Initialize (resurrect) transactions at startup. */
void trx_lists_init_at_db_start();
dberr_t trx_lists_init_at_db_start();

/*************************************************************//**
Starts the transaction if it is not yet started. */
@@ -698,10 +698,6 @@ struct trx_undo_ptr_t {
yet */
trx_undo_t* undo; /*!< pointer to the undo log, or
NULL if nothing logged yet */
trx_undo_t* old_insert; /*!< pointer to recovered
insert undo log, or NULL if no
INSERT transactions were
recovered from old-format undo logs */
};

/** An instance of temporary rollback segment. */
@@ -1055,13 +1051,6 @@ struct trx_t {
return(has_logged_persistent() || rsegs.m_noredo.undo);
}

/** @return whether any undo log has been generated or
recovered */
bool has_logged_or_recovered() const
{
return(has_logged() || rsegs.m_redo.old_insert);
}

/** @return rollback segment for modifying temporary tables */
trx_rseg_t* get_temp_rseg()
{
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -253,13 +253,11 @@ trx_undo_set_state_at_prepare(
bool rollback,
mtr_t* mtr);

/** Free an old insert or temporary undo log after commit or rollback.
/** Free temporary undo log after commit or rollback.
The information is not needed after a commit or rollback, therefore
the data can be discarded.
@param[in,out] undo undo log
@param[in] is_temp whether this is temporary undo log */
void
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp);
@param undo temporary undo log */
void trx_undo_commit_cleanup(trx_undo_t *undo);

/** At shutdown, frees the undo logs of a transaction. */
void
@@ -302,10 +300,11 @@ trx_undo_parse_page_header(
@param[in] id rollback segment slot
@param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */
ulint
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
trx_id_t& max_trx_id);
@return the undo log
@retval nullptr on error */
trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t &max_trx_id);

#endif /* !UNIV_INNOCHECKSUM */

@@ -319,7 +318,6 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
#define TRX_UNDO_ACTIVE 1 /* contains an undo log of an active
transaction */
#define TRX_UNDO_CACHED 2 /* cached for quick reuse */
#define TRX_UNDO_TO_FREE 3 /* insert undo segment can be freed */
#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be
reused: it can be freed in purge when
all undo data in it is removed */
@@ -383,7 +381,8 @@ struct trx_undo_t {
/** Transaction undo log page header offsets */
/* @{ */
#define TRX_UNDO_PAGE_TYPE 0 /*!< unused; 0 (before MariaDB 10.3.1:
TRX_UNDO_INSERT or TRX_UNDO_UPDATE) */
1=TRX_UNDO_INSERT or
2=TRX_UNDO_UPDATE) */
#define TRX_UNDO_PAGE_START 2 /*!< Byte offset where the undo log
records for the LATEST transaction
start on this page (remember that
@@ -4584,7 +4584,7 @@ lock_print_info_summary(
"Purge done for trx's n:o < " TRX_ID_FMT
" undo n:o < " TRX_ID_FMT " state: %s\n"
"History list length %u\n",
purge_sys.tail.trx_no(),
purge_sys.tail.trx_no,
purge_sys.tail.undo_no,
purge_sys.enabled()
? (purge_sys.running() ? "running"
@@ -1404,6 +1404,11 @@ dberr_t srv_start(bool create_new_db)
|| is_mariabackup_restore_or_export());


if (srv_force_recovery) {
ib::info() << "!!! innodb_force_recovery is set to "
<< srv_force_recovery << " !!!";
}

if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
srv_read_only_mode = true;
}
@@ -1922,7 +1927,11 @@ dberr_t srv_start(bool create_new_db)
All the remaining rollback segments will be created later,
after the double write buffer has been created. */
trx_sys_create_sys_pages();
trx_lists_init_at_db_start();
err = trx_lists_init_at_db_start();

if (err != DB_SUCCESS) {
return(srv_init_abort(err));
}

err = dict_create();

@@ -1986,7 +1995,10 @@ dberr_t srv_start(bool create_new_db)
case SRV_OPERATION_RESTORE:
/* This must precede
recv_apply_hashed_log_recs(true). */
trx_lists_init_at_db_start();
err = trx_lists_init_at_db_start();
if (err != DB_SUCCESS) {
return srv_init_abort(err);
}
break;
case SRV_OPERATION_RESTORE_DELTA:
case SRV_OPERATION_BACKUP:
@@ -2453,11 +2465,6 @@ dberr_t srv_start(bool create_new_db)
<< "; transaction id " << trx_sys.get_max_trx_id();
}

if (srv_force_recovery > 0) {
ib::info() << "!!! innodb_force_recovery is set to "
<< srv_force_recovery << " !!!";
}

if (srv_force_recovery == 0) {
/* In the insert buffer we may have even bigger tablespace
id's, because we may have dropped those tablespaces, but

0 comments on commit e46f76c

Please sign in to comment.