PS-11530 [8.4] Members of one Group Replication group assign different GNOs to the same transaction - #6146
Open
kamil-holubicki wants to merge 1 commit into
Open
PS-11530 [8.4] Members of one Group Replication group assign different GNOs to the same transaction#6146kamil-holubicki wants to merge 1 commit into
kamil-holubicki wants to merge 1 commit into
Conversation
…t GNOs to the same transaction https://perconadev.atlassian.net/browse/PS-11530 Upstream bug: Bug#121063: https://bugs.mysql.com/bug.php?id=121063 Problem: Two members of the same group assign different GNOs to the same transaction, in multi-primary mode, when a member leaves and rejoins during a rolling restart under write load. The group splits into internally consistent sets that disagree on the GTID of the same transaction. It can surface on the `group_replication_applier` channel as Error_code 1032 or 1062, or stay silent with every member ONLINE and the disagreement present only in the binary logs. Cause: A reserved synode is only ours while we still hold the node index it was reserved under. `local_synode_allocator` stamps the member's current index into the synode, `synode.node = my_nodeno`. Still inside `reserve_synode_number`, the task yields in the `while (too_far(*msgno))` loop at `TIMED_TASK_WAIT`. During that yield, `site_install_action` reassigns `site->nodeno`. The reservation still carries the old index, so `proposer_task` brands and proposes into a slot that now belongs to another node. The header comment of `xcom_base.cc` states the rule: only node N may propose a value for synode {X N}. With two proposers on the same slot at `cnt=0`, `acceptor.promise` is never raised, since it is assigned in exactly one place, inside `handle_simple_prepare`, which is the phase 1 decision. Both proposals are accepted, both are learned, and `handle_learn` keeps whichever LEARN arrived first because of the `/* Avoid re-learn */` guard. Members that heard different values first deliver different payloads. Solution: Before proposing, verify the reservation still carries the member's own node index. If it does not, drop it through `retry_new` and take a new one. This is the same check `incr_msgno` already makes whenever it advances, with the comment `In case site and node number has changed`. The client transaction is not lost, it goes out in a slot that does belong to the member. Ported from upstream MySQL PR mysql/mysql-server#736 by Matias Sanchez. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
kamil-holubicki
requested review from
inikep,
lukin-oleksiy and
percona-ysorokin
September 4, 2026 10:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://perconadev.atlassian.net/browse/PS-11530
Upstream bug:
Bug#121063: https://bugs.mysql.com/bug.php?id=121063
Problem:
Two members of the same group assign different GNOs to the same transaction, in multi-primary mode, when a member leaves and rejoins during a rolling restart under write load. The group splits into internally consistent sets that disagree on the GTID of the same transaction. It can surface on the
group_replication_applierchannel as Error_code 1032 or 1062, or stay silent with every member ONLINE and the disagreement present only in the binary logs.Cause:
A reserved synode is only ours while we still hold the node index it was reserved under.
local_synode_allocatorstamps the member's current index into the synode,synode.node = my_nodeno. Still insidereserve_synode_number, the task yields in thewhile (too_far(*msgno))loop atTIMED_TASK_WAIT. During that yield,site_install_actionreassignssite->nodeno. The reservation still carries the old index, soproposer_taskbrands and proposes into a slot that now belongs to another node.The header comment of
xcom_base.ccstates the rule: only node N may propose a value for synode {X N}. With two proposers on the same slot atcnt=0,acceptor.promiseis never raised, since it is assigned in exactly one place, insidehandle_simple_prepare, which is the phase 1 decision. Both proposals are accepted, both are learned, andhandle_learnkeeps whichever LEARN arrived first because of the/* Avoid re-learn */guard. Members that heard different values first deliver different payloads.Solution:
Before proposing, verify the reservation still carries the member's own node index. If it does not, drop it through
retry_newand take a new one.This is the same check
incr_msgnoalready makes whenever it advances, with the commentIn case site and node number has changed. The client transaction is not lost, it goes out in a slot that does belong to the member.Ported from upstream MySQL PR
mysql/mysql-server#736
by Matias Sanchez.