summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-09-05 09:54:47 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2022-09-05 09:54:47 +0300
commit244fdc435da364aea3b6e55835115cc04fe3297f (patch)
treebb8e6f1b1855d47f4f14d82ae3a606fbb3b22345
parent5cbc5dbbbe6c82ec6a4704073514ae274cdf40c1 (diff)
downloadmariadb-git-244fdc435da364aea3b6e55835115cc04fe3297f.tar.gz
MDEV-29438 Recovery or backup of instant ALTER TABLE is incorrect
This bug was found in MariaDB Server 10.6 thanks to the OPT_PAGE_CHECKSUM record that was implemented in commit 4179f93d28035ea2798cb1c16feeaaef87ab4775 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.
-rw-r--r--storage/innobase/log/log0recv.cc11
-rw-r--r--storage/innobase/page/page0cur.cc2
2 files changed, 8 insertions, 5 deletions
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index d9761fe9d85..f789e061d9b 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -187,7 +187,9 @@ public:
/** 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.
@@ -308,8 +310,7 @@ public:
{
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:
@@ -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:
@@ -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;
}
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index 31a780d8644..a1856586a10 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -1573,7 +1573,7 @@ inc_dir:
{
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;