Disallow changing @@gtid_domain_id while a temporary table is open in
STATEMENT or MIXED binlog mode. Otherwise, a slave may try to replicate
events refering to the same temporary table in parallel, using domain-based
out-of-order parallel replication. This is not valid, temporary tables are
only available for use within a single thread at a time.

Use an existing error code that's somewhat close to the real issue
(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO), to not add a
new error code in a GA release. When this is merged to the next GA release,
we could optionally introduce a new and more precise error code for an
attempt to change the domain_id while temporary tables are open.

Signed-off-by: Kristian Nielsen <kniel...@knielsen-hq.org>
---
 .../suite/rpl/r/rpl_gtid_errorhandling.result | 36 ++++++++++++++++---
 .../suite/rpl/t/rpl_gtid_errorhandling.test   | 31 ++++++++++++++++
 sql/sys_vars.cc                               | 27 ++++++++++++--
 3 files changed, 87 insertions(+), 7 deletions(-)

diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result 
b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result
index 54156685806..5e26bdb0032 100644
--- a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result
+++ b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result
@@ -60,6 +60,34 @@ ROLLBACK;
 SELECT * FROM t1 ORDER BY a;
 a
 1
+SET @old_mode= @@SESSION.binlog_format;
+SET SESSION binlog_format= row;
+SET SESSION gtid_domain_id= 200;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION gtid_domain_id= 0;
+BEGIN;
+INSERT INTO t2 VALUES (200);
+INSERT INTO t1 SELECT * FROM t2;
+COMMIT;
+SET SESSION gtid_domain_id= 201;
+SET SESSION gtid_domain_id= 0;
+DELETE FROM t1 WHERE a=200;
+SET SESSION gtid_domain_id= 202;
+DROP TEMPORARY TABLE t2;
+SET SESSION binlog_format= mixed;
+SET SESSION gtid_domain_id= 0;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1);
+SET SESSION gtid_domain_id= 0;
+SET SESSION gtid_domain_id= 204;
+ERROR HY000: Cannot modify @@session.gtid_domain_id or @@session.gtid_seq_no 
inside a transaction
+SET SESSION binlog_format=statement;
+INSERT INTO t2 VALUES (2);
+SET SESSION gtid_domain_id= 205;
+ERROR HY000: Cannot modify @@session.gtid_domain_id or @@session.gtid_seq_no 
inside a transaction
+DROP TEMPORARY TABLE t2;
+SET SESSION gtid_domain_id= @old_domain;
+SET SESSION binlog_format= @old_mode;
 *** Test requesting an explicit GTID position that conflicts with newer GTIDs 
of our own in the binlog. ***
 connection slave;
 include/stop_slave.inc
@@ -83,16 +111,16 @@ ERROR 25000: You are not allowed to execute this command 
in a transaction
 ROLLBACK;
 SET GLOBAL gtid_strict_mode= 1;
 SET GLOBAL gtid_slave_pos = "0-1-1";
-ERROR HY000: Specified GTID 0-1-1 conflicts with the binary log which contains 
a more recent GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog 
position will override the new value of @@gtid_slave_pos
+ERROR HY000: Specified GTID 0-1-1 conflicts with the binary log which contains 
a more recent GTID 0-2-17. If MASTER_GTID_POS=CURRENT_POS is used, the binlog 
position will override the new value of @@gtid_slave_pos
 SET GLOBAL gtid_slave_pos = "";
-ERROR HY000: Specified value for @@gtid_slave_pos contains no value for 
replication domain 0. This conflicts with the binary log which contains GTID 
0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will 
override the new value of @@gtid_slave_pos
+ERROR HY000: Specified value for @@gtid_slave_pos contains no value for 
replication domain 0. This conflicts with the binary log which contains GTID 
0-2-17. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will 
override the new value of @@gtid_slave_pos
 SET GLOBAL gtid_strict_mode= 0;
 SET GLOBAL gtid_slave_pos = "0-1-1";
 Warnings:
-Warning        1947    Specified GTID 0-1-1 conflicts with the binary log 
which contains a more recent GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is 
used, the binlog position will override the new value of @@gtid_slave_pos
+Warning        1947    Specified GTID 0-1-1 conflicts with the binary log 
which contains a more recent GTID 0-2-17. If MASTER_GTID_POS=CURRENT_POS is 
used, the binlog position will override the new value of @@gtid_slave_pos
 SET GLOBAL gtid_slave_pos = "";
 Warnings:
-Warning        1948    Specified value for @@gtid_slave_pos contains no value 
for replication domain 0. This conflicts with the binary log which contains 
GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will 
override the new value of @@gtid_slave_pos
+Warning        1948    Specified value for @@gtid_slave_pos contains no value 
for replication domain 0. This conflicts with the binary log which contains 
GTID 0-2-17. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will 
override the new value of @@gtid_slave_pos
 RESET MASTER;
 SET GLOBAL gtid_slave_pos = "0-1-1";
 START SLAVE;
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test 
b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test
index eec7a275e03..e3ca6df1a6e 100644
--- a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test
+++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test
@@ -68,6 +68,37 @@ SELECT * FROM t1 ORDER BY a;
 ROLLBACK;
 SELECT * FROM t1 ORDER BY a;
 
+# MDEV-34049: Parallel access to temptable in different domain_id in parallel 
replication
+SET @old_mode= @@SESSION.binlog_format;
+SET SESSION binlog_format= row;
+SET SESSION gtid_domain_id= 200;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION gtid_domain_id= 0;
+BEGIN;
+INSERT INTO t2 VALUES (200);
+INSERT INTO t1 SELECT * FROM t2;
+COMMIT;
+SET SESSION gtid_domain_id= 201;
+SET SESSION gtid_domain_id= 0;
+DELETE FROM t1 WHERE a=200;
+SET SESSION gtid_domain_id= 202;
+DROP TEMPORARY TABLE t2;
+
+SET SESSION binlog_format= mixed;
+SET SESSION gtid_domain_id= 0;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1);
+SET SESSION gtid_domain_id= 0;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
+SET SESSION gtid_domain_id= 204;
+SET SESSION binlog_format=statement;
+INSERT INTO t2 VALUES (2);
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
+SET SESSION gtid_domain_id= 205;
+DROP TEMPORARY TABLE t2;
+SET SESSION gtid_domain_id= @old_domain;
+SET SESSION binlog_format= @old_mode;
+
 
 --echo *** Test requesting an explicit GTID position that conflicts with newer 
GTIDs of our own in the binlog. ***
 --connection slave
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 115bbdf499b..2ef1e404f85 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1808,12 +1808,33 @@ Sys_pseudo_thread_id(
 static bool
 check_gtid_domain_id(sys_var *self, THD *thd, set_var *var)
 {
-  if (var->type != OPT_GLOBAL &&
-      error_if_in_trans_or_substatement(thd,
+  if (var->type != OPT_GLOBAL)
+  {
+    if (error_if_in_trans_or_substatement(thd,
           ER_STORED_FUNCTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO,
           ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO))
     return true;
-
+    /*
+      All binlogged statements on a temporary table must be binlogged in the
+      same domain_id; it is not safe to run them in parallel in different
+      domains, temporary table must be exclusive to a single thread.
+      In row-based binlogging, temporary tables do not end up in the binlog,
+      so there is no such issue.
+
+      ToDo: When merging to next (non-GA) release, introduce a more specific
+      error that describes that the problem is changing gtid_domain_id with
+      open temporary tables in statement/mixed binlogging mode; it is not
+      really due to doing it inside a "transaction".
+    */
+    if (thd->has_thd_temporary_tables() &&
+        !thd->is_current_stmt_binlog_format_row() &&
+        var->save_result.ulonglong_value != thd->variables.gtid_domain_id)
+    {
+      my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO,
+               MYF(0));
+        return true;
+    }
+  }
   return false;
 }
 
-- 
2.39.5

_______________________________________________
commits mailing list -- commits@lists.mariadb.org
To unsubscribe send an email to commits-le...@lists.mariadb.org

Reply via email to