Skip to content

Commit

Permalink
Replace purge_iter_t with purge_sys_t::iterator
Browse files Browse the repository at this point in the history
Also, remove the field undo_rseg_space.
Apparently its purpose was to avoid problems with
temporary undo logs, which MySQL 5.7 unnecessarily adds to
the purge system. (Temporary undo log records are not purged.)
MariaDB 10.2 fixed this in MDEV-12289 or earlier.
  • Loading branch information
dr-m committed Feb 21, 2018
1 parent 28d844f commit d4187bd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 100 deletions.
53 changes: 18 additions & 35 deletions storage/innobase/include/trx0purge.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,36 +219,6 @@ struct TrxUndoRsegsIterator {
static const TrxUndoRsegs NullElement;
};

/** This is the purge pointer/iterator. We need both the undo no and the
transaction no up to which purge has parsed and applied the records. */
struct purge_iter_t {
purge_iter_t()
:
trx_no(),
undo_no(),
undo_rseg_space(ULINT_UNDEFINED)
{
// Do nothing
}

bool operator<=(const purge_iter_t& other) const
{
if (trx_no < other.trx_no) return true;
if (trx_no > other.trx_no) return false;
return undo_no <= other.undo_no;
}

trx_id_t trx_no; /*!< Purge has advanced past all
transactions whose number is less
than this */
undo_no_t undo_no; /*!< Purge has advanced past all records
whose undo number is less than this */
ulint undo_rseg_space;
/*!< Last undo record resided in this
space id. */
};


/* Namespace to hold all the related functions and variables need for truncate
of undo tablespace. */
namespace undo {
Expand Down Expand Up @@ -522,16 +492,29 @@ class purge_sys_t
to the task queue */
ulint n_completed; /*!< Count of total tasks completed */

/*------------------------------*/
/* The following two fields form the 'purge pointer' which advances
during a purge, and which is used in history list truncation */
/** Iterator to the undo log records of committed transactions */
struct iterator
{
bool operator<=(const iterator& other) const
{
if (trx_no < other.trx_no) return true;
if (trx_no > other.trx_no) return false;
return undo_no <= other.undo_no;
}

/** The 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;
};

/** The tail of the purge queue; the last parsed undo log of a
committed transaction. */
purge_iter_t tail;
iterator tail;
/** The head of the purge queue; any older undo logs of committed
transactions may be discarded (history list truncation). */
purge_iter_t head;
iterator head;
/*-----------------------------*/
bool next_stored; /*!< whether rseg holds the next record
to purge */
Expand Down
104 changes: 39 additions & 65 deletions storage/innobase/trx/trx0purge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)

/** Remove unnecessary history data from a rollback segment.
@param[in,out] rseg rollback segment
@param[in] limit truncate offset */
@param[in] limit truncate anything before this */
static
void
trx_purge_truncate_rseg_history(trx_rseg_t* rseg, const purge_iter_t* limit)
trx_purge_truncate_rseg_history(
trx_rseg_t& rseg,
const purge_sys_t::iterator& limit)
{
fil_addr_t hdr_addr;
fil_addr_t prev_hdr_addr;
Expand All @@ -469,48 +471,37 @@ trx_purge_truncate_rseg_history(trx_rseg_t* rseg, const purge_iter_t* limit)
mtr_t mtr;
trx_id_t undo_trx_no;

mtr_start(&mtr);
ut_ad(rseg->is_persistent());
mutex_enter(&(rseg->mutex));
mtr.start();
ut_ad(rseg.is_persistent());
mutex_enter(&rseg.mutex);

rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr);

hdr_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_hdr + TRX_RSEG_HISTORY, &mtr));
loop:
if (hdr_addr.page == FIL_NULL) {

mutex_exit(&(rseg->mutex));

mtr_commit(&mtr);

func_exit:
mutex_exit(&rseg.mutex);
mtr.commit();
return;
}

undo_page = trx_undo_page_get(page_id_t(rseg->space, hdr_addr.page),
undo_page = trx_undo_page_get(page_id_t(rseg.space, hdr_addr.page),
&mtr);

log_hdr = undo_page + hdr_addr.boffset;

undo_trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);

if (undo_trx_no >= limit->trx_no) {

/* limit space_id should match the rollback segment
space id to avoid freeing of the page belongs to
different rollback segment for the same trx_no. */
if (undo_trx_no == limit->trx_no
&& rseg->space == limit->undo_rseg_space) {

if (undo_trx_no >= limit.trx_no) {
if (undo_trx_no == limit.trx_no) {
trx_undo_truncate_start(
rseg, hdr_addr.page,
hdr_addr.boffset, limit->undo_no);
&rseg, hdr_addr.page,
hdr_addr.boffset, limit.undo_no);
}

mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);

return;
goto func_exit;
}

prev_hdr_addr = trx_purge_get_log_from_hist(
Expand All @@ -523,24 +514,24 @@ trx_purge_truncate_rseg_history(trx_rseg_t* rseg, const purge_iter_t* limit)

/* We can free the whole log segment */

mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
mutex_exit(&rseg.mutex);
mtr.commit();

/* calls the trx_purge_remove_log_hdr()
inside trx_purge_free_segment(). */
trx_purge_free_segment(rseg, hdr_addr);
trx_purge_free_segment(&rseg, hdr_addr);
} else {
/* Remove the log hdr from the rseg history. */
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);

mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
mutex_exit(&rseg.mutex);
mtr.commit();
}

mtr_start(&mtr);
mutex_enter(&(rseg->mutex));
mtr.start();
mutex_enter(&rseg.mutex);

rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr);

hdr_addr = prev_hdr_addr;

Expand Down Expand Up @@ -929,7 +920,7 @@ that resides in the tablespace are free.
static
void
trx_purge_initiate_truncate(
purge_iter_t* limit,
const purge_sys_t::iterator& limit,
undo::Truncate* undo_trunc)
{
/* Step-1: Early check to findout if any of the the UNDO tablespace
Expand Down Expand Up @@ -977,7 +968,7 @@ trx_purge_initiate_truncate(
undo != NULL && all_free;
undo = UT_LIST_GET_NEXT(undo_list, undo)) {

if (limit->trx_no < undo->trx_id) {
if (limit.trx_no < undo->trx_id) {
all_free = false;
} else {
cached_undo_size += undo->size;
Expand Down Expand Up @@ -1080,30 +1071,23 @@ trx_purge_initiate_truncate(
/**
Removes unnecessary history data from rollback segments. NOTE that when this
function is called, the caller must not have any latches on undo log pages!
@param[in] limit truncate limit
*/
static void trx_purge_truncate_history(purge_iter_t *limit)
static void trx_purge_truncate_history()
{
ut_ad(purge_sys->head <= purge_sys->tail);
purge_sys_t::iterator& head = purge_sys->head.trx_no
? purge_sys->head : purge_sys->tail;

/* We play safe and set the truncate limit at most to the purge view
low_limit number, though this is not necessary */

if (limit->trx_no >= purge_sys->view.low_limit_no()) {
limit->trx_no = purge_sys->view.low_limit_no();
limit->undo_no = 0;
limit->undo_rseg_space = ULINT_UNDEFINED;
if (head.trx_no >= purge_sys->view.low_limit_no()) {
/* This is sometimes necessary. TODO: find out why. */
head.trx_no = purge_sys->view.low_limit_no();
head.undo_no = 0;
}

ut_ad(limit->trx_no <= purge_sys->view.low_limit_no());

for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
trx_rseg_t* rseg = trx_sys.rseg_array[i];

if (rseg != NULL) {
ut_a(rseg->id == i);
trx_purge_truncate_rseg_history(rseg, limit);
if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
ut_ad(rseg->id == i);
trx_purge_truncate_rseg_history(*rseg, head);
}
}

Expand All @@ -1112,7 +1096,7 @@ static void trx_purge_truncate_history(purge_iter_t *limit)
try and truncate all the UNDO tablespaces. */
for (ulint i = srv_undo_tablespaces_active; i--; ) {
trx_purge_mark_undo_for_truncate(&purge_sys->undo_trunc);
trx_purge_initiate_truncate(limit, &purge_sys->undo_trunc);
trx_purge_initiate_truncate(head, &purge_sys->undo_trunc);
}
}

Expand All @@ -1139,7 +1123,6 @@ trx_purge_rseg_get_next_history_log(

purge_sys->tail.trx_no = rseg->last_trx_no + 1;
purge_sys->tail.undo_no = 0;
purge_sys->tail.undo_rseg_space = ULINT_UNDEFINED;
purge_sys->next_stored = false;

mtr_start(&mtr);
Expand Down Expand Up @@ -1216,7 +1199,6 @@ trx_purge_read_undo_rec()
ulint offset;
ulint page_no;
ib_uint64_t undo_no;
ulint undo_rseg_space;

purge_sys->hdr_offset = purge_sys->rseg->last_offset;
page_no = purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;
Expand All @@ -1230,25 +1212,21 @@ trx_purge_read_undo_rec()

offset = page_offset(undo_rec);
undo_no = trx_undo_rec_get_undo_no(undo_rec);
undo_rseg_space = purge_sys->rseg->space;
page_no = page_get_page_no(page_align(undo_rec));
} else {
offset = 0;
undo_no = 0;
undo_rseg_space = ULINT_UNDEFINED;
}

mtr.commit();
} else {
offset = 0;
undo_no = 0;
undo_rseg_space = ULINT_UNDEFINED;
}

purge_sys->offset = offset;
purge_sys->page_no = page_no;
purge_sys->tail.undo_no = undo_no;
purge_sys->tail.undo_rseg_space = undo_rseg_space;

purge_sys->next_stored = true;
}
Expand Down Expand Up @@ -1352,7 +1330,6 @@ trx_purge_get_next_rec(
purge_sys->offset = rec2 - page;
purge_sys->page_no = page_get_page_no(page);
purge_sys->tail.undo_no = trx_undo_rec_get_undo_no(rec2);
purge_sys->tail.undo_rseg_space = space;

if (undo_page != page) {
/* We advance to a new page of the undo log: */
Expand Down Expand Up @@ -1667,10 +1644,7 @@ trx_purge(
ut_a(purge_sys->n_submitted == purge_sys->n_completed);

if (truncate) {
trx_purge_truncate_history(
purge_sys->head.trx_no
? &purge_sys->head
: &purge_sys->tail);
trx_purge_truncate_history();
}

MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
Expand Down

0 comments on commit d4187bd

Please sign in to comment.