Skip to content

Commit 009956e

Browse files
Ingo Struewingdahlerlend
authored andcommitted
Bug#27571663 - MEB FAILS WHEN INNODB_LOG_FILE_SIZE IS DIFFERENT FOR INITIALIZE AND SERVER START
MEB failed do scan the redo log up to its logical end under circumstances. One such case was resizing of the log files. Resizing can happen by shutdown and start of the server with a new value for the log file size. The case was repeatable after two resizes with one megabyte of extended size each. The core of the problem lies in a new redo log format (version 3). In this format, the log header field LOG_HEADER_START_LSN does not always have the expected value. Instead the relation of LOG_CHECKPOINT_LSN and LOG_CHECKPOINT_OFFSET is significant for lsn to offset calculations. So far MEB relied on LOG_CHECKPOINT_LSN for lsn to offset calculations. Due to the unreliable values, MEB could start to read the log from a wrong offset. It could get a zero-filled block, on which it assumed end of log. This patch fixes the lsn to offset calculations. It gets rid of MEB's own calculation and calls an InnoDB function for this calculation instead. (log_files_real_offset_for_lsn() from log0write.cc, log0log.h, log0types.h). It does also fix the creation of the log files at restore time. The checkpoint offset field needs to be set appropriately. Unrelated changes: Fix variable types used for lsns and offsets. Lsns have lsn_t and offsets have utin64_t. Reorder functions around the calculation in header and implementation file to a consistent order. Reduce the number of functions with similar signature. Rename variables, so that the same name is used for the same "thing" throughout. Rename functions so, that a prefix of log_ is reserved for InnoDB functions, a prefix of meb_ is used for MEB functions, that are implemented inside InnoDB sources, a function name with get_ extracts information from memory structures, a function name with read_ invloves reading of information from a file. Move meb_read_checkpoint_info from log0recv.cc to Redo_log_adapter::get_checkpoint_info(). Fix a message about parsing redo log when redo log was not parsed. Fix tests, that used the message about parsing. Use the message about scanning instead. In tests, use $MYSQLTEST_VARDIR/tmp for logs. $MYSQLTEST_VARDIR/log is not preserved by MTR after a failing test. But the MEB logs are most valuable then. Add new test script meb.log_size_increase to repeat the reported bug when the patch is not applied. RB#19145
1 parent 47f80fc commit 009956e

File tree

5 files changed

+18
-58
lines changed

5 files changed

+18
-58
lines changed

storage/innobase/include/log0log.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ void log_buffer_x_lock_enter(log_t &log);
853853
/** Releases the log buffer x-lock.
854854
@param[in,out] log redo log */
855855
void log_buffer_x_lock_exit(log_t &log);
856+
#endif /* !UNIV_HOTBACKUP */
856857

857858
/** Calculates offset within log files, excluding headers of log files.
858859
@param[in] log redo log
@@ -872,6 +873,7 @@ for the provided lsn value.
872873
@param[in] lsn log sequence number
873874
@return real offset within the log files */
874875
uint64_t log_files_real_offset_for_lsn(const log_t &log, lsn_t lsn);
876+
#ifndef UNIV_HOTBACKUP
875877

876878
/** Changes size of the log buffer. This is a thread-safe version.
877879
It is used by SET GLOBAL innodb_log_buffer_size = X.

storage/innobase/include/log0recv.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,6 @@ extern volatile lsn_t backup_redo_log_flushed_lsn;
6565
/** TRUE when the redo log is being backed up */
6666
extern bool recv_is_making_a_backup;
6767

68-
/** Reads the checkpoint info needed in hot backup.
69-
@param[in] hdr buffer containing the log group header
70-
@param[out] lsn checkpoint lsn
71-
@param[out] offset checkpoint offset in the log group
72-
@param[out] cp_no checkpoint number
73-
@param[out] first_header_lsn lsn of of the start of the first log file
74-
@return true if success */
75-
bool meb_read_checkpoint_info(const byte *hdr, lsn_t *lsn, lsn_t *offset,
76-
lsn_t *cp_no, lsn_t *first_header_lsn)
77-
MY_ATTRIBUTE((warn_unused_result));
78-
7968
/** Scans the log segment and n_bytes_scanned is set to the length of valid
8069
log scanned.
8170
@param[in] buf buffer containing log data

storage/innobase/include/log0types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ struct alignas(INNOBASE_CACHE_LINE_SIZE) log_t {
326326
/** Up to this file offset in the log files, the write-ahead
327327
has been done or is not required (for any other reason). */
328328
uint64_t write_ahead_end_offset;
329+
#endif /* !UNIV_HOTBACKUP */
329330

330331
/** Some lsn value within the current log file. */
331332
lsn_t current_file_lsn;
@@ -347,6 +348,7 @@ struct alignas(INNOBASE_CACHE_LINE_SIZE) log_t {
347348
including headers of the log files. */
348349
uint64_t files_real_capacity;
349350

351+
#ifndef UNIV_HOTBACKUP
350352
/** Mutex which can be used to pause log writer thread. */
351353
ib_mutex_t writer_mutex;
352354

@@ -465,10 +467,12 @@ struct alignas(INNOBASE_CACHE_LINE_SIZE) log_t {
465467

466468
/** Lsn from which recovery has been started. */
467469
lsn_t recovered_lsn;
470+
#endif /* !UNIV_HOTBACKUP */
468471

469472
/** Number of log files. */
470473
uint32_t n_files;
471474

475+
#ifndef UNIV_HOTBACKUP
472476
/** Format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT. */
473477
uint32_t format;
474478

storage/innobase/log/log0recv.cc

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,48 +1299,6 @@ void recv_apply_hashed_log_recs(log_t &log, bool allow_ibuf) {
12991299
}
13001300

13011301
#else /* !UNIV_HOTBACKUP */
1302-
/** Reads the checkpoint info needed in hot backup.
1303-
@param[in] hdr buffer containing the log group header
1304-
@param[out] lsn checkpoint lsn
1305-
@param[out] offset checkpoint offset in the log group
1306-
@param[out] cp_no checkpoint number
1307-
@param[out] first_header_lsn lsn of of the start of the first log file
1308-
@return true if success */
1309-
bool meb_read_checkpoint_info(const byte *hdr, lsn_t *lsn, lsn_t *offset,
1310-
lsn_t *cp_no, lsn_t *first_header_lsn) {
1311-
ulint max_cp = 0;
1312-
uint64_t max_cp_no = 0;
1313-
const byte *cp_buf = hdr + LOG_CHECKPOINT_1;
1314-
1315-
if (recv_check_log_header_checksum(cp_buf)) {
1316-
max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
1317-
max_cp = LOG_CHECKPOINT_1;
1318-
}
1319-
1320-
cp_buf = hdr + LOG_CHECKPOINT_2;
1321-
1322-
if (recv_check_log_header_checksum(cp_buf)) {
1323-
if (mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO) > max_cp_no) {
1324-
max_cp = LOG_CHECKPOINT_2;
1325-
}
1326-
}
1327-
1328-
if (max_cp == 0) {
1329-
return (false);
1330-
}
1331-
1332-
cp_buf = hdr + max_cp;
1333-
1334-
*lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN);
1335-
*offset = mach_read_from_8(cp_buf + LOG_CHECKPOINT_OFFSET);
1336-
1337-
*cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
1338-
1339-
*first_header_lsn = mach_read_from_8(hdr + LOG_HEADER_START_LSN);
1340-
1341-
return (true);
1342-
}
1343-
13441302
/** Scans the log segment and n_bytes_scanned is set to the length of valid
13451303
log scanned.
13461304
@param[in] buf buffer containing log data

storage/innobase/log/log0write.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ this program; if not, write to the Free Software Foundation, Inc.,
4646
#include "buf0flu.h"
4747
#include "dict0boot.h"
4848
#include "dict0stats_bg.h"
49+
#endif /* !UNIV_HOTBACKUP */
4950
#include "fil0fil.h"
5051
#include "log0log.h"
52+
#ifndef UNIV_HOTBACKUP
5153
#include "log0recv.h"
5254
#include "mem0mem.h"
5355
#include "mysqld.h" /* server_uuid */
@@ -872,15 +874,19 @@ Wait_stats log_write_up_to(log_t &log, lsn_t end_lsn, bool flush_to_disk) {
872874
}
873875
}
874876

875-
/* @} */
877+
/* @} */
876878

877-
/**************************************************/ /**
879+
/**************************************************/ /**
878880
879-
@name Log writer thread
881+
@name Log writer thread
880882
881-
*******************************************************/
883+
*******************************************************/
882884

883-
/* @{ */
885+
/* @{ */
886+
887+
#else /* !UNIV_HOTBACKUP */
888+
#define log_writer_mutex_own(log) true
889+
#endif /* !UNIV_HOTBACKUP */
884890

885891
uint64_t log_files_size_offset(const log_t &log, uint64_t offset) {
886892
ut_ad(log_writer_mutex_own(log));
@@ -923,6 +929,7 @@ uint64_t log_files_real_offset_for_lsn(const log_t &log, lsn_t lsn) {
923929

924930
return (log_files_real_offset(log, size_offset));
925931
}
932+
#ifndef UNIV_HOTBACKUP
926933

927934
void log_files_update_offsets(log_t &log, lsn_t lsn) {
928935
ut_ad(log_writer_mutex_own(log));

0 commit comments

Comments
 (0)