Commit 2fe61861 authored by Sachin Setiya's avatar Sachin Setiya Committed by Sachin Setiya

MDEV-10715 Galera: Replicate MariaDB GTID to other nodes in the cluster

Problem:- Gtid are not transferred in Galera Cluster.

Solution:- We need to transfer gtid in the case on either when cluster is
slave/master in async replication. In normal Gtid replication gtid are generated on
recieving node itself and it is always on sync with other nodes. Because galera keeps
node in sync , So all nodes get same no of event groups. So the issue arises when
say galera is slave in async replication.
A
|    (Async replication)
D <-> E <-> F  {Galera replication}
So what should happen is that all node should apply the master gtid but this does
node happen, becuase node E, F does not recieve gtid from D in write set , So what E(or F)
does is that it applies wsrep_gtid_domain_id, D server-id , E gtid next seq no. This
generated gtid does not always work when say A has different domain id.

So In this commit, on galera node when we see that this event is recieved from master
we simply write Gtid_Log_Event in write_set and send it to other nodes.
parent db3bdca7
START SLAVE;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
begin;
insert into t2 values(21);
insert into t2 values(22);
commit;
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4
INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(3);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4,2-2-2
INSERT INTO t1 VALUES(4);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4,2-2-2,2-3-3
DROP TABLE t1,t2;
reset master;
STOP SLAVE;
RESET SLAVE ALL;
reset master;
reset master;
#Connection 2
START SLAVE;
#Connection 1
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4
include/save_master_gtid.inc
#Connection 2
include/sync_with_master_gtid.inc
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4
INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4,2-2-3
#Connection 3
INSERT INTO t2 VALUES(7,77);
INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-4,2-2-3,2-3-5
#Connection 1
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
include/save_master_gtid.inc
#Connection 2
include/sync_with_master_gtid.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
#Connection 3
Shutting down server ...
#Connection 2
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
#Connection 3
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node3_committed_after');
INSERT INTO t1 VALUES ('node3_committed_after');
COMMIT;
#Connection 2
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
node2_committed_before
node2_committed_before
node3_committed_after
node3_committed_after
#Connection 3
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
node2_committed_before
node2_committed_before
node3_committed_after
node3_committed_after
#Connection 2
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-6,2-2-7,2-3-8
#Connection 3
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-6,2-2-7,2-3-8
#Connection 1
SET AUTOCOMMIT=ON;
#Connection 2
SET AUTOCOMMIT=ON;
#Connection 3
SET AUTOCOMMIT=ON;
#Connection 2
STOP slave;
INSERT INTO t1 VALUES ('node2_slave_stoped');
#Connection 1
INSERT INTO t1 VALUES ('node1_normal_entry');
include/save_master_gtid.inc
#Connection 2
INSERT INTO t1 VALUES ('node2_slave_stoped_inserted');
start slave;
include/sync_with_master_gtid.inc
INSERT INTO t1 VALUES ('node2_slave_started');
SELECT count(*) from t1;
count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-7,2-3-8,2-2-11
#Connection 3
SELECT count(*) from t1;
count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
1-1-7,2-3-8,2-2-11
#Connection 1
DROP TABLE t2,t1;
#Connection 2
#Connection 3
#Connection 2
STOP SLAVE;
RESET SLAVE ALL;
reset master;
#Connection 3
reset master;
#Connection 1
reset master;
!include ../galera_2nodes_as_slave.cnf
[mysqld]
log-bin=mysqld-bin
log-slave-updates
binlog-format=ROW
[mysqld.1]
gtid-domain-id=1
[mysqld.2]
gtid-domain-id=2
wsrep_gtid_mode=1
wsrep_gtid_domain_id=2
[mysqld.3]
gtid-domain-id=2
wsrep_gtid_mode=1
wsrep_gtid_domain_id=2
#
# Test Galera as a slave to a MariaDB master using GTIDs
#
# suite/galera/galera_2nodes_as_slave.cnf describes the setup of the nodes
# suite/galera/t/galera_as_slave_gtid.cnf has the GTID options
#
# In addition to performing DDL and DML, we check that the gtid of the master is preserved inside the cluster
#
--source include/have_innodb.inc
# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
--connection node_2
--disable_query_log
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
--enable_query_log
START SLAVE;
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
#multi stmt trans
begin;
insert into t2 values(21);
insert into t2 values(22);
commit;
SELECT @@global.gtid_binlog_state;
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
--source include/wait_condition.inc
--sleep 1
INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(3);
SELECT @@global.gtid_binlog_state;
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--let $wait_condition = SELECT COUNT(*) = 3 FROM t1;
--source include/wait_condition.inc
INSERT INTO t1 VALUES(4);
SELECT @@global.gtid_binlog_state;
--connection node_1
DROP TABLE t1,t2;
reset master;
#
# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
# is difficult to understand given that it is an aggregate query. A "query execution was interrupted"
# warning is also reported by MTR, which is also weird.
#
--sleep 1
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
reset master;
--connection node_3
reset master;
!include ../galera_2nodes_as_slave.cnf
[mysqld]
log-bin=mysqld-bin
log-slave-updates
binlog-format=ROW
wsrep_sst_method=rsync
[mysqld.1]
gtid-domain-id=1
[mysqld.2]
gtid-domain-id=2
wsrep_gtid_mode=1
wsrep_gtid_domain_id=2
[mysqld.3]
gtid-domain-id=2
wsrep_gtid_mode=1
wsrep_gtid_domain_id=2
#
# Test Galera as a slave to a MariaDB master using GTIDs
#
# suite/galera/galera_2nodes_as_slave.cnf describes the setup of the nodes
#
# In addition to performing DDL and DML, we check that the gtid of the master is preserved inside the cluster
#
--source include/big_test.inc
--source include/have_innodb.inc
# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
--echo #Connection 2
--connection node_2
--disable_query_log
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1,master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--sleep 1
--echo #Connection 1
--connection node_1
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
--source include/save_master_gtid.inc
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
SELECT @@global.gtid_binlog_state;
INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
--echo #Connection 3
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't2';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 6 FROM t2;
--source include/wait_condition.inc
INSERT INTO t2 VALUES(7,77);
INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
#Perform SST
--echo #Connection 1
--connection node_1
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
--source include/save_master_gtid.inc
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
--echo #Connection 3
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 4 FROM t1;
--source include/wait_condition.inc
--let $node_1= node_2
--let $node_2= node_3
--source include/auto_increment_offset_save.inc
--echo Shutting down server ...
--source include/shutdown_mysqld.inc
--echo #Connection 2
--connection node_2
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
--echo #Connection 3
--connection node_3
--echo Starting server ...
--source include/start_mysqld.inc
--source include/wait_until_ready.inc
--source include/auto_increment_offset_restore.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node3_committed_after');
INSERT INTO t1 VALUES ('node3_committed_after');
COMMIT;
--echo #Connection 2
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 8 FROM t1;
--source include/wait_condition.inc
Select * from t1 order by f1;
--echo #Connection 3
--connection node_3
Select * from t1 order by f1;
#SST Done
--sleep 1
--echo #Connection 2
--connection node_2
SELECT @@global.gtid_binlog_state;
--echo #Connection 3
--connection node_3
SELECT @@global.gtid_binlog_state;
--echo #Connection 1
--connection node_1
SET AUTOCOMMIT=ON;
#drop table t1;
#CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
--echo #Connection 2
--connection node_2
SET AUTOCOMMIT=ON;
--echo #Connection 3
--connection node_3
SET AUTOCOMMIT=ON;
#
#stop slave on node 2
--echo #Connection 2
--connection node_2
STOP slave;
--sleep 1
INSERT INTO t1 VALUES ('node2_slave_stoped');
--echo #Connection 1
--connection node_1
INSERT INTO t1 VALUES ('node1_normal_entry');
--source include/save_master_gtid.inc
#start slave
--echo #Connection 2
--connection node_2
INSERT INTO t1 VALUES ('node2_slave_stoped_inserted');
start slave;
--source include/sync_with_master_gtid.inc
INSERT INTO t1 VALUES ('node2_slave_started');
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
--echo #Connection 3
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 12 FROM t1;
--source include/wait_condition.inc
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
--echo #Connection 1
--connection node_1
DROP TABLE t2,t1;
# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
# is difficult to understand given that it is an aggregate query. A "query execution was interrupted"
# warning is also reported by MTR, which is also weird.
#
--sleep 3
--echo #Connection 2
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
--echo #Connection 3
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--echo #Connection 2
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
reset master;
--echo #Connection 3
--connection node_3
reset master;
--echo #Connection 1
--connection node_1
reset master;
# Use default setting for mysqld processes
!include include/default_mysqld.cnf
[mysqld]
log-bin
log-slave-updates
binlog-format=row
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep_gtid_mode=1
gtid_ignore_duplicates
wsrep-on=1
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
# enforce read-committed characteristics across the cluster
# wsrep-causal-reads=ON
# wsrep-sync-wait=15
[mysqld.1]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep-cluster-address='gcomm://'
wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.1.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
[mysqld.2]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
[mysqld.3]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.3.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
[mysqld.4]
wsrep_cluster_name=cluster2
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep-cluster-address='gcomm://'
wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.4.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port'
[mysqld.5]
wsrep_cluster_name=cluster2
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port'
wsrep_provider_options='base_port=@mysqld.5.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.5.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.5.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.5.#sst_port'
[mysqld.6]
wsrep_cluster_name=cluster2
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port'
wsrep_provider_options='base_port=@mysqld.6.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S'
wsrep_sst_receive_address=127.0.0.2:@mysqld.6.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.6.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.6.#sst_port'
[ENV]
NODE_MYPORT_1= @mysqld.1.port
NODE_MYSOCK_1= @mysqld.1.socket
NODE_MYPORT_2= @mysqld.2.port
NODE_MYSOCK_2= @mysqld.2.socket
NODE_MYPORT_3= @mysqld.3.port
NODE_MYSOCK_3= @mysqld.3.socket
NODE_MYPORT_4= @mysqld.4.port
NODE_MYSOCK_4= @mysqld.4.socket
NODE_MYPORT_5= @mysqld.5.port
NODE_MYSOCK_5= @mysqld.5.socket
NODE_MYPORT_6= @mysqld.6.port
NODE_MYSOCK_6= @mysqld.6.socket
NODE_GALERAPORT_1= @mysqld.1.#galera_port
NODE_GALERAPORT_2= @mysqld.2.#galera_port
NODE_GALERAPORT_3= @mysqld.3.#galera_port
NODE_GALERAPORT_4= @mysqld.4.#galera_port
NODE_GALERAPORT_5= @mysqld.5.#galera_port
NODE_GALERAPORT_6= @mysqld.6.#galera_port
NODE_SSTPORT_1= @mysqld.1.#sst_port
NODE_SSTPORT_2= @mysqld.2.#sst_port
NODE_SSTPORT_3= @mysqld.3.#sst_port
NODE_SSTPORT_4= @mysqld.4.#sst_port
NODE_SSTPORT_5= @mysqld.5.#sst_port
NODE_SSTPORT_6= @mysqld.6.#sst_port
cluster 1 node 1
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
cluster 1 node 2
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
cluster 1 node 3
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
cluster 2 node 1
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
cluster 2 node 2
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
cluster 2 node 3
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
wsrep_cluster_size 3
change master to master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_4, master_use_gtid=current_pos, ignore_server_ids=(12,13);;
start slave;
include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
@@gtid_binlog_state
select @@gtid_slave_pos;
@@gtid_slave_pos
change master to master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_1, master_use_gtid=current_pos, ignore_server_ids=(22,23);;
start slave;
include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
@@gtid_binlog_state
select @@gtid_slave_pos;
@@gtid_slave_pos
cluster 1 node 1
create table t1 (cluster_domain_id int ,node_server_id int, seq_no int);
insert into t1 values (1, 11, 2);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 1
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2
insert into t1 values (2, 21, 1);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,2-21-1
select * from t1;
cluster_domain_id node_server_id seq_no
1 11 2
2 21 1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 2
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,2-21-1
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,1-12-3,2-21-1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 3
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,1-12-3,2-21-1
insert into t1 values (1, 13, 4);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 2
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1
insert into t1 values (2, 22, 2);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
#wait for sync cluster 2 and 1
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 3
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
insert into t1 values (2, 23, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2,2-23-3
#wait for sync cluster 2 and 1
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 1
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2,2-23-3
drop table t1;
stop slave;
reset slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
cluster 2 node 1
stop slave;
reset slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
reset master;
reset master;
reset master;
reset master;
change master to master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_6, master_use_gtid=current_pos, ignore_server_ids=(12,13);;
start slave;
include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
@@gtid_binlog_state
select @@gtid_slave_pos;
@@gtid_slave_pos
change master to master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_3, master_use_gtid=current_pos, ignore_server_ids=(22,23);;
start slave;
include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
@@gtid_binlog_state
select @@gtid_slave_pos;
@@gtid_slave_pos
cluster 1 node 1
create table t1 (cluster_domain_id int ,node_server_id int, seq_no int);
insert into t1 values (1, 11, 2);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 1
insert into t1 values (2, 21, 1);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,2-21-1
select * from t1;
cluster_domain_id node_server_id seq_no
1 11 2
2 21 1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 2
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,2-21-1
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,1-12-3,2-21-1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 3
select @@gtid_binlog_state;
@@gtid_binlog_state
1-11-2,1-12-3,2-21-1
insert into t1 values (1, 13, 4);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1
#wait for sync cluster 1 and 2
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 2
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1
insert into t1 values (2, 22, 2);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
#wait for sync cluster 2 and 1
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 2 node 3
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
insert into t1 values (2, 23, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2,2-23-3
#wait for sync cluster 2 and 1
include/save_master_gtid.inc
include/sync_with_master_gtid.inc
cluster 1 node 1
select @@gtid_binlog_state;
@@gtid_binlog_state
1-12-3,1-11-2,1-13-4,2-21-1,2-22-2,2-23-3
drop table t1;
stop slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
cluster 2 node 1
stop slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
reset master;
reset master;
reset master;
reset master;
# We need a dedicated .cnf file, even if empty, in order to force this test to run
# alone on a freshly started cluster. Otherwise there are adverse interactions with
# following tests such as galera_3nodes.galera_var_dirty_reads2
!include ../galera_2x3nodes.cnf
[mysqld.1]
wsrep_gtid_domain_id=1
server-id=11
[mysqld.2]
wsrep_gtid_domain_id=1
server-id=12
[mysqld.3]
wsrep_gtid_domain_id=1
server-id=13
[mysqld.4]
wsrep_gtid_domain_id=2
server-id=21
[mysqld.5]
wsrep_gtid_domain_id=2
server-id=22
[mysqld.6]
wsrep_gtid_domain_id=2
server-id=23
#
# This test creates 2x 3 nodes galera cluster.
# The whole test case
# A <-> B <-> C {Galera cluster 1}
# | {Circular Async replication}
# D <-> E <-> F {Galera cluster 2}
# We will write on any random node to see if gtid is consitent or not
# Then we will kill node D and set up the replication between A and E
# To see whether fail over works or not.
--source include/big_test.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--connection node_1
--echo cluster 1 node 1
SHOW STATUS LIKE 'wsrep_cluster_size';
--connection node_2
--echo cluster 1 node 2
SHOW STATUS LIKE 'wsrep_cluster_size';
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connection node_3
--echo cluster 1 node 3
SHOW STATUS LIKE 'wsrep_cluster_size';
--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connection node_4
--echo cluster 2 node 1
SHOW STATUS LIKE 'wsrep_cluster_size';
--connect node_5, 127.0.0.1, root, , test, $NODE_MYPORT_5
--connection node_5
--echo cluster 2 node 2
SHOW STATUS LIKE 'wsrep_cluster_size';
--connect node_6, 127.0.0.1, root, , test, $NODE_MYPORT_6
--connection node_6
--echo cluster 2 node 3
SHOW STATUS LIKE 'wsrep_cluster_size';
#--disable_parsing
--connection node_1
--replace_result $NODE_MYPORT_4 NODE_MYPORT_4
--eval change master to master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_4, master_use_gtid=current_pos, ignore_server_ids=(12,13);
start slave;
--source include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
select @@gtid_slave_pos;
#--query_vertical SHOW SLAVE STATUS;
--connection node_4
--replace_result $NODE_MYPORT_1 NODE_MYPORT_1
--eval change master to master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_1, master_use_gtid=current_pos, ignore_server_ids=(22,23);
start slave;
--source include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
select @@gtid_slave_pos;
#--query_vertical SHOW SLAVE STATUS;
--echo cluster 1 node 1
--connection node_1
create table t1 (cluster_domain_id int ,node_server_id int, seq_no int);
insert into t1 values (1, 11, 2);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 2 node 1
--connection node_4
select @@gtid_binlog_state;
insert into t1 values (2, 21, 1);
select @@gtid_binlog_state;
select * from t1;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 2
--connection node_2
select @@gtid_binlog_state;
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 3
--connection node_3
select @@gtid_binlog_state;
insert into t1 values (1, 13, 4);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 2 node 2
--connection node_5
select @@gtid_binlog_state;
insert into t1 values (2, 22, 2);
select @@gtid_binlog_state;
--echo #wait for sync cluster 2 and 1
--connection node_4
--source include/save_master_gtid.inc
--connection node_1
--source include/sync_with_master_gtid.inc
--echo cluster 2 node 3
--connection node_6
select @@gtid_binlog_state;
insert into t1 values (2, 23, 3);
select @@gtid_binlog_state;
--echo #wait for sync cluster 2 and 1
--connection node_4
--source include/save_master_gtid.inc
--connection node_1
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 1
--connection node_1
select @@gtid_binlog_state;
drop table t1;
stop slave;
reset slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
--sleep 2
--echo cluster 2 node 1
--connection node_4
stop slave;
reset slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
--connection node_2
reset master;
--connection node_3
reset master;
--connection node_5
reset master;
--connection node_6
reset master;
#--enable_parsing
#
# This test creates 2x 3 nodes galera cluster.
# The whole test case
# A <-> B <-> C {Galera cluster 1}
# \ /
# \ /
# / {C->D, F->A , Async normal slave repl}
# / \
# | \
# D <-> E <-> F {Galera cluster 2}
# We will write on any random node to see if gtid is consitent or not
# Then we will kill node D and set up the replication between A and E
# To see whether fail over works or not.
--connection node_1
--replace_result $NODE_MYPORT_6 NODE_MYPORT_6
--eval change master to master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_6, master_use_gtid=current_pos, ignore_server_ids=(12,13);
start slave;
--source include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
select @@gtid_slave_pos;
#--query_vertical SHOW SLAVE STATUS;
--connection node_4
--replace_result $NODE_MYPORT_3 NODE_MYPORT_3
--eval change master to master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_3, master_use_gtid=current_pos, ignore_server_ids=(22,23);
start slave;
--source include/wait_for_slave_to_start.inc
select @@gtid_binlog_state;
select @@gtid_slave_pos;
#--query_vertical SHOW SLAVE STATUS;
--echo cluster 1 node 1
--connection node_1
create table t1 (cluster_domain_id int ,node_server_id int, seq_no int);
insert into t1 values (1, 11, 2);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--sleep 2
--echo cluster 2 node 1
--connection node_4
insert into t1 values (2, 21, 1);
select @@gtid_binlog_state;
select * from t1;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 2
--connection node_2
select @@gtid_binlog_state;
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 3
--connection node_3
select @@gtid_binlog_state;
insert into t1 values (1, 13, 4);
select @@gtid_binlog_state;
--echo #wait for sync cluster 1 and 2
--connection node_1
--source include/save_master_gtid.inc
--connection node_4
--source include/sync_with_master_gtid.inc
--echo cluster 2 node 2
--connection node_5
select @@gtid_binlog_state;
insert into t1 values (2, 22, 2);
select @@gtid_binlog_state;
--echo #wait for sync cluster 2 and 1
--connection node_4
--source include/save_master_gtid.inc
--connection node_1
--source include/sync_with_master_gtid.inc
--echo cluster 2 node 3
--connection node_6
select @@gtid_binlog_state;
insert into t1 values (2, 23, 3);
select @@gtid_binlog_state;
--echo #wait for sync cluster 2 and 1
--connection node_4
--source include/save_master_gtid.inc
--connection node_1
--source include/sync_with_master_gtid.inc
--echo cluster 1 node 1
--connection node_1
select @@gtid_binlog_state;
drop table t1;
stop slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
--echo cluster 2 node 1
--connection node_4
stop slave;
change master to master_use_gtid=no, ignore_server_ids=();
reset master;
set global GTID_SLAVE_POS="";
--connection node_2
reset master;
--connection node_3
reset master;
--connection node_5
reset master;
--connection node_6
reset master;
......@@ -4947,7 +4947,55 @@ MYSQL_BIN_LOG::is_xidlist_idle_nolock()
return true;
}
#ifdef WITH_WSREP
inline bool
is_gtid_cached_internal(IO_CACHE *file)
{
uchar data[EVENT_TYPE_OFFSET+1];
bool result= false;
my_off_t write_pos= my_b_tell(file);
if (reinit_io_cache(file, READ_CACHE, 0, 0, 0))
return false;
/*
In the cache we have gtid event if , below condition is true,
*/
my_b_read(file, data, sizeof(data));
uint event_type= (uchar)data[EVENT_TYPE_OFFSET];
if (event_type == GTID_LOG_EVENT)
result= true;
/*
Cleanup , Why because we have not read the full buffer
and this will cause next to next reinit_io_cache(called in write_cache)
to make cache empty.
*/
file->read_pos= file->read_end;
if (reinit_io_cache(file, WRITE_CACHE, write_pos, 0, 0))
return false;
return result;
}
#endif
#ifdef WITH_WSREP
inline bool
MYSQL_BIN_LOG::is_gtid_cached(THD *thd)
{
binlog_cache_mngr *mngr= (binlog_cache_mngr *) thd_get_ha_data(
thd, binlog_hton);
if (!mngr)
return false;
binlog_cache_data *cache_trans= mngr->get_binlog_cache_data(
use_trans_cache(thd, true));
binlog_cache_data *cache_stmt= mngr->get_binlog_cache_data(
use_trans_cache(thd, false));
if (cache_trans && !cache_trans->empty() &&
is_gtid_cached_internal(&cache_trans->cache_log))
return true;
if (cache_stmt && !cache_stmt->empty() &&
is_gtid_cached_internal(&cache_stmt->cache_log))
return true;
return false;
}
#endif
/**
Create a new log file name.
......@@ -5544,7 +5592,37 @@ THD::binlog_start_trans_and_stmt()
cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
{
this->binlog_set_stmt_begin();
if (in_multi_stmt_transaction_mode())
bool mstmt_mode= in_multi_stmt_transaction_mode();
#ifdef WITH_WSREP
/* Write Gtid
Get domain id only when gtid mode is set
If this event is replicate through a master then ,
we will forward the same gtid another nodes
We have to do this only one time in mysql transaction.
Since this function is called multiple times , We will check for
ha_info->is_started()
*/
Ha_trx_info *ha_info;
ha_info= this->ha_data[binlog_hton->slot].ha_info + (mstmt_mode ? 1 : 0);
if (!ha_info->is_started() && wsrep_gtid_mode
&& this->variables.gtid_seq_no)
{
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
IO_CACHE *file=
cache_mngr->get_binlog_cache_log(use_trans_cache(this, true));
Log_event_writer writer(file);
Gtid_log_event gtid_event(this, this->variables.gtid_seq_no,
this->variables.gtid_domain_id,
true, LOG_EVENT_SUPPRESS_USE_F,
true, 0);
gtid_event.server_id= this->variables.server_id;
writer.write(&gtid_event);
}
#endif
if (mstmt_mode)
trans_register_ha(this, TRUE, binlog_hton);
trans_register_ha(this, FALSE, binlog_hton);
/*
......@@ -5826,7 +5904,7 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
DBUG_PRINT("enter", ("standalone: %d", standalone));
#ifdef WITH_WSREP
if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode)
if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode && !thd->variables.gtid_seq_no)
{
domain_id= wsrep_gtid_domain_id;
} else {
......@@ -5878,6 +5956,12 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
/* Write the event to the binary log. */
DBUG_ASSERT(this == &mysql_bin_log);
#ifdef WITH_WSREP
if (wsrep_gtid_mode && is_gtid_cached(thd))
DBUG_RETURN(false);
#endif
if (write_event(&gtid_event))
DBUG_RETURN(true);
status_var_add(thd->status_var.binlog_bytes_written, gtid_event.data_written);
......
......@@ -559,7 +559,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
bool write_transaction_to_binlog_events(group_commit_entry *entry);
void trx_group_commit_leader(group_commit_entry *leader);
bool is_xidlist_idle_nolock();
#ifdef WITH_WSREP
/*
When this mariadb node is slave and galera enabled. So in this case
we write the gtid in wsrep_run_commit itself.
*/
inline bool is_gtid_cached(THD *thd);
#endif
public:
/*
A list of struct xid_count_per_binlog is used to keep track of how many
......
......@@ -1227,6 +1227,16 @@ int wsrep_to_buf_helper(
if (!ret && writer.write(&gtid_ev)) ret= 1;
}
#endif /* GTID_SUPPORT */
if (wsrep_gtid_mode && thd->variables.gtid_seq_no)
{
Gtid_log_event gtid_event(thd, thd->variables.gtid_seq_no,
thd->variables.gtid_domain_id,
true, LOG_EVENT_SUPPRESS_USE_F,
true, 0);
gtid_event.server_id= thd->variables.server_id;
if (!gtid_event.is_valid()) ret= 0;
ret= writer.write(&gtid_event);
}
/* if there is prepare query, add event for it */
if (!ret && thd->wsrep_TOI_pre_query)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment