MDEV-34389 Avoid log overwrite in early recovery

- InnoDB tries to write FILE_CHECKPOINT marker during
early recovery when log file size is insufficient.
While updating the log checkpoint at the end of the recovery,
InnoDB must already have written out all pending changes
to the persistent files. To complete the checkpoint, InnoDB
has to write some log records for the checkpoint and to
update the checkpoint header. If the server gets killed
before updating the checkpoint header then it would lead
the logfile to be unrecoverable.

- This patch avoids FILE_CHECKPOINT marker during early
recovery and narrows down the window of opportunity to
make the log file unrecoverable.
parent 6cecf61a
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("plugin 'InnoDB' registration as a STORAGE ENGINE failed.");
CREATE TABLE t1(f1 INT NOT NULL, f2 TEXT)ENGINE=InnoDB;
# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0
INSERT INTO t1 SELECT seq, repeat('a', 4000) FROM seq_1_to_1800;
# restart: --debug_dbug=+d,before_final_redo_apply --innodb_log_file_size=8M
# restart: --innodb_log_file_size=10M
DROP TABLE t1;
--source include/have_innodb.inc
--source include/have_sequence.inc
--source include/have_debug.inc
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("plugin 'InnoDB' registration as a STORAGE ENGINE failed.");
CREATE TABLE t1(f1 INT NOT NULL, f2 TEXT)ENGINE=InnoDB;
let $restart_parameters=--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0;
--source include/restart_mysqld.inc
INSERT INTO t1 SELECT seq, repeat('a', 4000) FROM seq_1_to_1800;
let $restart_parameters=--debug_dbug=+d,before_final_redo_apply --innodb_log_file_size=8M;
let $shutdown_timeout=0;
--source include/restart_mysqld.inc
let $restart_parameters=--innodb_log_file_size=10M;
let $shutdown_timeout=;
--source include/restart_mysqld.inc
DROP TABLE t1;
......@@ -3738,7 +3738,9 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
if (!srv_read_only_mode
&& srv_operation <= SRV_OPERATION_EXPORT_RESTORED
&& (~log_t::FORMAT_ENCRYPTED & log_sys.log.format)
== log_t::FORMAT_10_5) {
== log_t::FORMAT_10_5
&& recv_sys.recovered_lsn - log_sys.last_checkpoint_lsn
< log_sys.log_capacity) {
/* Write a FILE_CHECKPOINT marker as the first thing,
before generating any other redo log. This ensures
that subsequent crash recovery will be possible even
......@@ -3748,6 +3750,9 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
log_sys.next_checkpoint_no = ++checkpoint_no;
DBUG_EXECUTE_IF("before_final_redo_apply",
mysql_mutex_unlock(&log_sys.mutex);
return DB_ERROR;);
mutex_enter(&recv_sys.mutex);
recv_sys.apply_log_recs = true;
......
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