Skip to content

MDEV-38147 Mariadb error 1950 after SST - #5316

Open
ayurchen wants to merge 2 commits into
10.11from
MDEV-38147-mariadb-error-1950-after-sst
Open

MDEV-38147 Mariadb error 1950 after SST#5316
ayurchen wants to merge 2 commits into
10.11from
MDEV-38147-mariadb-error-1950-after-sst

Conversation

@ayurchen

@ayurchen ayurchen commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Pull request created in: https://jira.mariadb.org/browse/MDEV-38147

Investigation into MDEV-38147 revealed that with --galera-info option given during SST mariabackup rotates the binlog and ships it to joiner. The file is likely to contain wrong Gtid_list info and is used on joiner to initialize binlog.
Since that file is useless, don't rotate the binlog and ship the file, instead the joiner can generate its own correct Gtid_list.

MDEV-40179 - rollback orphaned prepared transactions.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@ayurchen
ayurchen requested a review from temeo July 1, 2026 13:02
@ayurchen ayurchen self-assigned this Jul 1, 2026
@ayurchen ayurchen added the Codership Codership Galera label Jul 1, 2026
@ayurchen ayurchen added this to the 10.11 milestone Jul 1, 2026
@ayurchen

ayurchen commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@mariadb-TeemuOllakka
mariadb-TeemuOllakka requested review from mariadb-TeemuOllakka and removed request for temeo July 2, 2026 09:34
@ayurchen
ayurchen force-pushed the MDEV-38147-mariadb-error-1950-after-sst branch 2 times, most recently from f5dec0e to 3363fc8 Compare July 5, 2026 21:46

@mariadb-TeemuOllakka mariadb-TeemuOllakka left a comment

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.

Initial comments for issues which caught my eye.

I could not yet fully understand the change in recovery logic, need to re-visit it later on.

Comment thread sql/handler.cc Outdated
Comment thread sql/handler.cc Outdated
Comment thread sql/handler.cc Outdated
@ayurchen
ayurchen force-pushed the MDEV-38147-mariadb-error-1950-after-sst branch 3 times, most recently from b4852ec to 8a98a1e Compare July 7, 2026 14:53

@mariadb-TeemuOllakka mariadb-TeemuOllakka left a comment

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.

@ayurchen Here's the comments for my second review pass.

The review is not complete, I haven't gone through mariabackup changes fully yet.

Comment thread sql/handler.cc
Comment thread scripts/wsrep_sst_mariabackup.sh
Comment thread scripts/wsrep_sst_mariabackup.sh Outdated
Comment thread sql/log.cc Outdated
Comment thread sql/wsrep_sst.cc Outdated
Comment thread sql/wsrep_sst.cc Outdated
Comment thread sql/handler.cc Outdated
Comment thread mysql-test/suite/galera_3nodes/t/MDEV-40179.inc
Comment thread mysql-test/suite/galera_3nodes/t/MDEV-38147.test
@mariadb-TeemuOllakka

Copy link
Copy Markdown
Contributor

The commit message for MDEV-38147 part says:

The cause is that the binary log copied from the donor carries a
Gtid_list whose position can be ahead of the storage-engine snapshot: BACKUP STAGE BLOCK_COMMIT blocks the engine commit (2PC step 3) but not the binary log write (step 2), so transactions can be present in the copied binlog that are not committed in the copied engine snapshot.

This is not entirely correct: Due to change introduced in 41b435f (MDEV-33211), the provider sql/backup.cc:backup_block_commit() does not pause the provider for BLOCK_COMMIT stage, therefore applying of wsrep transactions will not blocked at all on donor.

@ayurchen
ayurchen force-pushed the MDEV-38147-mariadb-error-1950-after-sst branch 2 times, most recently from a713b71 to 8674eec Compare July 29, 2026 08:36
ayurchen and others added 2 commits August 1, 2026 12:23
After a mariabackup SST the joiner could fail with

  ER_GTID_STRICT_OUT_OF_ORDER (error 1950)

while re-binlogging transactions received over IST.

The cause is that the binary log copied from the donor carries a
Gtid_list whose position can be ahead of the storage-engine snapshot
because getting snapshot and binlog are no mutually atomic, so transactions
can be present in the copied binlog that are not committed in the copied
engine snapshot.
After the SST the joiner reports the (committed) engine position to the
cluster, IST resends those transactions, and re-binlogging them under
gtid_strict_mode=ON collides with the ahead Gtid_list -> error 1950.
(MDEV-34483 made the engine snapshot stop short of the binlog, which is
what exposed this.)

The copied binary log carries no transactions the joiner needs - only a
Gtid_list - so instead of shipping and then having to truncate/reconcile
it, the joiner now starts a fresh binary log and seeds its GTID position
from the storage-engine checkpoint during recovery. That checkpoint is
the committed cluster position, i.e. exactly where IST resumes, so the
joiner's binary log stays in lockstep with the rest of the cluster and
no out-of-order GTID can occur.

This works for both wsrep_gtid_mode settings; only the binlog domain of
the cluster stream differs:

  - wsrep_gtid_mode=ON : wsrep_gtid_domain_id (cluster writes are
    re-tagged to it), which is the domain stored in the checkpoint;
  - wsrep_gtid_mode=OFF: gtid_domain_id (cluster writes keep the node's
    configured domain).

Async-replica positions (mysql.gtid_slave_pos) are part of the engine
snapshot and survive the SST unchanged, so a Galera node can still serve
as an async master or replica across the SST.

This commit:
 - sql/log.cc: adds wsrep_seed_binlog_gtid_state(), called from
   do_binlog_recovery() when the joiner has no binary log, seeding the
   binlog GTID state for the cluster domain to the SE checkpoint position.
 - scripts/wsrep_sst_mariabackup.sh: no longer moves the donor's binary
   log into place on the joiner.
 - extra/mariabackup: backward compatibility: keep shipping binlog file
   in SST but
   - on donor fix the race between rotation and shipping so that the file
     shipped is the one that had been rotated;
   - on joiner discard shipped binlog in favour of one generated by
     wsrep_seed_binlog_gtid_state().
 - sql/wsrep_sst.cc: logs the position actually adopted from storage
   (the authoritative post-SST position) rather than the script-reported
   one.
 - sql/handler.cc: downgrades the "Discovered discontinuity in recovered
   wsrep transaction XIDs" message in wsrep_order_and_check_continuity()
   from warning to debug level. With parallel appliers a snapshot
   routinely captures prepared XIDs that are not contiguous with the
   engine checkpoint, so this is normal during SST recovery and of no
   value in regular operation; the transactions past the checkpoint are
   re-delivered by the cluster (IST/SST) regardless.
 - Adds an MDEV-38147 MTR test reproducing the issue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
With log_bin=ON a transaction is committed via two-phase commit (the
binary log is the second participant), so it passes through the InnoDB
XA-prepare state. While a donor is held in BLOCK_COMMIT for a mariabackup
backup, its parallel appliers (wsrep_slave_threads > 1) leave one or more
such writesets prepared-but-not-yet-committed, and the snapshot captures
them. On a freshly SST'd joiner nothing resolves these prepared
transactions: binlog crash recovery does not run (the joiner has no in-use
binlog to recover from), and the wsrep continuity-based commit is inactive
because wsrep_emulate_bin_log is FALSE when log_bin is ON. The leftover
prepared transactions then abort startup with "Found <N> prepared
transactions!". Note this does not depend on the prepared set being
non-contiguous - even a contiguous run aborts, because nothing commits
or rolls it back.

Rollback these transactions in xarecover_handlerton(). If rollback fails
flag error to cause unireg_abort().
@ayurchen
ayurchen force-pushed the MDEV-38147-mariadb-error-1950-after-sst branch from 8674eec to 59ba47d Compare August 1, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Codership Codership Galera

Development

Successfully merging this pull request may close these issues.

2 participants