Commit 0a224edc authored by Vlad Lesin's avatar Vlad Lesin

MDEV-23711 make mariabackup innodb redo log read error message more clear

log_group_read_log_seg() returns error when:

1) Calculated log block number does not correspond to read log block
number. This can be caused by:
  a) Garbage or an incompletely written log block. We can exclude this
  case by checking log block checksum if it's enabled(see innodb-log-checksums,
  encrypted log block contains checksum always).
  b) The log block is overwritten. In this case checksum will be correct and
  read log block number will be greater then requested one.

2) When log block length is wrong. In this case recv_sys->found_corrupt_log
is set.

3) When redo log block checksum is wrong. In this case innodb code
writes messages to error log with the following prefix: "Invalid log
block checksum."

The fix processes all the cases above.
parent 69d536a2
...@@ -2773,6 +2773,7 @@ static bool xtrabackup_copy_logfile(bool last = false) ...@@ -2773,6 +2773,7 @@ static bool xtrabackup_copy_logfile(bool last = false)
ut_a(dst_log_file != NULL); ut_a(dst_log_file != NULL);
ut_ad(recv_sys != NULL); ut_ad(recv_sys != NULL);
bool overwritten_block;
lsn_t start_lsn; lsn_t start_lsn;
lsn_t end_lsn; lsn_t end_lsn;
...@@ -2799,6 +2800,12 @@ static bool xtrabackup_copy_logfile(bool last = false) ...@@ -2799,6 +2800,12 @@ static bool xtrabackup_copy_logfile(bool last = false)
} }
if (lsn == start_lsn) { if (lsn == start_lsn) {
overwritten_block= !recv_sys->found_corrupt_log
&& (innodb_log_checksums || log_sys->log.is_encrypted())
&& log_block_calc_checksum_crc32(log_sys->buf) ==
log_block_get_checksum(log_sys->buf)
&& log_block_get_hdr_no(log_sys->buf) >
log_block_convert_lsn_to_no(start_lsn);
start_lsn = 0; start_lsn = 0;
} else { } else {
mutex_enter(&recv_sys->mutex); mutex_enter(&recv_sys->mutex);
...@@ -2809,9 +2816,15 @@ static bool xtrabackup_copy_logfile(bool last = false) ...@@ -2809,9 +2816,15 @@ static bool xtrabackup_copy_logfile(bool last = false)
log_mutex_exit(); log_mutex_exit();
if (!start_lsn) { if (!start_lsn) {
die(recv_sys->found_corrupt_log const char *reason = recv_sys->found_corrupt_log
? "xtrabackup_copy_logfile() failed: corrupt log." ? "corrupt log."
: "xtrabackup_copy_logfile() failed."); : (overwritten_block
? "redo log block is overwritten, please increase redo log size with innodb_log_file_size parameter."
: ((innodb_log_checksums || log_sys->log.is_encrypted())
? "redo log block checksum does not match."
: "unknown reason as innodb_log_checksums is switched off and redo"
" log is not encrypted."));
die("xtrabackup_copy_logfile() failed: %s", reason);
return true; return true;
} }
} while (start_lsn == end_lsn); } while (start_lsn == end_lsn);
......
--loose-innodb-log-file-size=1048576 --loose-innodb-log-files-in-group=2
CREATE TABLE t(i INT) ENGINE=INNODB;
INSERT INTO t VALUES
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
# Generate enough data to overwrite innodb redo log
# on the next "INSERT INTO t SELECT * FROM t" execution.
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
# xtrabackup backup
FOUND 1 /failed: redo log block is overwritten/ in backup.log
FOUND 1 /failed: redo log block checksum does not match/ in backup.log
FOUND 1 /failed: unknown reason/ in backup.log
DROP TABLE t;
--source include/have_innodb.inc
--source include/have_debug_sync.inc
CREATE TABLE t(i INT) ENGINE=INNODB;
INSERT INTO t VALUES
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
--echo # Generate enough data to overwrite innodb redo log
--echo # on the next "INSERT INTO t SELECT * FROM t" execution.
--let $i = 0
while ($i < 9) {
INSERT INTO t SELECT * FROM t;
--inc $i
}
--echo # xtrabackup backup
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
--let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log
--let before_innodb_log_copy_thread_started=INSERT INTO test.t SELECT * FROM test.t
--disable_result_log
--error 1
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events > $backuplog
--enable_result_log
--let SEARCH_PATTERN=failed: redo log block is overwritten
--let SEARCH_FILE=$backuplog
--source include/search_pattern_in_file.inc
--remove_file $backuplog
--rmdir $targetdir
--let before_innodb_log_copy_thread_started=INSERT INTO test.t VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)
--disable_result_log
--error 1
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events,log_checksum_mismatch > $backuplog
--enable_result_log
--let SEARCH_PATTERN=failed: redo log block checksum does not match
--let SEARCH_FILE=$backuplog
--source include/search_pattern_in_file.inc
--remove_file $backuplog
--rmdir $targetdir
--let before_innodb_log_copy_thread_started=INSERT INTO test.t SELECT * FROM test.t LIMIT 50000
--disable_result_log
--error 1
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --innodb-log-checksums=0 --dbug=+d,mariabackup_events > $backuplog
--enable_result_log
--let SEARCH_PATTERN=failed: unknown reason
--let SEARCH_FILE=$backuplog
--source include/search_pattern_in_file.inc
--remove_file $backuplog
--rmdir $targetdir
--let before_innodb_log_copy_thread_started=
DROP TABLE t;
...@@ -965,6 +965,8 @@ log_group_read_log_seg( ...@@ -965,6 +965,8 @@ log_group_read_log_seg(
} }
}); });
DBUG_EXECUTE_IF("log_checksum_mismatch", { cksum = crc + 1; });
if (crc != cksum) { if (crc != cksum) {
ib::error() << "Invalid log block checksum." ib::error() << "Invalid log block checksum."
<< " block: " << block_number << " block: " << block_number
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment