Commit 42f657cd authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-13267 At startup with crash recovery: mtr_t::commit_checkpoint(lsn_t,...

MDEV-13267 At startup with crash recovery: mtr_t::commit_checkpoint(lsn_t, bool): Assertion `!recv_no_log_write' failed

This is a bogus debug assertion failure that should be possible
starting with MariaDB 10.2.2 (which merged WL#7142 via MySQL 5.7.9).

While generating page-change redo log records is strictly out of the
question during tat certain parts of crash recovery, the
fil_names_clear() is only emitting informational MLOG_FILE_NAME
and MLOG_CHECKPOINT records to guarantee that if the server is killed
during or soon after the crash recovery, subsequent crash recovery
will be possible.

The metadata buffer that fil_names_clear() is flushing to the redo log
is being filled by recv_init_crash_recovery_spaces(), right before
starting to apply redo log, by invoking fil_names_dirty() on every
discovered tablespace for which there are changes to apply.

When it comes to Mariabackup (xtrabackup --prepare), it is strictly out
of the question to generate any redo log whatsoever, because that could
break the restore of incremental backups by causing LSN deviation.
So, the fil_names_dirty() call must be skipped when restoring backups.

recv_recovery_from_checkpoint_start(): Do not invoke fil_names_clear()
when restoring a backup.

mtr_t::commit_checkpoint(): Remove the failing assertion. The only
caller is fil_names_clear(), and it must be called by
recv_recovery_from_checkpoint_start() for normal server startup to be
crash-safe. The debug assertion in mtr_t::commit() will still
catch rogue redo log writes.
parent f20693c2
...@@ -3126,6 +3126,9 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3126,6 +3126,9 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
byte* buf; byte* buf;
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|| srv_operation == SRV_OPERATION_RESTORE);
/* Initialize red-black tree for fast insertions into the /* Initialize red-black tree for fast insertions into the
flush_list during recovery process. */ flush_list during recovery process. */
buf_flush_init_flush_rbt(); buf_flush_init_flush_rbt();
...@@ -3342,9 +3345,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3342,9 +3345,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
log_sys->last_checkpoint_lsn = checkpoint_lsn; log_sys->last_checkpoint_lsn = checkpoint_lsn;
if (!srv_read_only_mode) { if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL) {
/* Write a MLOG_CHECKPOINT marker as the first thing, /* Write a MLOG_CHECKPOINT marker as the first thing,
before generating any other redo log. */ before generating any other redo log. This ensures
that subsequent crash recovery will be possible even
if the server were killed soon after this. */
fil_names_clear(log_sys->last_checkpoint_lsn, true); fil_names_clear(log_sys->last_checkpoint_lsn, true);
} }
......
...@@ -599,9 +599,6 @@ mtr_t::commit_checkpoint( ...@@ -599,9 +599,6 @@ mtr_t::commit_checkpoint(
ut_d(m_impl.m_state = MTR_STATE_COMMITTING); ut_d(m_impl.m_state = MTR_STATE_COMMITTING);
ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1); ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1);
/* This is a dirty read, for debugging. */
ut_ad(!recv_no_log_write);
switch (m_impl.m_n_log_recs) { switch (m_impl.m_n_log_recs) {
case 0: case 0:
break; break;
......
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