Skip to content

MDEV-39006: Galera test failure on galera_3nodes.galera_garbd_backup#5018

Open
hemantdangi-gc wants to merge 1 commit into10.11from
10.11-MDEV-39006
Open

MDEV-39006: Galera test failure on galera_3nodes.galera_garbd_backup#5018
hemantdangi-gc wants to merge 1 commit into10.11from
10.11-MDEV-39006

Conversation

@hemantdangi-gc
Copy link
Copy Markdown
Contributor

Issue:
sst_disable_innodb_writes() promises no writes to persistent files between Galera donor state and SST release, and most engine subsystems already honour that (purge, dict_stats, encryption thread count, FTS optimizer in fts0opt.cc:2844). The page cleaner did not: buf_flush_page_cleaner()'s set_almost_idle: block ran buf_dblwr.flush_buffered_writes() and log_checkpoint() unconditionally on every wake-up. With LSN advanced past last_checkpoint_lsn (via any prior background mtr - the most common one being a wsrep applier writeset), log_checkpoint_low() then appended a fresh FILE_CHECKPOINT record to ib_logfile0 mid-SST, breaking
galera_3nodes.galera_garbd_backup with a --diff_files mismatch.

Solution:
Add a wsrep_sst_disable_writes gate around those two writes, mirroring the FTS pattern. In non-WSREP builds the flag is a constexpr false and the check compiles away. This closes the page-cleaner leak; other writers (wsrep apply paths, in-flight encryption rotation, ib_buffer_pool dump) are separate concerns and out of scope.

Also assert !recv_no_log_write after log_write_up_to() in log_checkpoint_low() so debug builds catch any future write path that slips through.

@hemantdangi-gc hemantdangi-gc force-pushed the 10.11-MDEV-39006 branch 2 times, most recently from 6824491 to 39d9068 Compare April 29, 2026 10:54
Comment on lines +1803 to +1826
DBUG_EXECUTE_IF("sst_force_lsn_advance",
{
/* Test-only: write a single FILE_MODIFY redo record so that
log_sys.get_lsn() advances past
last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT + 8*is_encrypted().
A subsequent buf_flush_page_cleaner() wake-up will then enter
log_checkpoint_low() past its early-return and, absent the
wsrep_sst_disable_writes gate in buf0flu.cc, fire the
recv_no_log_write tripwire (debug) or write a FILE_CHECKPOINT
record to ib_logfile0 (release). With the
UNIV_LIKELY(!wsrep_sst_disable_writes) check in place this
extra LSN gets checkpointed past once sst_enable_innodb_writes()
runs, so it does not survive past the SST window). */
skip_verify_checkpoint= true;
log_sys.latch.wr_lock();
mtr_t mtr;
mtr.start();
mtr.log_file_op(FILE_MODIFY, SRV_SPACE_ID_UPPER_BOUND - 1,
"./mdev39006_fake.ibd");
const lsn_t lsn_after_modify= mtr.commit_files();
log_sys.latch.wr_unlock();
log_write_up_to(lsn_after_modify ? lsn_after_modify : log_sys.get_lsn(),
true);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a compilation failure on many debug builders, because the low-level member function mtr_t::log_file_op() is not intended to be invoked directly, but only via other functions, such as mtr_t::name_write().

Is there really no other way to trigger this scenario? Could we write a dummy FILE_CHECKPOINT record instead, like innodb_log_file_size_update() does?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missed that as it run successfully on local.
Thanks for checking issue, I added a dummy function to resolve the issue as mtr_t::name_write() and innodb_log_file_size_update() needed some more changes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this piece of code can be removed?

Issue:
sst_disable_innodb_writes() promises no writes to persistent files
between Galera donor state and SST release, and most engine subsystems
already honour that (purge, dict_stats, encryption thread count, FTS
optimizer in fts0opt.cc:2844). The page cleaner did not:
buf_flush_page_cleaner()'s set_almost_idle: block ran
buf_dblwr.flush_buffered_writes() and log_checkpoint() unconditionally
on every wake-up. With LSN advanced past last_checkpoint_lsn (via any
prior background mtr - the most common one being a wsrep applier
writeset), log_checkpoint_low() then appended a fresh FILE_CHECKPOINT
record to ib_logfile0 mid-SST, breaking
galera_3nodes.galera_garbd_backup with a --diff_files mismatch.

Solution:
Add a wsrep_sst_disable_writes gate around those two writes, mirroring
the FTS pattern. In non-WSREP builds the flag is a constexpr false and
the check compiles away. This closes the page-cleaner leak; other
writers (wsrep apply paths, in-flight encryption rotation, ib_buffer_pool
dump) are separate concerns and out of scope.

Also assert !recv_no_log_write after log_write_up_to() in
log_checkpoint_low() so debug builds catch any future write path that
slips through.
Copy link
Copy Markdown
Contributor

@janlindstrom janlindstrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some improvement requests.

# (debug) or writes FILE_CHECKPOINT to ib_logfile0 (release).
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
--sleep 2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any other way to see that page cleaner had a change to run? This introduces a race, page cleaner thread might not get change to run during this 2 second wait leading to fact that this test is not testing intended behaviour.

# recv_no_log_write and resumes normal page-cleaner operation.
# (raise pct first so the lwm setter does not warn about lwm > pct.)
SET GLOBAL innodb_max_dirty_pages_pct=99;
SET GLOBAL debug_dbug = "+d,sst_enable_writes_now";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we clear dbug_dbug before setting max_dirty_pages* values?

Comment on lines +1803 to +1826
DBUG_EXECUTE_IF("sst_force_lsn_advance",
{
/* Test-only: write a single FILE_MODIFY redo record so that
log_sys.get_lsn() advances past
last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT + 8*is_encrypted().
A subsequent buf_flush_page_cleaner() wake-up will then enter
log_checkpoint_low() past its early-return and, absent the
wsrep_sst_disable_writes gate in buf0flu.cc, fire the
recv_no_log_write tripwire (debug) or write a FILE_CHECKPOINT
record to ib_logfile0 (release). With the
UNIV_LIKELY(!wsrep_sst_disable_writes) check in place this
extra LSN gets checkpointed past once sst_enable_innodb_writes()
runs, so it does not survive past the SST window). */
skip_verify_checkpoint= true;
log_sys.latch.wr_lock();
mtr_t mtr;
mtr.start();
mtr.log_file_op(FILE_MODIFY, SRV_SPACE_ID_UPPER_BOUND - 1,
"./mdev39006_fake.ibd");
const lsn_t lsn_after_modify= mtr.commit_files();
log_sys.latch.wr_unlock();
log_write_up_to(lsn_after_modify ? lsn_after_modify : log_sys.get_lsn(),
true);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this piece of code can be removed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants