Commit 6f623907 authored by Marko Mäkelä's avatar Marko Mäkelä

Backport MDEV-13430 recovery improvement to MariaDB 10.2

If the latest InnoDB redo log checkpoint was stored in the
first checkpoint slot and not the second one, InnoDB would
incorrectly set log_sys->log.lsn to the previous checkpoint.

It is possible that this logic error did not exist before
commit 86927cc7, which
removed traces of multiple InnoDB redo logs, to prepare for
MDEV-12548 (Mariabackup for MariaDB 10.2). In the worst case,
this error could mean that InnoDB unnecessarily fails to
recover from redo log when the last-but-one checkpoint was
overwritten, but the last checkpoint is intact.

recv_find_max_checkpoint(), recv_find_max_checkpoint_0():
Do not overwrite the fields of log_sys->log with the information
of an older checkpoint.

recv_find_max_checkpoint(): Do not return DB_SUCCESS on an error.

recv_recovery_from_checkpoint_start(): Return early if the log is
in a version-tagged format but not in the latest format. (In this case,
the log must be logically empty, and there is nothing to apply.)
parent 34eef269
...@@ -821,13 +821,6 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) ...@@ -821,13 +821,6 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field)
continue; continue;
} }
group->state = LOG_GROUP_OK;
group->lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = static_cast<ib_uint64_t>(
mach_read_from_4(buf + OFFSET_HIGH32)) << 32
| mach_read_from_4(buf + OFFSET_LOW32);
checkpoint_no = mach_read_from_8( checkpoint_no = mach_read_from_8(
buf + LOG_CHECKPOINT_NO); buf + LOG_CHECKPOINT_NO);
...@@ -838,12 +831,21 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) ...@@ -838,12 +831,21 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field)
DBUG_PRINT("ib_log", DBUG_PRINT("ib_log",
("checkpoint " UINT64PF " at " LSN_PF " found", ("checkpoint " UINT64PF " at " LSN_PF " found",
checkpoint_no, group->lsn)); checkpoint_no,
mach_read_from_8(buf + LOG_CHECKPOINT_LSN)));
if (checkpoint_no >= max_no) { if (checkpoint_no >= max_no) {
*max_group = group; *max_group = group;
*max_field = field; *max_field = field;
max_no = checkpoint_no; max_no = checkpoint_no;
group->state = LOG_GROUP_OK;
group->lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = static_cast<ib_uint64_t>(
mach_read_from_4(buf + OFFSET_HIGH32)) << 32
| mach_read_from_4(buf + OFFSET_LOW32);
} }
} }
...@@ -998,22 +1000,22 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -998,22 +1000,22 @@ recv_find_max_checkpoint(ulint* max_field)
continue; continue;
} }
group->state = LOG_GROUP_OK;
group->lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET);
checkpoint_no = mach_read_from_8( checkpoint_no = mach_read_from_8(
buf + LOG_CHECKPOINT_NO); buf + LOG_CHECKPOINT_NO);
DBUG_PRINT("ib_log", DBUG_PRINT("ib_log",
("checkpoint " UINT64PF " at " LSN_PF " found ", ("checkpoint " UINT64PF " at " LSN_PF " found",
checkpoint_no, group->lsn)); checkpoint_no, mach_read_from_8(
buf + LOG_CHECKPOINT_LSN)));
if (checkpoint_no >= max_no) { if (checkpoint_no >= max_no) {
*max_field = field; *max_field = field;
max_no = checkpoint_no; max_no = checkpoint_no;
group->state = LOG_GROUP_OK;
group->lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET);
} }
} }
...@@ -3148,7 +3150,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3148,7 +3150,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
err = recv_find_max_checkpoint(&max_cp_field); err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS
|| (log_sys->log.format != 0
&& (log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
!= LOG_HEADER_FORMAT_CURRENT)) {
log_mutex_exit(); log_mutex_exit();
return(err); return(err);
} }
...@@ -3178,8 +3184,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3178,8 +3184,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
case 0: case 0:
log_mutex_exit(); log_mutex_exit();
return(recv_log_format_0_recover(checkpoint_lsn)); return(recv_log_format_0_recover(checkpoint_lsn));
case LOG_HEADER_FORMAT_CURRENT: default:
case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED:
if (end_lsn == 0) { if (end_lsn == 0) {
break; break;
} }
...@@ -3187,8 +3192,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3187,8 +3192,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
contiguous_lsn = end_lsn; contiguous_lsn = end_lsn;
break; break;
} }
/* fall through */
default:
recv_sys->found_corrupt_log = true; recv_sys->found_corrupt_log = true;
log_mutex_exit(); log_mutex_exit();
return(DB_ERROR); return(DB_ERROR);
......
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