MDEV-22351 InnoDB may recover wrong information after RESET MASTER

Ever since commit 947efe17ed8188ca4feef6deb0c2831a246b5c8f
InnoDB no longer writes binlog position in one place.
It will not at all be written to the TRX_SYS page, and
instead it will be written to the undo log header page that
changes the transaction state.

trx_rseg_mem_restore(): Recover the information from the latest
written page.
This commit is contained in:
Marko Mäkelä 2021-01-22 16:44:17 +02:00
parent 4e503aec7f
commit 0e10d7ea14
2 changed files with 25 additions and 29 deletions

View File

@ -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
@ -857,8 +857,10 @@ public:
#endif
/** Latest recovered binlog offset */
uint64_t recovered_binlog_offset;
/** Latest recovred binlog file name */
/** Latest recovered binlog file name */
char recovered_binlog_filename[TRX_SYS_MYSQL_LOG_NAME_LEN];
/** FIL_PAGE_LSN of the page with the latest recovered binlog metadata */
lsn_t recovered_binlog_lsn;
/**

View File

@ -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
@ -439,8 +439,14 @@ static
void
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
{
trx_rsegf_t* rseg_header = trx_rsegf_get_new(
rseg->space->id, rseg->page_no, mtr);
/* This is based on trx_rsegf_get_new().
We need to access buf_block_t. */
buf_block_t *block = buf_page_get(
page_id_t(rseg->space->id, rseg->page_no),
univ_page_size, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
const trx_rsegf_t* rseg_header = TRX_RSEG + block->frame;
if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) {
trx_id_t id = mach_read_from_8(rseg_header
@ -451,32 +457,20 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
}
if (rseg_header[TRX_RSEG_BINLOG_NAME]) {
const char* binlog_name = reinterpret_cast<const char*>
(rseg_header) + TRX_RSEG_BINLOG_NAME;
lsn_t lsn = std::max(block->page.newest_modification,
mach_read_from_8(FIL_PAGE_LSN
+ block->frame));
compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof
trx_sys.recovered_binlog_filename);
int cmp = *trx_sys.recovered_binlog_filename
? strncmp(binlog_name,
trx_sys.recovered_binlog_filename,
TRX_RSEG_BINLOG_NAME_LEN)
: 1;
if (cmp >= 0) {
uint64_t binlog_offset = mach_read_from_8(
rseg_header + TRX_RSEG_BINLOG_OFFSET);
if (cmp) {
memcpy(trx_sys.
recovered_binlog_filename,
binlog_name,
if (lsn > trx_sys.recovered_binlog_lsn) {
trx_sys.recovered_binlog_lsn = lsn;
trx_sys.recovered_binlog_offset
= mach_read_from_8(
rseg_header
+ TRX_RSEG_BINLOG_OFFSET);
memcpy(trx_sys.recovered_binlog_filename,
rseg_header + TRX_RSEG_BINLOG_NAME,
TRX_RSEG_BINLOG_NAME_LEN);
trx_sys.recovered_binlog_offset
= binlog_offset;
} else if (binlog_offset >
trx_sys.recovered_binlog_offset) {
trx_sys.recovered_binlog_offset
= binlog_offset;
}
}
#ifdef WITH_WSREP