Skip to content

Commit

Permalink
MDEV-29438 Recovery or backup of instant ALTER TABLE is incorrect
Browse files Browse the repository at this point in the history
This bug was found in MariaDB Server 10.6 thanks to the
OPT_PAGE_CHECKSUM record that was implemented
in commit 4179f93 for catching
this type of recovery failures.

page_cur_insert_rec_low(): If the previous record is the page infimum,
correctly limit the end of the record. We do not want to copy data from
the header of the page supremum. This omission caused the incorrect
recovery of DB_TRX_ID in an instant ALTER TABLE metadata record, because
part of the DB_TRX_ID was incorrectly copied from the n_owned of the
page supremum, which in recovery would be updated after the copying,
but in normal operation would already have been updated at the time the
common prefix was being determined.

log_phys_t::apply(): If a data page is found to be corrupted, do not
flag the log corrupted but instead return a new status APPLIED_CORRUPTED
so that the caller may discard all log for this page. We do not want
the recovery of unrelated pages to fail in recv_recover_page().

No test case is included, because the known test case would only work
in 10.6, and even after this fix, it would trigger another bug in
instant ALTER TABLE crash recovery.
  • Loading branch information
dr-m committed Sep 5, 2022
1 parent 5cbc5db commit 244fdc4
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 5 deletions.
11 changes: 7 additions & 4 deletions storage/innobase/log/log0recv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ struct log_phys_t : public log_rec_t
/** The page was modified, affecting the encryption parameters */
APPLIED_TO_ENCRYPTION,
/** The page was modified, affecting the tablespace header */
APPLIED_TO_FSP_HEADER
APPLIED_TO_FSP_HEADER,
/** The page was found to be corrupted */
APPLIED_CORRUPTED,
};

/** Apply log to a page frame.
Expand Down Expand Up @@ -308,8 +310,7 @@ struct log_phys_t : public log_rec_t
{
page_corrupted:
ib::error() << "Set innodb_force_recovery=1 to ignore corruption.";
recv_sys.found_corrupt_log= true;
return applied;
return APPLIED_CORRUPTED;
}
break;
case INSERT_HEAP_REDUNDANT:
Expand Down Expand Up @@ -2338,6 +2339,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
start_lsn = 0;
continue;
case log_phys_t::APPLIED_YES:
case log_phys_t::APPLIED_CORRUPTED:
goto set_start_lsn;
case log_phys_t::APPLIED_TO_FSP_HEADER:
case log_phys_t::APPLIED_TO_ENCRYPTION:
Expand Down Expand Up @@ -2391,7 +2393,8 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
}

set_start_lsn:
if (recv_sys.found_corrupt_log && !srv_force_recovery) {
if ((a == log_phys_t::APPLIED_CORRUPTED
|| recv_sys.found_corrupt_log) && !srv_force_recovery) {
break;
}

Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/page/page0cur.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@ page_cur_insert_rec_low(
{
const byte *r= rec;
const byte *c= cur->rec;
const byte *c_end= cur->rec + data_size;
const byte *c_end= c + (page_rec_is_infimum(c) ? 8 : data_size);
static_assert(REC_N_OLD_EXTRA_BYTES == REC_N_NEW_EXTRA_BYTES + 1, "");
if (c <= insert_buf && c_end > insert_buf)
c_end= insert_buf;
Expand Down

0 comments on commit 244fdc4

Please sign in to comment.