summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/mysqld--help.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_circular_semi_sync.result133
-rw-r--r--mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result30
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_semi_sync.test163
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test21
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result2
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log.h2
-rw-r--r--sql/rpl_gtid.cc9
-rw-r--r--sql/rpl_gtid.h3
-rw-r--r--sql/rpl_mi.cc3
-rw-r--r--sql/rpl_mi.h14
-rw-r--r--sql/slave.cc31
-rw-r--r--sql/sys_vars.cc5
14 files changed, 319 insertions, 107 deletions
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 2a158151528..bed2f6c86be 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -360,7 +360,9 @@ The following specify which files/extra groups are read (specified before remain
--gtid-strict-mode Enforce strict seq_no ordering of events in the binary
log. Slave stops with an error if it encounters an event
that would cause it to generate an out-of-order binlog if
- executed.
+ executed. When ON the same server-id semisync-replicated
+ transactions that duplicate exising ones in binlog are
+ ignored without error and slave interruption.
-?, --help Display this help and exit.
--histogram-size=# Number of bytes used for a histogram. If set to 0, no
histograms are created by ANALYZE.
diff --git a/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result b/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result
index dcced9833ca..5664b7913d2 100644
--- a/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result
+++ b/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result
@@ -1,12 +1,9 @@
include/master-slave.inc
[connection master]
-# Master server_1 and Slave server_2 initialiation ...
+# Master server_1 and Slave server_2 initialization ...
connection server_2;
include/stop_slave.inc
connection server_1;
-set @@sql_log_bin = off;
-call mtr.add_suppression("Slave: An attempt was made to binlog GTID 10-1-1 which would create an out-of-order sequence number with existing GTID");
-set @@sql_log_bin = on;
RESET MASTER;
set @@session.gtid_domain_id=10;
set @@global.rpl_semi_sync_master_enabled = 1;
@@ -22,31 +19,48 @@ 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-1. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos
CHANGE MASTER TO master_use_gtid= slave_pos;
include/start_slave.inc
-# ... server_1 -> server_2 is set up
+# server_1 -> server_2 semisync link is set up.
connection server_1;
-CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=Innodb;
-INSERT INTO t1 VALUES (1);
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT default 0) ENGINE=Innodb;
+INSERT INTO t1(a) VALUES (1);
+include/save_master_gtid.inc
connection server_2;
-# Circular configuration server_2 -> server_1 initialiation ...
+include/sync_with_master_gtid.inc
+# Circular configuration server_1 -> server_2 -> server_1 ...
connection server_1;
-# A. ... first when server_1 is in gtid strict mode...
set @@global.gtid_strict_mode = true;
set @@global.rpl_semi_sync_slave_enabled = 1;
CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=SLAVE_POS;
-# ... only for it to fail 'cos if its inconsistent (empty) slave's gtid state:
-SELECT @@global.gtid_slave_pos;
-@@global.gtid_slave_pos
-
-START SLAVE;
-include/wait_for_slave_sql_error.inc [errno=1950]
-# B. ... Resume on the circular setup with the server_id now in the non-strict mode ...
-set @@global.gtid_strict_mode = false;
include/start_slave.inc
-# ... to have succeeded.
+... is done.
+## A. no out-of-order gtid error for own transaction made round trip
+connection server_2;
+set @@global.gtid_strict_mode = true;
+set @@global.rpl_semi_sync_master_enabled = 1;
+INSERT INTO t1(a) VALUES (2);
+include/save_master_gtid.inc
+connection server_1;
+#
+# the successful sync is a required proof
+#
+include/sync_with_master_gtid.inc
+update t1 set b=b+1 where a=2;
+include/save_master_gtid.inc
connection server_2;
-INSERT INTO t1 VALUES (2);
+include/sync_with_master_gtid.inc
+# Post-execution state check on both servers synchronized with each other
connection server_1;
-INSERT INTO t1 VALUES (3);
+# ... the gtid states on server_1
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+Variable_name Value
+gtid_slave_pos 0-2-1,10-1-3,20-2-1
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+Variable_name Value
+gtid_binlog_pos 0-2-1,10-1-3,20-2-1
+SELECT * from t1;
+a b
+1 0
+2 1
connection server_2;
# The gtid states on server_2 must be equal to ...
SHOW VARIABLES LIKE 'gtid_binlog_pos';
@@ -55,22 +69,95 @@ gtid_binlog_pos 0-2-1,10-1-3,20-2-1
SHOW VARIABLES LIKE 'gtid_slave_pos';
Variable_name Value
gtid_slave_pos 0-2-1,10-1-3,20-2-1
+SELECT * from t1;
+a b
+1 0
+2 1
+## B. out-of-order gtid error for a "foreign" server-id transaction
+connection server_1;
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 10-2-4");
+set @@session.server_id=2;
+INSERT INTO t1(a) VALUES (3);
+set @@session.server_id=default;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (4);
+include/save_master_gtid.inc
+connection server_1;
+include/wait_for_slave_sql_error.inc [errno=1950]
+set sql_slave_skip_counter=1;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+connection server_2;
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 20-1-3");
+set @@session.server_id=1;
+INSERT INTO t1(a) VALUES (5);
+set @@session.server_id=default;
+include/save_master_gtid.inc
+connection server_1;
+include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (6);
+include/save_master_gtid.inc
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1950]
+set sql_slave_skip_counter=1;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+# Post-execution state check on both servers synchronized with each other
connection server_1;
# ... the gtid states on server_1
SHOW VARIABLES LIKE 'gtid_slave_pos';
Variable_name Value
-gtid_slave_pos 0-2-1,10-1-3,20-2-1
+gtid_slave_pos 0-2-1,10-1-5,20-1-3
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
-gtid_binlog_pos 0-2-1,10-1-3,20-2-1
+gtid_binlog_pos 0-2-1,10-1-5,20-1-3
+SELECT * from t1;
+a b
+1 0
+2 1
+3 0
+4 0
+5 0
+6 0
+connection server_2;
+include/sync_with_master_gtid.inc
+# The gtid states on server_2 must be equal to ...
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+Variable_name Value
+gtid_binlog_pos 0-2-1,10-1-5,20-1-3
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+Variable_name Value
+gtid_slave_pos 0-2-1,10-1-5,20-1-3
+SELECT * from t1;
+a b
+1 0
+2 1
+3 0
+4 0
+5 0
+6 0
+#
# Cleanup
+#
+connection server_1;
+DROP TABLE t1;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
connection server_1;
include/stop_slave.inc
set @@global.rpl_semi_sync_master_enabled = default;
set @@global.rpl_semi_sync_slave_enabled = default;
set @@global.rpl_semi_sync_master_wait_point=default;
-DROP TABLE t1;
+set @@global.gtid_ignore_duplicates = default;
+set @@global.gtid_strict_mode = default;
connection server_2;
+include/stop_slave.inc
+set @@global.gtid_ignore_duplicates = default;
set @@global.rpl_semi_sync_master_enabled = default;
set @@global.rpl_semi_sync_slave_enabled = default;
+set @@global.gtid_strict_mode = default;
+include/start_slave.inc
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result
index 1c15b10da96..8956eee2d2f 100644
--- a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result
@@ -70,6 +70,9 @@ INSERT INTO t1 VALUES (3, 'dummy3');
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-2-5
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-1-4,0-2-5
SHOW VARIABLES LIKE 'gtid_slave_pos';
Variable_name Value
gtid_slave_pos 0-1-4
@@ -84,12 +87,15 @@ gtid_slave_pos 0-2-5
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-2-5
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-1-4,0-2-5
connection server_2;
#
# Case:2
#
# CRASH the new master, and FAILOVER back to the original
-# INSERT INTO t1 VALUES (4, REPEAT("x", 4100))
+# SET STATEMENT server_id=1 FOR INSERT INTO t1 VALUES (4, REPEAT("x", 4100))
# INSERT INTO t1 VALUES (5, REPEAT("x", 4100))
# Rows 4 and 5 will be in master's binlog but not committed, they get
# replicated to slave and applied. On crash master should have 3 rows
@@ -98,14 +104,14 @@ connection server_2;
# Expected State post crash:
#=================================================================
# Master | Slave |
-# 0-2-6 (Not commited) | 0-2-6 (Received through semi-sync |
+# 0-1-6 (Not commited) | 0-1-6 (Received through semi-sync |
# | replication and applied) |
# 0-2-7 (Not commited) | 0-2-7 (Received through semi-sync |
# | replication and applied) |
#=================================================================
connect conn_client,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go";
-INSERT INTO t1 VALUES (4, REPEAT("x", 4100));
+SET STATEMENT server_id=1 FOR INSERT INTO t1 VALUES (4, REPEAT("x", 4100));
connect conn_client_2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
SET GLOBAL debug_dbug="d,Notify_binlog_EOF";
@@ -123,7 +129,7 @@ SELECT @@GLOBAL.gtid_current_pos;
# restart: --skip-slave-start=1 --rpl-semi-sync-slave-enabled=1
connection server_2;
include/assert.inc [Table t1 should have 3 rows.]
-FOUND 1 /truncated binlog file:.*slave.*000002/ in mysqld.2.err
+FOUND 1 /truncated binlog file:.*slave.*000002.* to remove transactions starting from GTID 0-1-6/ in mysqld.2.err
disconnect conn_client;
connection server_1;
set global rpl_semi_sync_master_enabled = 1;
@@ -134,7 +140,7 @@ set global rpl_semi_sync_slave_enabled = 1;
set @@global.gtid_slave_pos=@@global.gtid_binlog_pos;
include/start_slave.inc
#
-# Server_1 promoted as master will send 0-2-6 and 0-2-7 to slave Server_2
+# Server_1 promoted as master will send 0-1-6 and 0-2-7 to slave Server_2
#
connection server_1;
INSERT INTO t1 VALUES (6, 'dummy6');
@@ -142,6 +148,9 @@ INSERT INTO t1 VALUES (6, 'dummy6');
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-1-8
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-2-7,0-1-8
SHOW VARIABLES LIKE 'gtid_slave_pos';
Variable_name Value
gtid_slave_pos 0-2-7
@@ -156,6 +165,9 @@ gtid_slave_pos 0-1-8
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-1-8
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-2-7,0-1-8
include/diff_tables.inc [server_1:t1, server_2:t1]
connection server_1;
#
@@ -196,7 +208,7 @@ SELECT @@GLOBAL.gtid_current_pos;
# restart: --skip-slave-start=1 --rpl-semi-sync-slave-enabled=1
connection server_1;
include/assert.inc [Table t1 should have 6 rows.]
-NOT FOUND /truncated binlog file:.*master.*000003/ in mysqld.1.err
+FOUND 1 /truncated binlog file:.*master.*000002.* to remove transactions starting from GTID 0-1-9/ in mysqld.1.err
disconnect conn_client;
connection server_2;
set global rpl_semi_sync_master_enabled = 1;
@@ -216,6 +228,9 @@ include/save_master_gtid.inc
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-2-10
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-1-9,0-2-10
SHOW VARIABLES LIKE 'gtid_slave_pos';
Variable_name Value
gtid_slave_pos 0-1-9
@@ -231,6 +246,9 @@ gtid_slave_pos 0-2-10
SHOW VARIABLES LIKE 'gtid_binlog_pos';
Variable_name Value
gtid_binlog_pos 0-2-10
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+Variable_name Value
+gtid_binlog_state 0-1-9,0-2-10
#
# Cleanup
#
diff --git a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test
index 51fa5a242ea..267fa621945 100644
--- a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test
+++ b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test
@@ -1,115 +1,188 @@
# ==== References ====
#
# MDEV-27760 event may non stop replicate in circular semisync setup
-#
+# MDEV-28609 refine gtid-strict-mode to ignore same server-id gtid from the past
+# on semisync slave
--source include/have_innodb.inc
---source include/have_binlog_format_row.inc
+--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
# The following tests prove
-# A. out-of-order gtid error when the stict gtid mode semisync slave
-# receives the same server-id gtid event inconsistent
-# (rpl_semi_sync_fail_over tests the consistent case) with its state;
-# B. in the non-strict mode the same server-id events remains ignored
-# by default as usual.
-#
---echo # Master server_1 and Slave server_2 initialiation ...
+# A.
+# no out-of-order gtid error is done to the stict gtid mode semisync
+# slave receives the same server-id gtid event from the past (of its gtid
+# state). Such transaction is silently ignored similarly to
+# replicate_same_sever_id; and
+# B.
+# In contrast to A. the out-of-order gtid error is thrown when a "foreign"
+# server-id transaction makes its round-trip to the originator server.
+
+--echo # Master server_1 and Slave server_2 initialization ...
--connection server_2
--source include/stop_slave.inc
# Initial master
--connection server_1
-set @@sql_log_bin = off;
-call mtr.add_suppression("Slave: An attempt was made to binlog GTID 10-1-1 which would create an out-of-order sequence number with existing GTID");
-set @@sql_log_bin = on;
-
RESET MASTER;
-
set @@session.gtid_domain_id=10;
-
set @@global.rpl_semi_sync_master_enabled = 1;
set @@global.rpl_semi_sync_master_wait_point=AFTER_SYNC;
--connection server_2
RESET MASTER;
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
-
set @@session.gtid_domain_id=20;
-
set @@global.rpl_semi_sync_slave_enabled = 1;
--echo # a 1948 warning is expected
set @@global.gtid_slave_pos = "";
CHANGE MASTER TO master_use_gtid= slave_pos;
--source include/start_slave.inc
---echo # ... server_1 -> server_2 is set up
+--echo # server_1 -> server_2 semisync link is set up.
--connection server_1
-CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=Innodb;
-INSERT INTO t1 VALUES (1);
---save_master_pos
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT default 0) ENGINE=Innodb;
+INSERT INTO t1(a) VALUES (1);
+--source include/save_master_gtid.inc
--connection server_2
---sync_with_master
+--source include/sync_with_master_gtid.inc
---echo # Circular configuration server_2 -> server_1 initialiation ...
+--echo # Circular configuration server_1 -> server_2 -> server_1 ...
--connection server_1
---echo # A. ... first when server_1 is in gtid strict mode...
set @@global.gtid_strict_mode = true;
set @@global.rpl_semi_sync_slave_enabled = 1;
evalp CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=SLAVE_POS;
-
---echo # ... only for it to fail 'cos if its inconsistent (empty) slave's gtid state:
-SELECT @@global.gtid_slave_pos;
-START SLAVE;
-# ER_GTID_STRICT_OUT_OF_ORDER
---let $slave_sql_errno = 1950
---source include/wait_for_slave_sql_error.inc
-
---echo # B. ... Resume on the circular setup with the server_id now in the non-strict mode ...
-set @@global.gtid_strict_mode = false;
--source include/start_slave.inc
+--echo ... is done.
---echo # ... to have succeeded.
+--echo ## A. no out-of-order gtid error for own transaction made round trip
+# A0. server_1 has already originated the transaction
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+
+# A1. server_2 originates
--connection server_2
-INSERT INTO t1 VALUES (2);
---save_master_pos
+set @@global.gtid_strict_mode = true;
+set @@global.rpl_semi_sync_master_enabled = 1;
+INSERT INTO t1(a) VALUES (2);
+--source include/save_master_gtid.inc
--connection server_1
---sync_with_master
+--echo #
+--echo # the successful sync is a required proof
+--echo #
+--source include/sync_with_master_gtid.inc
+# A2. server_1 is originating now
+update t1 set b=b+1 where a=2;
+--source include/save_master_gtid.inc
-INSERT INTO t1 VALUES (3);
---save_master_pos
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--echo # Post-execution state check on both servers synchronized with each other
+--connection server_1
+--echo # ... the gtid states on server_1
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SELECT * from t1;
--connection server_2
---sync_with_master
--echo # The gtid states on server_2 must be equal to ...
--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
--source include/wait_condition.inc
SHOW VARIABLES LIKE 'gtid_binlog_pos';
SHOW VARIABLES LIKE 'gtid_slave_pos';
+SELECT * from t1;
+
+--echo ## B. out-of-order gtid error for a "foreign" server-id transaction
+# B1. circulation starts from server_1
+
+--connection server_1
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 10-2-4");
+set @@session.server_id=2;
+INSERT INTO t1(a) VALUES (3);
+set @@session.server_id=default;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_1
+--let $slave_sql_errno = 1950
+--source include/wait_for_slave_sql_error.inc
+set sql_slave_skip_counter=1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+# B2. circulation starts from server_2
+--connection server_2
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 20-1-3");
+set @@session.server_id=1;
+INSERT INTO t1(a) VALUES (5);
+set @@session.server_id=default;
+--source include/save_master_gtid.inc
--connection server_1
+--source include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (6);
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+--let $slave_sql_errno = 1950
+--source include/wait_for_slave_sql_error.inc
+set sql_slave_skip_counter=1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--echo # Post-execution state check on both servers synchronized with each other
+--connection server_1
--echo # ... the gtid states on server_1
--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
--source include/wait_condition.inc
SHOW VARIABLES LIKE 'gtid_slave_pos';
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SELECT * from t1;
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--echo # The gtid states on server_2 must be equal to ...
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SELECT * from t1;
+--echo #
--echo # Cleanup
+--echo #
+--connection server_1
+DROP TABLE t1;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
--connection server_1
--source include/stop_slave.inc
set @@global.rpl_semi_sync_master_enabled = default;
set @@global.rpl_semi_sync_slave_enabled = default;
set @@global.rpl_semi_sync_master_wait_point=default;
-
-DROP TABLE t1;
---save_master_pos
+set @@global.gtid_ignore_duplicates = default;
+set @@global.gtid_strict_mode = default;
--connection server_2
---sync_with_master
+--source include/stop_slave.inc
+set @@global.gtid_ignore_duplicates = default;
set @@global.rpl_semi_sync_master_enabled = default;
set @@global.rpl_semi_sync_slave_enabled = default;
+set @@global.gtid_strict_mode = default;
+--source include/start_slave.inc
--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test
index 0505e88d758..6a691ae04f6 100644
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test
@@ -1,6 +1,7 @@
# ==== References ====
#
-# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
+# MDEV-21117 recovery for --rpl-semi-sync-slave-enabled server
+# MDEV-27760 event may non stop replicate in circular semisync setup
#
--source include/have_innodb.inc
@@ -72,6 +73,7 @@ INSERT INTO t1 VALUES (1, 'dummy1');
--save_master_pos
--echo # The gtid state on current master must be equal to ...
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
SHOW VARIABLES LIKE 'gtid_slave_pos';
--connection server_1
@@ -80,6 +82,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos';
--echo # ... the gtid states on the slave:
SHOW VARIABLES LIKE 'gtid_slave_pos';
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
--connection server_2
--let $case = 2
@@ -89,7 +92,9 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
--echo # CRASH the new master, and FAILOVER back to the original
# value 0 for the reverse server id 2 -> 1 failover
--let $failover_to_slave=0
---let $query_to_crash = INSERT INTO t1 VALUES (4, REPEAT("x", 4100))
+# Additionally through "foreign" server_id verify MDEV-27760's acceptance
+# policy on the recient (to be promoted into master) server.
+--let $query_to_crash = SET STATEMENT server_id=1 FOR INSERT INTO t1 VALUES (4, REPEAT("x", 4100))
--let $query2_to_crash= INSERT INTO t1 VALUES (5, REPEAT("x", 4100))
--echo # $query_to_crash
--echo # $query2_to_crash
@@ -100,18 +105,18 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
--echo # Expected State post crash:
--echo #=================================================================
--echo # Master | Slave |
---echo # 0-2-6 (Not commited) | 0-2-6 (Received through semi-sync |
+--echo # 0-1-6 (Not commited) | 0-1-6 (Received through semi-sync |
--echo # | replication and applied) |
--echo # 0-2-7 (Not commited) | 0-2-7 (Received through semi-sync |
--echo # | replication and applied) |
--echo #=================================================================
---let $log_search_pattern=truncated binlog file:.*slave.*000002
+--let $log_search_pattern=truncated binlog file:.*slave.*000002.* to remove transactions starting from GTID 0-1-6
--let $expected_rows_on_master= 3
--let $expected_rows_on_slave= 5
--source rpl_semi_sync_crash.inc
--echo #
---echo # Server_1 promoted as master will send 0-2-6 and 0-2-7 to slave Server_2
+--echo # Server_1 promoted as master will send 0-1-6 and 0-2-7 to slave Server_2
--echo #
--connection server_1
--let $rows_so_far=6
@@ -119,6 +124,7 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
--save_master_pos
--echo # The gtid state on current master must be equal to ...
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
SHOW VARIABLES LIKE 'gtid_slave_pos';
--connection server_2
@@ -127,6 +133,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos';
--echo # ... the gtid states on the slave:
SHOW VARIABLES LIKE 'gtid_slave_pos';
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
--let $diff_tables=server_1:t1, server_2:t1
--source include/diff_tables.inc
@@ -154,7 +161,7 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
--echo # 0-1-10 (Not commited - | |
--echo # never sent to slave) | |
--echo #=================================================================
---let $log_search_pattern=truncated binlog file:.*master.*000003
+--let $log_search_pattern=truncated binlog file:.*master.*000002.* to remove transactions starting from GTID 0-1-9
--let $expected_rows_on_master= 6
--let $expected_rows_on_slave= 7
--source rpl_semi_sync_crash.inc
@@ -168,6 +175,7 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
--source include/save_master_gtid.inc
--echo # The gtid state on current master must be equal to ...
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
SHOW VARIABLES LIKE 'gtid_slave_pos';
--connection server_1
@@ -176,6 +184,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos';
--echo # ... the gtid states on the slave:
SHOW VARIABLES LIKE 'gtid_slave_pos';
SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
--echo #
--echo # Cleanup
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 7b811a011ff..a661a806ff6 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -1185,7 +1185,7 @@ COMMAND_LINE_ARGUMENT NULL
VARIABLE_NAME GTID_STRICT_MODE
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
-VARIABLE_COMMENT Enforce strict seq_no ordering of events in the binary log. Slave stops with an error if it encounters an event that would cause it to generate an out-of-order binlog if executed.
+VARIABLE_COMMENT Enforce strict seq_no ordering of events in the binary log. Slave stops with an error if it encounters an event that would cause it to generate an out-of-order binlog if executed. When ON the same server-id semisync-replicated transactions that duplicate exising ones in binlog are ignored without error and slave interruption.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
diff --git a/sql/log.cc b/sql/log.cc
index 81fe4b1e97d..11dd979715c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -6463,11 +6463,13 @@ MYSQL_BIN_LOG::bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no)
bool
MYSQL_BIN_LOG::check_strict_gtid_sequence(uint32 domain_id,
uint32 server_id_arg,
- uint64 seq_no)
+ uint64 seq_no,
+ bool no_error)
{
return rpl_global_gtid_binlog_state.check_strict_sequence(domain_id,
server_id_arg,
- seq_no);
+ seq_no,
+ no_error);
}
diff --git a/sql/log.h b/sql/log.h
index 516fb36adb9..aec48263d84 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -920,7 +920,7 @@ public:
bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid);
int bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no);
bool check_strict_gtid_sequence(uint32 domain_id, uint32 server_id,
- uint64 seq_no);
+ uint64 seq_no, bool no_error= false);
/**
* used when opening new file, and binlog_end_pos moves backwards
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index eecc6040051..fce5f260639 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -1734,7 +1734,7 @@ rpl_binlog_state::alloc_element_nolock(const rpl_gtid *gtid)
*/
bool
rpl_binlog_state::check_strict_sequence(uint32 domain_id, uint32 server_id,
- uint64 seq_no)
+ uint64 seq_no, bool no_error)
{
element *elem;
bool res= 0;
@@ -1744,9 +1744,10 @@ rpl_binlog_state::check_strict_sequence(uint32 domain_id, uint32 server_id,
(const uchar *)(&domain_id), 0)) &&
elem->last_gtid && elem->last_gtid->seq_no >= seq_no)
{
- my_error(ER_GTID_STRICT_OUT_OF_ORDER, MYF(0), domain_id, server_id, seq_no,
- elem->last_gtid->domain_id, elem->last_gtid->server_id,
- elem->last_gtid->seq_no);
+ if (!no_error)
+ my_error(ER_GTID_STRICT_OUT_OF_ORDER, MYF(0), domain_id, server_id, seq_no,
+ elem->last_gtid->domain_id, elem->last_gtid->server_id,
+ elem->last_gtid->seq_no);
res= 1;
}
mysql_mutex_unlock(&LOCK_binlog_state);
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index 531d746763b..c8decff8fe8 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -317,7 +317,8 @@ struct rpl_binlog_state
int update_with_next_gtid(uint32 domain_id, uint32 server_id,
rpl_gtid *gtid);
int alloc_element_nolock(const rpl_gtid *gtid);
- bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no);
+ bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no,
+ bool no_error= false);
int bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no);
int write_to_iocache(IO_CACHE *dest);
int read_from_iocache(IO_CACHE *src);
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index cdd56976549..8322bcd3042 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -43,7 +43,8 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg,
gtid_reconnect_event_skip_count(0), gtid_event_seen(false),
in_start_all_slaves(0), in_stop_all_slaves(0), in_flush_all_relay_logs(0),
users(0), killed(0),
- total_ddl_groups(0), total_non_trans_groups(0), total_trans_groups(0)
+ total_ddl_groups(0), total_non_trans_groups(0), total_trans_groups(0),
+ do_accept_own_server_id(false)
{
char *tmp;
host[0] = 0; user[0] = 0; password[0] = 0;
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
index ce2d3cc9ad5..1377a816d48 100644
--- a/sql/rpl_mi.h
+++ b/sql/rpl_mi.h
@@ -352,6 +352,20 @@ class Master_info : public Slave_reporting_capability
ACK from slave, or if delay_master is enabled.
*/
int semi_ack;
+ /*
+ The flag has replicate_same_server_id semantics and is raised to accept
+ a same-server-id event group by the gtid strict mode semisync slave.
+ Own server-id events can normally appear as result of EITHER
+ A. this server semisync (failover to) slave crash-recovery:
+ the transaction was created on this server then being master,
+ got replicated elsewhere right before the crash before commit,
+ and finally at recovery the transaction gets evicted from the
+ server's binlog and its gtid (slave) state; OR
+ B. in a general circular configuration and then when a recieved (returned
+ to slave) gtid exists in the server's binlog. Then, in gtid strict mode,
+ it must be ignored similarly to the replicate-same-server-id rule.
+ */
+ bool do_accept_own_server_id;
};
int init_master_info(Master_info* mi, const char* master_info_fname,
diff --git a/sql/slave.cc b/sql/slave.cc
index 9321598d06d..a0d725ca318 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -5047,6 +5047,7 @@ err_during_init:
mi->abort_slave= 0;
mi->slave_running= MYSQL_SLAVE_NOT_RUN;
mi->io_thd= 0;
+ mi->do_accept_own_server_id= false;
/*
Note: the order of the two following calls (first broadcast, then unlock)
is important. Otherwise a killer_thread can execute between the calls and
@@ -6186,15 +6187,6 @@ static int queue_event(Master_info* mi, const uchar *buf, ulong event_len)
bool is_malloc = false;
bool is_rows_event= false;
/*
- The flag has replicate_same_server_id semantics and is raised to accept
- a same-server-id event group by the gtid strict mode semisync slave.
- Own server-id events can appear as result of this server crash-recovery:
- the transaction was created on this server then being master, got replicated
- elsewhere right before the crash before commit;
- finally at recovery the transaction gets evicted from the server's binlog.
- */
- bool do_accept_own_server_id;
- /*
FD_q must have been prepared for the first R_a event
inside get_master_version_and_clock()
Show-up of FD:s affects checksum_alg at once because
@@ -6783,6 +6775,19 @@ dbug_gtid_accept:
++mi->events_queued_since_last_gtid;
inc_pos= event_len;
+
+ /*
+ To compute `true` is normal for this *now* semisync slave server when
+ it has passed its crash-recovery as a former master.
+ */
+ mi->do_accept_own_server_id=
+ (s_id == global_system_variables.server_id &&
+ rpl_semi_sync_slave_enabled && opt_gtid_strict_mode &&
+ mi->using_gtid != Master_info::USE_GTID_NO &&
+ !mysql_bin_log.check_strict_gtid_sequence(event_gtid.domain_id,
+ event_gtid.server_id,
+ event_gtid.seq_no,
+ true));
// ...} eof else_likely
}
break;
@@ -6965,10 +6970,6 @@ dbug_gtid_accept:
break;
}
- do_accept_own_server_id= (s_id == global_system_variables.server_id
- && rpl_semi_sync_slave_enabled && opt_gtid_strict_mode
- && mi->using_gtid != Master_info::USE_GTID_NO);
-
/*
Integrity of Rows- event group check.
A sequence of Rows- events must end with STMT_END_F flagged one.
@@ -7059,7 +7060,7 @@ dbug_gtid_accept:
else
if ((s_id == global_system_variables.server_id &&
!(mi->rli.replicate_same_server_id ||
- do_accept_own_server_id)) ||
+ mi->do_accept_own_server_id)) ||
event_that_should_be_ignored(buf) ||
/*
the following conjunction deals with IGNORE_SERVER_IDS, if set
@@ -7119,7 +7120,7 @@ dbug_gtid_accept:
}
else
{
- if (do_accept_own_server_id)
+ if (mi->do_accept_own_server_id)
{
int2store(const_cast<uchar*>(buf + FLAGS_OFFSET),
uint2korr(buf + FLAGS_OFFSET) | LOG_EVENT_ACCEPT_OWN_F);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 114714acfe6..b176d55134f 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2030,7 +2030,10 @@ Sys_gtid_strict_mode(
"gtid_strict_mode",
"Enforce strict seq_no ordering of events in the binary log. Slave "
"stops with an error if it encounters an event that would cause it to "
- "generate an out-of-order binlog if executed.",
+ "generate an out-of-order binlog if executed. "
+ "When ON the same server-id semisync-replicated transactions that "
+ "duplicate exising ones in binlog are ignored without error "
+ "and slave interruption.",
GLOBAL_VAR(opt_gtid_strict_mode),
CMD_LINE(OPT_ARG), DEFAULT(FALSE));