From 8abde0abe1d7d705bc42dad24de3391252ea888f Mon Sep 17 00:00:00 2001 From: Warrick <1016weicheng@gmail.com> Date: Wed, 27 May 2026 19:51:52 +0800 Subject: [PATCH] [fix] force to propagate first SELECT DBID --- src/server.c | 14 ++++++++++++ tests/gtid/gtid.tcl | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/server.c b/src/server.c index bc0e5f3e390..53c4a103b6e 100644 --- a/src/server.c +++ b/src/server.c @@ -3837,6 +3837,20 @@ static void propagatePendingCommands(void) { /* We use dbid=-1 to indicate we do not want to replicate SELECT. * It'll be inserted together with the next command (inside the MULTI) */ propagateNow(-1,&shared.multi,1,PROPAGATE_AOF|PROPAGATE_REPL); + + /* GTID-wrapped EXEC selects gtid_dbid_at_multi before executing the + * queued transaction. If the body starts in another DB, make the first + * DB-bound body command carry an explicit SELECT even if the replication + * stream was already on that DB. */ + if (server.gtid_dbid_at_multi != -1) { + for (j = 0; j < server.also_propagate.numops; j++) { + if (server.also_propagate.ops[j].dbid >= 0) { + if (server.also_propagate.ops[j].dbid != server.gtid_dbid_at_multi) + server.slaveseldb = -1; + break; + } + } + } } for (j = 0; j < server.also_propagate.numops; j++) { diff --git a/tests/gtid/gtid.tcl b/tests/gtid/gtid.tcl index c751a15c6e9..fdea50415f4 100644 --- a/tests/gtid/gtid.tcl +++ b/tests/gtid/gtid.tcl @@ -557,3 +557,56 @@ start_server {tags {"repl"} overrides} { } } + +start_server {tags {"repl"} overrides} { + set master [srv 0 client] + $master config set repl-diskless-sync-delay 1 + set master_host [srv 0 host] + set master_port [srv 0 port] + $master config set gtid-enabled yes + start_server {tags {"slave"}} { + set slave [srv 0 client] + $slave slaveof $master_host $master_port + wait_for_sync $slave + + test {GTID cross-DB transaction preserves body DB when stream already selected body DB} { + # Seed DB0 first so the replication stream may otherwise omit SELECT 0 + # before the transaction body. + $master select 0 + $master set gtid-cross-db-seed seed + wait_for_gtid_sync $master $slave + set repl [attach_to_replication_stream] + + $master select 9 + $master multi + $master select 0 + $master set gtid-cross-db-key:1 value-in-db0 + $master set gtid-cross-db-key:2 value-in-db0 + $master exec + + assert_replication_stream $repl { + {multi} + {select 0} + {set gtid-cross-db-key:1 value-in-db0} + {set gtid-cross-db-key:2 value-in-db0} + {gtid * 9 EXEC} + } + + wait_for_gtid_sync $master $slave + + $master select 0 + $slave select 0 + assert_equal value-in-db0 [$master get gtid-cross-db-key:1] + assert_equal value-in-db0 [$slave get gtid-cross-db-key:1] + assert_equal value-in-db0 [$master get gtid-cross-db-key:2] + assert_equal value-in-db0 [$slave get gtid-cross-db-key:2] + + $master select 9 + $slave select 9 + assert_equal {} [$master get gtid-cross-db-key:1] + assert_equal {} [$slave get gtid-cross-db-key:1] + assert_equal {} [$master get gtid-cross-db-key:2] + assert_equal {} [$slave get gtid-cross-db-key:2] + } + } +}