summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormkaruza <mario.karuza@galeracluster.com>2019-04-01 13:23:05 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2020-01-27 11:39:13 +0200
commita3a798158879db045780882803fe54476c4d3cd7 (patch)
tree37fd2a0f5f243dbab3e517e4cfc4e171161189d2
parentb534a6675c6ba99d35112545ba7576d55cd27bb6 (diff)
downloadmariadb-git-bb-10.5-galera-gtid.tar.gz
Galera GTID supportbb-10.5-galera-gtid
Support for galera GTID consistency thru cluster. All nodes in cluster should have same GTID for replicated events which are originating from cluster. Cluster originating commands need to contain sequential WSREP GTID seqno Ignore manual setting of gtid_seq_no=X. In master-slave scenario where master is non galera node replicated GTID is replicated and is preserved in all nodes. To have this - domain_id, server_id and seqnos should be same on all nodes. Node which bootstraps the cluster, to achieve this, sends domain_id and server_id to other nodes and this combination is used to write GTID for events that are replicated inside cluster. Cluster nodes that are executing non replicated events are going to have different GTID than replicated ones, difference will be visible in domain part of gtid. With wsrep_gtid_domain_id you can set domain_id for WSREP cluster. Functions WSREP_LAST_WRITTEN_GTID, WSREP_LAST_SEEN_GTID and WSREP_SYNC_WAIT_UPTO_GTID now works with "native" GTID format. Fixed galera tests to reflect this chances. Add variable to manually update WSREP GTID seqno in cluster Add variable to manipulate and change WSREP GTID seqno. Next command originating from cluster and on same thread will have set seqno and cluster should change their internal counter to it's value. Behavior is same as using @@gtid_seq_no for non WSREP transaction.
-rw-r--r--mysql-test/suite/galera/disabled.def2
-rw-r--r--mysql-test/suite/galera/r/MDEV-10715.result28
-rw-r--r--mysql-test/suite/galera/r/galera_as_master_gtid.result28
-rw-r--r--mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result28
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result25
-rw-r--r--mysql-test/suite/galera/r/galera_gra_log.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gtid_slave.result4
-rw-r--r--mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result12
-rw-r--r--mysql-test/suite/galera/r/galera_gtid_trx_conflict.result44
-rw-r--r--mysql-test/suite/galera/r/galera_last_committed_id.result41
-rw-r--r--mysql-test/suite/galera/r/galera_performance_schema.result1
-rw-r--r--mysql-test/suite/galera/r/galera_sync_wait_upto.result27
-rw-r--r--mysql-test/suite/galera/t/MDEV-10715.cnf14
-rw-r--r--mysql-test/suite/galera/t/MDEV-10715.test19
-rw-r--r--mysql-test/suite/galera/t/MDEV-16509.test27
-rw-r--r--mysql-test/suite/galera/t/galera_as_master_gtid.cnf9
-rw-r--r--mysql-test/suite/galera/t/galera_as_master_gtid.test23
-rw-r--r--mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test19
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test11
-rw-r--r--mysql-test/suite/galera/t/galera_gra_log.test8
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_slave.cnf10
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.cnf8
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_trx_conflict.cnf14
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_trx_conflict.test56
-rw-r--r--mysql-test/suite/galera/t/galera_last_committed_id.cnf9
-rw-r--r--mysql-test/suite/galera/t/galera_last_committed_id.combinations6
-rw-r--r--mysql-test/suite/galera/t/galera_last_committed_id.test52
-rw-r--r--mysql-test/suite/galera/t/galera_sync_wait_upto.cnf9
-rw-r--r--mysql-test/suite/galera/t/galera_sync_wait_upto.combinations6
-rw-r--r--mysql-test/suite/galera/t/galera_sync_wait_upto.test90
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result38
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_wsrep.result15
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item_strfunc.cc118
-rw-r--r--sql/log.cc127
-rw-r--r--sql/log.h7
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/service_wsrep.cc24
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/wsrep_applier.cc40
-rw-r--r--sql/wsrep_high_priority_service.cc5
-rw-r--r--sql/wsrep_mysqld.cc178
-rw-r--r--sql/wsrep_mysqld.h125
-rw-r--r--sql/wsrep_server_service.cc12
-rw-r--r--sql/wsrep_sst.cc18
-rw-r--r--sql/wsrep_trans_observer.h30
-rw-r--r--sql/wsrep_var.cc55
-rw-r--r--sql/wsrep_var.h9
-rw-r--r--sql/wsrep_xid.cc66
-rw-r--r--sql/wsrep_xid.h7
52 files changed, 1055 insertions, 478 deletions
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index e00ce9e5d6f..903b2f220c0 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -21,8 +21,6 @@ MW-329 : MDEV-19962 Galera test failure on MW-329
MW-360 : needs rewrite to be MariaDB gtid compatible
galera.galera_defaults : MDEV-21494 Galera test sporadic failure on galera.galera_defaults
galera_account_management : MariaDB 10.0 does not support ALTER USER
-galera_as_master_gtid : Requires MySQL GTID
-galera_as_master_gtid_change_master : Requires MySQL GTID
galera_as_slave_gtid_myisam : MDEV-21421 galera.galera_as_slave_gtid_myisam
galera_as_slave_gtid_replicate_do_db_cc : Requires MySQL GTID
galera_as_slave_preordered : wsrep-preordered feature not merged to MariaDB
diff --git a/mysql-test/suite/galera/r/MDEV-10715.result b/mysql-test/suite/galera/r/MDEV-10715.result
new file mode 100644
index 00000000000..5ab60f08097
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-10715.result
@@ -0,0 +1,28 @@
+connection node_2;
+connection node_1;
+connection node_1;
+create table t1(a int);
+set @@wsrep_gtid_seq_no=22;
+insert into t1 values(1);
+insert into t1 values(2);
+select @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-23
+select wsrep_last_seen_gtid();
+wsrep_last_seen_gtid()
+1-1-23
+select wsrep_last_written_gtid();
+wsrep_last_written_gtid()
+1-1-23
+connection node_2;
+select @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-23
+select wsrep_last_seen_gtid();
+wsrep_last_seen_gtid()
+1-1-23
+select wsrep_last_written_gtid();
+wsrep_last_written_gtid()
+1-1-0
+connection node_1;
+drop table t1;
diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid.result b/mysql-test/suite/galera/r/galera_as_master_gtid.result
index 4f5c38b607a..51337321712 100644
--- a/mysql-test/suite/galera/r/galera_as_master_gtid.result
+++ b/mysql-test/suite/galera/r/galera_as_master_gtid.result
@@ -1,22 +1,28 @@
-START SLAVE USER='root';
-Warnings:
-Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
+connection node_2;
+connection node_1;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+START SLAVE;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
-uuids_do_not_match
-1
+SELECT @@global.gtid_binlog_pos;
+@@global.gtid_binlog_pos
+100-1-2
+connection node_2;
INSERT INTO t1 VALUES(2);
-uuids_do_not_match
-1
-uuids_match
-1
-uuids_do_not_match
+gtid_do_not_match
1
-uuids_match
+connection node_3;
+gtid_do_not_match
1
+connection node_1;
DROP TABLE t1;
+connection node_3;
+connection node_1;
+connection node_2;
gtid_executed_equal
1
+connection node_3;
gtid_executed_equal
1
STOP SLAVE;
diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result b/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result
index 80fbccf58e2..38040fbe9d7 100644
--- a/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result
+++ b/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result
@@ -1,15 +1,31 @@
-START SLAVE USER='root';
-Warnings:
-Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
+connection node_2;
+connection node_1;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+START SLAVE;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
+connection node_2;
INSERT INTO t1 VALUES(2);
+connection node_3;
STOP SLAVE;
-START SLAVE USER='root';
-Warnings:
-Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
+START SLAVE;
+connection node_1;
INSERT INTO t1 VALUES(3);
+connection node_2;
INSERT INTO t1 VALUES(4);
+connection node_3;
+connection node_1;
DROP TABLE t1;
+connection node_3;
STOP SLAVE;
RESET SLAVE ALL;
+RESET MASTER;
+connection node_2;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+connection node_1;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
index 9589d319991..afe30250811 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
@@ -97,34 +97,34 @@ master-bin.000001 256 Gtid_list 1 285 []
master-bin.000001 285 Binlog_checkpoint 1 329 master-bin.000001
master-bin.000001 329 Gtid 3 371 GTID 0-3-1
master-bin.000001 371 Query 3 458 CREATE SCHEMA test1
-master-bin.000001 458 Gtid 3 500 GTID 0-3-2
+master-bin.000001 458 Gtid 3 500 GTID 0-3-3
master-bin.000001 500 Query 3 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB
-master-bin.000001 647 Gtid 3 689 BEGIN GTID 0-3-3
+master-bin.000001 647 Gtid 3 689 BEGIN GTID 0-3-5
master-bin.000001 689 Annotate_rows 3 748 INSERT INTO test1.t1 (f1) VALUES (1)
master-bin.000001 748 Table_map 3 797 table_id: ### (test1.t1)
master-bin.000001 797 Write_rows_v1 3 839 table_id: ### flags: STMT_END_F
master-bin.000001 839 Xid 3 870 COMMIT /* xid=### */
-master-bin.000001 870 Gtid 3 912 BEGIN GTID 0-3-4
+master-bin.000001 870 Gtid 3 912 BEGIN GTID 0-3-7
master-bin.000001 912 Annotate_rows 3 971 INSERT INTO test1.t1 (f1) VALUES (2)
master-bin.000001 971 Table_map 3 1020 table_id: ### (test1.t1)
master-bin.000001 1020 Write_rows_v1 3 1062 table_id: ### flags: STMT_END_F
master-bin.000001 1062 Xid 3 1093 COMMIT /* xid=### */
-master-bin.000001 1093 Gtid 3 1135 BEGIN GTID 0-3-5
+master-bin.000001 1093 Gtid 3 1135 BEGIN GTID 0-3-9
master-bin.000001 1135 Annotate_rows 3 1194 INSERT INTO test1.t1 (f1) VALUES (3)
master-bin.000001 1194 Table_map 3 1243 table_id: ### (test1.t1)
master-bin.000001 1243 Write_rows_v1 3 1285 table_id: ### flags: STMT_END_F
master-bin.000001 1285 Xid 3 1316 COMMIT /* xid=### */
-master-bin.000001 1316 Gtid 3 1358 BEGIN GTID 0-3-6
+master-bin.000001 1316 Gtid 3 1358 BEGIN GTID 0-3-12
master-bin.000001 1358 Annotate_rows 3 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'
master-bin.000001 1451 Table_map 3 1500 table_id: ### (test1.t1)
master-bin.000001 1500 Update_rows_v1 3 1588 table_id: ### flags: STMT_END_F
master-bin.000001 1588 Xid 3 1619 COMMIT /* xid=### */
-master-bin.000001 1619 Gtid 3 1661 BEGIN GTID 0-3-7
+master-bin.000001 1619 Gtid 3 1661 BEGIN GTID 0-3-13
master-bin.000001 1661 Annotate_rows 3 1795 DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3
master-bin.000001 1795 Table_map 3 1844 table_id: ### (test1.t1)
master-bin.000001 1844 Delete_rows_v1 3 1886 table_id: ### flags: STMT_END_F
master-bin.000001 1886 Xid 3 1917 COMMIT /* xid=### */
-master-bin.000001 1917 Gtid 3 1959 BEGIN GTID 0-3-8
+master-bin.000001 1917 Gtid 3 1959 BEGIN GTID 0-3-15
master-bin.000001 1959 Annotate_rows 3 2020 INSERT INTO test1.t1 (f1) VALUES (111)
master-bin.000001 2020 Table_map 3 2069 table_id: ### (test1.t1)
master-bin.000001 2069 Write_rows_v1 3 2111 table_id: ### flags: STMT_END_F
@@ -132,7 +132,7 @@ master-bin.000001 2111 Annotate_rows 3 2172 INSERT INTO test1.t1 (f1) VALUES (22
master-bin.000001 2172 Table_map 3 2221 table_id: ### (test1.t1)
master-bin.000001 2221 Write_rows_v1 3 2263 table_id: ### flags: STMT_END_F
master-bin.000001 2263 Xid 3 2294 COMMIT /* xid=### */
-master-bin.000001 2294 Gtid 3 2336 BEGIN GTID 0-3-9
+master-bin.000001 2294 Gtid 3 2336 BEGIN GTID <effective_uuid>
master-bin.000001 2336 Annotate_rows 3 2397 INSERT INTO test1.t1 (f1) VALUES (333)
master-bin.000001 2397 Table_map 3 2446 table_id: ### (test1.t1)
master-bin.000001 2446 Write_rows_v1 3 2488 table_id: ### flags: STMT_END_F
@@ -157,3 +157,12 @@ connection node_1;
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+connection node_1;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+connection node_3;
+RESET MASTER;
diff --git a/mysql-test/suite/galera/r/galera_gra_log.result b/mysql-test/suite/galera/r/galera_gra_log.result
index 3b133b2732e..a6dca500719 100644
--- a/mysql-test/suite/galera/r/galera_gra_log.result
+++ b/mysql-test/suite/galera/r/galera_gra_log.result
@@ -1,5 +1,7 @@
connection node_2;
connection node_1;
+connection node_1;
+connection node_2;
connection node_2;
SET GLOBAL wsrep_ignore_apply_errors=0;
SET SESSION wsrep_on=OFF;
diff --git a/mysql-test/suite/galera/r/galera_gtid_slave.result b/mysql-test/suite/galera/r/galera_gtid_slave.result
index 7a3048231af..1ff062064e7 100644
--- a/mysql-test/suite/galera/r/galera_gtid_slave.result
+++ b/mysql-test/suite/galera/r/galera_gtid_slave.result
@@ -19,12 +19,12 @@ INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(3);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-0-2-2,2-3-4
+1-1-2,2-3-4
connection node_1;
INSERT INTO t1 VALUES(4);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-1,2-3-4,2-2-6
+1-1-3,2-3-4
connection node_3;
DROP TABLE t1,t2;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
index 7c5519af495..992f6c3455b 100644
--- a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
+++ b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
@@ -25,14 +25,14 @@ INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-0-2-3,2-3-4
+1-1-3,2-3-4
#Connection 1
connection node_1;
INSERT INTO t2 VALUES(7,77);
INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-2,2-3-4,2-2-7
+1-1-5,2-3-4
#Connection 3
connection node_3;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
@@ -100,12 +100,12 @@ node2_committed_before
connection node_1;
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-3,2-3-6,2-2-9
+1-1-8,2-3-6
#Connection 2
connection node_2;
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-0-1-7,0-2-8,2-3-6
+1-1-8,2-3-6
#Connection 3
connection node_3;
SET AUTOCOMMIT=ON;
@@ -134,7 +134,7 @@ count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-0-1-7,0-2-11,2-3-7
+1-1-11,2-3-7
#Connection 1
connection node_1;
SELECT count(*) from t1;
@@ -142,7 +142,7 @@ count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-3,2-3-7,2-2-12
+1-1-11,2-3-7
#Connection 3
connection node_3;
DROP TABLE t2,t1;
diff --git a/mysql-test/suite/galera/r/galera_gtid_trx_conflict.result b/mysql-test/suite/galera/r/galera_gtid_trx_conflict.result
new file mode 100644
index 00000000000..dcabff40841
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_gtid_trx_conflict.result
@@ -0,0 +1,44 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+connection node_1;
+SET AUTOCOMMIT = OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES(1);
+connection node_2;
+SET AUTOCOMMIT = OFF;
+SET @@wsrep_gtid_seq_no = 100;
+START TRANSACTION;
+INSERT INTO t1 VALUES(1);
+connection node_1;
+COMMIT;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+connection node_2;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+# Expected GTID value 1-1-2 on both nodes
+SELECT @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-2
+SET AUTOCOMMIT = ON;
+INSERT INTO t1 VALUES(2);
+# Expected GTID value 1-1-100 on both nodes, seqno is set with wsrep_gtid_seq_no
+SELECT @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-100
+connection node_1;
+SELECT @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-100
+SET AUTOCOMMIT = ON;
+INSERT INTO t1 VALUES(3);
+# Expected GTID value 1-1-101 on both nodes
+SELECT @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-101
+connection node_2;
+SELECT @@gtid_binlog_state;
+@@gtid_binlog_state
+1-1-101
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_last_committed_id.result b/mysql-test/suite/galera/r/galera_last_committed_id.result
index fabc5337576..eadf49d7ce0 100644
--- a/mysql-test/suite/galera/r/galera_last_committed_id.result
+++ b/mysql-test/suite/galera/r/galera_last_committed_id.result
@@ -1,38 +1,35 @@
connection node_2;
connection node_1;
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
-WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1'
-1
-wsrep_last_committed_id_match
-1
-connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-connection node_1a;
+SELECT WSREP_LAST_WRITTEN_GTID();
+WSREP_LAST_WRITTEN_GTID()
+100-1-0
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
-connection node_1;
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
-WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1'
-1
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;;
connection node_1a;
-INSERT INTO t1 VALUES (1);
+SELECT WSREP_LAST_WRITTEN_GTID() != '100-1-2' AS wsrep_written_does_not_match_different_conn;
+wsrep_written_does_not_match_different_conn
+1
+connection node_2;
+SELECT WSREP_LAST_WRITTEN_GTID() != '100-1-2' AS wsrep_written_does_not_match_different_nodes;
+wsrep_written_does_not_match_different_nodes
+1
connection node_1;
-wsrep_last_committed_id_match
+INSERT INTO t1 VALUES (1);
+connection node_2;
+wsrep_last_written_seen_id_match
1
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
-WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1'
-1
INSERT INTO t1 VALUES (1);
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
-WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1'
+WSREP_LAST_SEEN_GTID() = '100-1-3'
1
-wsrep_last_committed_id_match
+wsrep_last_written_id_match
1
COMMIT;
-wsrep_last_committed_id_advanced
-1
-wsrep_last_committed_id_advanced
+wsrep_last_written_id_advanced
1
SET AUTOCOMMIT=ON;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_performance_schema.result b/mysql-test/suite/galera/r/galera_performance_schema.result
index ea0b6ad9ef4..f91d33d5fbf 100644
--- a/mysql-test/suite/galera/r/galera_performance_schema.result
+++ b/mysql-test/suite/galera/r/galera_performance_schema.result
@@ -16,6 +16,7 @@ name wait/synch/mutex/sql/LOCK_wsrep_cluster_config
name wait/synch/mutex/sql/LOCK_wsrep_config_state
name wait/synch/mutex/sql/LOCK_wsrep_desync
name wait/synch/mutex/sql/LOCK_wsrep_group_commit
+name wait/synch/mutex/sql/LOCK_wsrep_gtid_wait_upto
name wait/synch/mutex/sql/LOCK_wsrep_ready
name wait/synch/mutex/sql/LOCK_wsrep_replaying
name wait/synch/mutex/sql/LOCK_wsrep_slave_threads
diff --git a/mysql-test/suite/galera/r/galera_sync_wait_upto.result b/mysql-test/suite/galera/r/galera_sync_wait_upto.result
index 7d691e105da..86c1f80f081 100644
--- a/mysql-test/suite/galera/r/galera_sync_wait_upto.result
+++ b/mysql-test/suite/galera/r/galera_sync_wait_upto.result
@@ -5,39 +5,22 @@ INSERT INTO t1 VALUES (1);
SELECT WSREP_SYNC_WAIT_UPTO_GTID(NULL);
ERROR HY000: Incorrect arguments to wsrep_sync_wait_upto_gtid
SELECT WSREP_SYNC_WAIT_UPTO_GTID('a');
-ERROR HY000: Incorrect arguments to wsrep_sync_wait_upto_gtid
+ERROR HY000: Could not parse GTID list
SELECT WSREP_SYNC_WAIT_UPTO_GTID(2);
+ERROR HY000: Could not parse GTID list
+SELECT WSREP_SYNC_WAIT_UPTO_GTID('1-1-1,1-1-2');
ERROR HY000: Incorrect arguments to wsrep_sync_wait_upto_gtid
WSREP_SYNC_WAIT_UPTO
1
WSREP_SYNC_WAIT_UPTO
1
-WSREP_SYNC_WAIT_UPTO
-1
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
connection node_2;
-SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
+SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-3');
connection node_1;
INSERT INTO t1 VALUES (2);
-INSERT INTO t1 VALUES (3);
-connection node_2;
-SET SESSION wsrep_sync_wait = 0;
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
-connection node_2a;
-SET SESSION wsrep_sync_wait = 0;
-SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
connection node_2;
-WSREP_SYNC_WAIT_UPTO
-1
-gtid_current = gtid_first
-1
-SET GLOBAL DEBUG_DBUG = "";
-SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
-WSREP_SYNC_WAIT_UPTO
-1
-seqno_current = seqno_second
+WSREP_SYNC_WAIT_UPTO_GTID('100-1-3')
1
-SET DEBUG_SYNC = "RESET";
connection node_1;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/MDEV-10715.cnf b/mysql-test/suite/galera/t/MDEV-10715.cnf
new file mode 100644
index 00000000000..589514466ed
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-10715.cnf
@@ -0,0 +1,14 @@
+!include ../galera_2nodes.cnf
+
+[mysqld]
+log-bin=mysqld-bin
+log-slave-updates
+binlog-format=ROW
+[mysqld.1]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1
+[mysqld.2]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1 \ No newline at end of file
diff --git a/mysql-test/suite/galera/t/MDEV-10715.test b/mysql-test/suite/galera/t/MDEV-10715.test
new file mode 100644
index 00000000000..186320589c3
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-10715.test
@@ -0,0 +1,19 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+create table t1(a int);
+set @@wsrep_gtid_seq_no=22;
+insert into t1 values(1);
+insert into t1 values(2);
+select @@gtid_binlog_state;
+select wsrep_last_seen_gtid();
+select wsrep_last_written_gtid();
+
+--connection node_2
+select @@gtid_binlog_state;
+select wsrep_last_seen_gtid();
+select wsrep_last_written_gtid();
+
+--connection node_1
+drop table t1;
diff --git a/mysql-test/suite/galera/t/MDEV-16509.test b/mysql-test/suite/galera/t/MDEV-16509.test
index dddd8ede293..da79cdc7d4c 100644
--- a/mysql-test/suite/galera/t/MDEV-16509.test
+++ b/mysql-test/suite/galera/t/MDEV-16509.test
@@ -15,14 +15,13 @@ CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
# Scenario 1: Block INSERT after commit order release after queued for
# group commit. Verify that
#
-# - WSREP_LAST_SEEN_GTID is not advanced before commit finishes
+# - wsrep_last_committed is not advanced before commit finishes
# - The INSERT does not become visible before commit finishes
-# Turn off sync wait to avoid blocking and use WSREP_LAST_SEEN_GTID()
+# Turn off sync wait to avoid blocking and use wsrep_last_committed
# to observe gtid position.
SET SESSION wsrep_sync_wait = 0;
---let $last_seen_gtid_prev = `SELECT WSREP_LAST_SEEN_GTID()`
-
+--let $last_seen_gtid_prev = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
--connection node_1
SET SESSION wsrep_sync_wait = 0;
# Set up sync points
@@ -37,7 +36,7 @@ SET DEBUG_SYNC = "after_group_after_commit SIGNAL after_group_reached WAIT_FOR a
# committed in memory.
SET DEBUG_SYNC = "now WAIT_FOR bcol_reached";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match
+--eval SELECT VARIABLE_VALUE = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
SELECT * FROM t1;
SET DEBUG_SYNC = "now SIGNAL bcol_continue";
@@ -45,14 +44,14 @@ SET DEBUG_SYNC = "now SIGNAL bcol_continue";
# SE commit finished but wsrep_after_commit() has not called yet.
SET DEBUG_SYNC = "now WAIT_FOR acol_reached";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match
+--eval SELECT VARIABLE_VALUE = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
SELECT * FROM t1;
SET DEBUG_SYNC = "now SIGNAL acol_continue";
SET DEBUG_SYNC = "now WAIT_FOR after_group_reached";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_do_not_match
+--eval SELECT VARIABLE_VALUE != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_do_not_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
SET DEBUG_SYNC = "now SIGNAL after_group_continue";
@@ -69,7 +68,7 @@ SET DEBUG_SYNC = "now SIGNAL after_group_continue";
SET SESSION wsrep_sync_wait = 0;
--connection ctrl
---let $last_seen_gtid_prev = `SELECT WSREP_LAST_SEEN_GTID()`
+--let $last_seen_gtid_prev = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
--connection node_1
SET DEBUG_SYNC = "wsrep_before_commit_order_leave SIGNAL bcol_reached_1 WAIT_FOR bcol_continue_1";
@@ -80,7 +79,7 @@ SET DEBUG_SYNC = "after_group_after_commit SIGNAL agac_reached_1 WAIT_FOR agac_c
SET DEBUG_SYNC = "now WAIT_FOR bcol_reached_1";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match
+--eval SELECT VARIABLE_VALUE = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
--connection node_1a
@@ -97,14 +96,14 @@ SET DEBUG_SYNC = "now WAIT_FOR acol_reached_1";
SET DEBUG_SYNC = "now WAIT_FOR bcol_reached_2";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match
+--eval SELECT VARIABLE_VALUE = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
SET DEBUG_SYNC = "now SIGNAL bcol_continue_2";
SET DEBUG_SYNC = "now WAIT_FOR acol_reached_2";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match
+--eval SELECT VARIABLE_VALUE = '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
# Last seen GTIDs are incremented one by one once after_group_after_commit
@@ -113,14 +112,14 @@ SET DEBUG_SYNC = "now SIGNAL acol_continue_1";
SET DEBUG_SYNC = "now WAIT_FOR agac_reached_1";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_no_match
+--eval SELECT VARIABLE_VALUE != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_no_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
---let $last_seen_gtid_prev = `SELECT WSREP_LAST_SEEN_GTID()`
+--let $last_seen_gtid_prev = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
SET DEBUG_SYNC = "now SIGNAL acol_continue_2";
SET DEBUG_SYNC = "now WAIT_FOR agac_reached_2";
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_no_match
+--eval SELECT VARIABLE_VALUE != '$last_seen_gtid_prev' AS wsrep_last_seen_gtid_no_match FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'
--enable_query_log
SET DEBUG_SYNC = "now SIGNAL agac_continue_1";
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
index 75caba5420a..53d8b5e59dd 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
@@ -4,3 +4,12 @@
log-bin=mysqld-bin
log-slave-updates
binlog-format=ROW
+[mysqld.1]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=100
+[mysqld.2]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+[mysqld.3]
+gtid-domain-id=2 \ No newline at end of file
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid.test b/mysql-test/suite/galera/t/galera_as_master_gtid.test
index 9be065e448b..3ddccf94da1 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid.test
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid.test
@@ -14,25 +14,22 @@
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
--enable_query_log
-START SLAVE USER='root';
+START SLAVE;
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
---let $effective_uuid = `SELECT LEFT(@@global.gtid_executed, 36)`
---disable_query_log
---eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match;
---enable_query_log
+SELECT @@global.gtid_binlog_pos;
+--let $effective_gtid = @@global.gtid_binlog_pos
--connection node_2
INSERT INTO t1 VALUES(2);
--disable_query_log
---eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match;
---eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
+--eval SELECT '$effective_gtid' != @@global.gtid_binlog_pos AS gtid_do_not_match;
--enable_query_log
--connection node_3
@@ -43,8 +40,7 @@ INSERT INTO t1 VALUES(2);
--source include/wait_condition.inc
--disable_query_log
---eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match;
---eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
+--eval SELECT '$effective_gtid' != @@global.gtid_binlog_pos AS gtid_do_not_match;
--enable_query_log
--connection node_1
@@ -55,15 +51,14 @@ DROP TABLE t1;
--source include/wait_condition.inc
--connection node_1
---let $gtid_executed_node1 = `SELECT @@global.gtid_executed;`
-
+--let $gtid_executed_node1 = `SELECT @@global.gtid_binlog_pos;`
--connection node_2
--disable_query_log
---eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal
+--eval SELECT '$gtid_executed_node1' = @@global.gtid_binlog_pos AS gtid_executed_equal
--enable_query_log
--connection node_3
--disable_query_log
---eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal
+--eval SELECT '$gtid_executed_node1' = @@global.gtid_binlog_pos AS gtid_executed_equal
--enable_query_log
STOP SLAVE;
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
index 61c7eed6543..e67456dddaf 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
@@ -12,9 +12,9 @@
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
--enable_query_log
-START SLAVE USER='root';
+START SLAVE;
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
@@ -28,9 +28,9 @@ INSERT INTO t1 VALUES(2);
--source include/wait_condition.inc
STOP SLAVE;
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_2, MASTER_AUTO_POSITION=1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_2, MASTER_USER='root';
--enable_query_log
-START SLAVE USER='root';
+START SLAVE;
--connection node_1
INSERT INTO t1 VALUES(3);
@@ -54,3 +54,14 @@ DROP TABLE t1;
STOP SLAVE;
RESET SLAVE ALL;
+RESET MASTER;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
index 81b6d446ba6..10886c41fde 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
@@ -148,3 +148,14 @@ DROP SCHEMA test2;
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_3
+RESET MASTER;
diff --git a/mysql-test/suite/galera/t/galera_gra_log.test b/mysql-test/suite/galera/t/galera_gra_log.test
index aeadafad969..23561d9a2b1 100644
--- a/mysql-test/suite/galera/t/galera_gra_log.test
+++ b/mysql-test/suite/galera/t/galera_gra_log.test
@@ -5,6 +5,11 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
+# Save original auto_increment_offset values.
+--let $node_1=node_1
+--let $node_2=node_2
+--source include/auto_increment_offset_save.inc
+
--connection node_2
--exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/GRA_*.log
let $restore_wsrep_ignore_apply_errors = `SELECT @@GLOBAL.wsrep_ignore_apply_errors`;
@@ -39,3 +44,6 @@ CREATE TABLE t1 (f1 INTEGER);
DROP TABLE t1;
CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on");
+
+# Restore original auto_increment_offset values.
+--source include/auto_increment_offset_restore.inc
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave.cnf b/mysql-test/suite/galera/t/galera_gtid_slave.cnf
index 409d0d1609a..112c487851f 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave.cnf
+++ b/mysql-test/suite/galera/t/galera_gtid_slave.cnf
@@ -4,15 +4,13 @@
log-bin=mysqld-bin
log-slave-updates
binlog-format=ROW
-
[mysqld.1]
gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1
[mysqld.2]
-gtid-domain-id=2
+gtid-domain-id=1
wsrep_gtid_mode=1
-wsrep_gtid_domain_id=2
+wsrep_gtid_domain_id=1
[mysqld.3]
gtid-domain-id=2
-wsrep_gtid_mode=1
-wsrep_gtid_domain_id=2
-
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.cnf b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.cnf
index bb9c8e84f1b..efeb536de96 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.cnf
+++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.cnf
@@ -7,12 +7,12 @@ binlog-format=ROW
wsrep_sst_method=rsync
[mysqld.1]
gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1
[mysqld.2]
-gtid-domain-id=2
+gtid-domain-id=1
wsrep_gtid_mode=1
-wsrep_gtid_domain_id=2
+wsrep_gtid_domain_id=1
[mysqld.3]
gtid-domain-id=2
-wsrep_gtid_mode=1
-wsrep_gtid_domain_id=2
diff --git a/mysql-test/suite/galera/t/galera_gtid_trx_conflict.cnf b/mysql-test/suite/galera/t/galera_gtid_trx_conflict.cnf
new file mode 100644
index 00000000000..5f129e7c168
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_gtid_trx_conflict.cnf
@@ -0,0 +1,14 @@
+!include ../galera_2nodes.cnf
+
+[mysqld]
+log-bin=mysqld-bin
+log-slave-updates
+binlog-format=ROW
+[mysqld.1]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1
+[mysqld.2]
+gtid-domain-id=1
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=1
diff --git a/mysql-test/suite/galera/t/galera_gtid_trx_conflict.test b/mysql-test/suite/galera/t/galera_gtid_trx_conflict.test
new file mode 100644
index 00000000000..27539b2ab52
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_gtid_trx_conflict.test
@@ -0,0 +1,56 @@
+#
+# Test galera GTID with conflicting trx and @@wsrep_gtid_seq_no set on one node.
+#
+
+--source include/galera_cluster.inc
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_1
+SET AUTOCOMMIT = OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES(1);
+
+--connection node_2
+SET AUTOCOMMIT = OFF;
+SET @@wsrep_gtid_seq_no = 100;
+START TRANSACTION;
+INSERT INTO t1 VALUES(1);
+
+--connection node_1
+COMMIT;
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--echo # Expected GTID value 1-1-2 on both nodes
+SELECT @@gtid_binlog_state;
+
+SET AUTOCOMMIT = ON;
+INSERT INTO t1 VALUES(2);
+
+--echo # Expected GTID value 1-1-100 on both nodes, seqno is set with wsrep_gtid_seq_no
+SELECT @@gtid_binlog_state;
+
+--connection node_1
+SELECT @@gtid_binlog_state;
+
+SET AUTOCOMMIT = ON;
+INSERT INTO t1 VALUES(3);
+
+--echo # Expected GTID value 1-1-101 on both nodes
+SELECT @@gtid_binlog_state;
+
+--connection node_2
+SELECT @@gtid_binlog_state;
+
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_last_committed_id.cnf b/mysql-test/suite/galera/t/galera_last_committed_id.cnf
new file mode 100644
index 00000000000..375d2480f23
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_last_committed_id.cnf
@@ -0,0 +1,9 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=100
+
+[mysqld.2]
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=100
diff --git a/mysql-test/suite/galera/t/galera_last_committed_id.combinations b/mysql-test/suite/galera/t/galera_last_committed_id.combinations
new file mode 100644
index 00000000000..dd92b9fa81f
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_last_committed_id.combinations
@@ -0,0 +1,6 @@
+[binlogoff]
+
+[binlogon]
+--log-bin=master-bin
+--log-bin-index=master-bin
+--log-slave-updates
diff --git a/mysql-test/suite/galera/t/galera_last_committed_id.test b/mysql-test/suite/galera/t/galera_last_committed_id.test
index 550838cdcd9..b6e3e1f7e7a 100644
--- a/mysql-test/suite/galera/t/galera_last_committed_id.test
+++ b/mysql-test/suite/galera/t/galera_last_committed_id.test
@@ -4,64 +4,62 @@
--source include/galera_cluster.inc
-# Returns -1 if no transactions have been run
+# Returns domain-server-0 if no transactions have been run
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
+SELECT WSREP_LAST_WRITTEN_GTID();
+
+# WSREP_LAST_WRITTEN_GTID() should not be influenced by transactions written
+# on other nodes or connections
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
--disable_query_log
---let $seqno = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
---let $state = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_uuid'`
---eval SELECT WSREP_LAST_SEEN_GTID() = '$state:$seqno' AS wsrep_last_committed_id_match;
+--let $wsrep_last_written_id_conn_1 = `SELECT WSREP_LAST_WRITTEN_GTID()`
--enable_query_log
-# WSREP_LAST_WRITTEN_GTID() should not be influenced by transactions committed
-# on other connections
-
---connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
--connection node_1a
-CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
-INSERT INTO t1 VALUES (1);
+--eval SELECT WSREP_LAST_WRITTEN_GTID() != '$wsrep_last_written_id_conn_1' AS wsrep_written_does_not_match_different_conn
---connection node_1
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
+--connection node_2
+--eval SELECT WSREP_LAST_WRITTEN_GTID() != '$wsrep_last_written_id_conn_1' AS wsrep_written_does_not_match_different_nodes
-# WSREP_LAST_SEEN_GTID() should be influenced by transactions committed
+# WSREP_LAST_SEEN_GTID() should be influenced by transactions written
# on other connections
---connection node_1a
+--connection node_1
INSERT INTO t1 VALUES (1);
--disable_query_log
---let $wsrep_last_committed_id_conn_1a = `SELECT WSREP_LAST_SEEN_GTID()`
+--let $wsrep_last_written_id_conn_1 = `SELECT WSREP_LAST_WRITTEN_GTID()`
--enable_query_log
---connection node_1
+--connection node_2
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$wsrep_last_committed_id_conn_1a' AS wsrep_last_committed_id_match;
+--eval SELECT WSREP_LAST_SEEN_GTID() = '$wsrep_last_written_id_conn_1' AS wsrep_last_written_seen_id_match
--enable_query_log
# Should not advance while a transaction is in progress
+--connection node_1
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
--disable_query_log
---let $wsrep_last_committed_id_before = `SELECT WSREP_LAST_SEEN_GTID()`
+--let $wsrep_last_written_id_before = `SELECT WSREP_LAST_WRITTEN_GTID()`
--enable_query_log
INSERT INTO t1 VALUES (1);
-SELECT WSREP_LAST_WRITTEN_GTID() = '00000000-0000-0000-0000-000000000000:-1';
--disable_query_log
---eval SELECT WSREP_LAST_SEEN_GTID() = '$wsrep_last_committed_id_before' AS wsrep_last_committed_id_match;
+--eval SELECT WSREP_LAST_SEEN_GTID() = '$wsrep_last_written_id_before'
+--eval SELECT WSREP_LAST_WRITTEN_GTID() = '$wsrep_last_written_id_before' AS wsrep_last_written_id_match
--enable_query_log
-# Should only advance after the transaction has been committed
+# Should only advance after the transaction has been commited
COMMIT;
--disable_query_log
---let $seqno = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
---let $state = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_uuid'`
---eval SELECT WSREP_LAST_WRITTEN_GTID() = '$state:$seqno' AS wsrep_last_committed_id_advanced;
---eval SELECT WSREP_LAST_SEEN_GTID() = '$state:$seqno' AS wsrep_last_committed_id_advanced;
+--eval SELECT WSREP_LAST_WRITTEN_GTID() != 'wsrep_last_written_id_before' AS wsrep_last_written_id_advanced
--enable_query_log
SET AUTOCOMMIT=ON;
diff --git a/mysql-test/suite/galera/t/galera_sync_wait_upto.cnf b/mysql-test/suite/galera/t/galera_sync_wait_upto.cnf
new file mode 100644
index 00000000000..375d2480f23
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_sync_wait_upto.cnf
@@ -0,0 +1,9 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=100
+
+[mysqld.2]
+wsrep_gtid_mode=1
+wsrep_gtid_domain_id=100
diff --git a/mysql-test/suite/galera/t/galera_sync_wait_upto.combinations b/mysql-test/suite/galera/t/galera_sync_wait_upto.combinations
new file mode 100644
index 00000000000..dd92b9fa81f
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_sync_wait_upto.combinations
@@ -0,0 +1,6 @@
+[binlogoff]
+
+[binlogon]
+--log-bin=master-bin
+--log-bin-index=master-bin
+--log-slave-updates
diff --git a/mysql-test/suite/galera/t/galera_sync_wait_upto.test b/mysql-test/suite/galera/t/galera_sync_wait_upto.test
index 32c6b590c84..460abf061b2 100644
--- a/mysql-test/suite/galera/t/galera_sync_wait_upto.test
+++ b/mysql-test/suite/galera/t/galera_sync_wait_upto.test
@@ -8,108 +8,64 @@
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
-
# Test with invalid values
--error ER_WRONG_ARGUMENTS
SELECT WSREP_SYNC_WAIT_UPTO_GTID(NULL);
---error ER_WRONG_ARGUMENTS
+--error ER_INCORRECT_GTID_STATE
SELECT WSREP_SYNC_WAIT_UPTO_GTID('a');
---error ER_WRONG_ARGUMENTS
+--error ER_INCORRECT_GTID_STATE
SELECT WSREP_SYNC_WAIT_UPTO_GTID(2);
+--error ER_WRONG_ARGUMENTS
+SELECT WSREP_SYNC_WAIT_UPTO_GTID('1-1-1,1-1-2');
-# If set to low value, expect no waiting
+# Expected starting seqno
---disable_query_log
---let $seqno = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
---let $state = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_uuid'`
---enable_query_log
+--let $start_seqno = 2
---disable_query_log
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('00000000-0000-0000-0000-000000000000:-1') AS WSREP_SYNC_WAIT_UPTO;
---enable_query_log
+# If set to low value, expect no waiting
--disable_query_log
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$state:0') AS WSREP_SYNC_WAIT_UPTO;
+--let $lower_seqno = $start_seqno
+--dec $lower_seqno
+--eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-$lower_seqno') AS WSREP_SYNC_WAIT_UPTO;
--enable_query_log
-
-# If set to current last_committed value
+# If set to current last_committed value no waiting
--disable_query_log
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$state:$seqno') AS WSREP_SYNC_WAIT_UPTO;
+--let $wsrep_last_committed_gtid = `SELECT WSREP_LAST_SEEN_GTID()`
+--eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$wsrep_last_committed_gtid') AS WSREP_SYNC_WAIT_UPTO;
--enable_query_log
-# If set to very high value, will wait
+# Timeout if GTID is not received on time
--disable_query_log
+--let $high_seqno = $start_seqno
+--inc $high_seqno
--error ER_LOCK_WAIT_TIMEOUT
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$state:9223372036854775807', 1) AS WSREP_SYNC_WAIT_UPTO;
+--eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-$high_seqno', 1) AS WSREP_SYNC_WAIT_UPTO;
--enable_query_log
-
-# If applier is blocked, will wait
-
---connection node_2
-SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
-
-
---connection node_1
-# Perform two inserts and record the IDs of each
-INSERT INTO t1 VALUES (2);
---let $gtid_first = `SELECT WSREP_LAST_WRITTEN_GTID()`
-
-INSERT INTO t1 VALUES (3);
---let $gtid_second = `SELECT WSREP_LAST_WRITTEN_GTID()`
+# Wait for GTID value
--connection node_2
-SET SESSION wsrep_sync_wait = 0;
-
--disable_query_log
---error ER_LOCK_WAIT_TIMEOUT
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$gtid_first', 1) AS WSREP_SYNC_WAIT_UPTO;
+--let $wait_seqno = $start_seqno
+--inc $wait_seqno
--enable_query_log
---disable_query_log
---send_eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$gtid_first') AS WSREP_SYNC_WAIT_UPTO;
---enable_query_log
+--send_eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-$wait_seqno')
-# Unblock applier
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
---connection node_2a
-SET SESSION wsrep_sync_wait = 0;
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'SELECT WSREP_SYNC_WAIT%';
---source include/wait_condition.inc
-SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+--connection node_1
+INSERT INTO t1 VALUES (2);
--connection node_2
--reap
-# Confirm that we were allowed to proceed when the applier reached $seqno_first
---let $gtid_current = `SELECT WSREP_LAST_SEEN_GTID()`
---disable_query_log
---eval SELECT '$gtid_current' = '$gtid_first' AS `gtid_current = gtid_first`
---enable_query_log
-
-SET GLOBAL DEBUG_DBUG = "";
-SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
-
-# Move forward some more, to $seqno_second;
-
---disable_query_log
---eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('$gtid_second') AS WSREP_SYNC_WAIT_UPTO;
---enable_query_log
-
---let $gtid_current = `SELECT WSREP_LAST_SEEN_GTID()`
---disable_query_log
---eval SELECT '$gtid_current' = '$gtid_second' AS `seqno_current = seqno_second`
---enable_query_log
-
-SET DEBUG_SYNC = "RESET";
-
--connection node_1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result b/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result
index afb94d493c4..7d4751e79af 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result
@@ -92,7 +92,7 @@ select @@gtid_binlog_state;
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,1-12-3,2-21-1
+1-11-3,2-21-1
#wait for sync cluster 1 and 2
connection node_1;
include/save_master_gtid.inc
@@ -102,11 +102,11 @@ cluster 1 node 3
connection node_3;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,1-12-3,2-21-1
+1-11-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
+1-11-4,2-21-1
#wait for sync cluster 1 and 2
connection node_1;
include/save_master_gtid.inc
@@ -116,11 +116,11 @@ cluster 2 node 2
connection node_5;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-12-3,1-11-2,1-13-4,2-21-1
+1-11-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
+1-11-4,2-21-2
#wait for sync cluster 2 and 1
connection node_4;
include/save_master_gtid.inc
@@ -130,11 +130,11 @@ cluster 2 node 3
connection node_6;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
+1-11-4,2-21-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
+1-11-4,2-21-3
#wait for sync cluster 2 and 1
connection node_4;
include/save_master_gtid.inc
@@ -144,7 +144,7 @@ cluster 1 node 1
connection 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
+1-11-4,2-21-3
drop table t1;
stop slave;
reset slave;
@@ -208,7 +208,7 @@ 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
+1-11-7
#wait for sync cluster 1 and 2
connection node_1;
include/save_master_gtid.inc
@@ -219,7 +219,7 @@ connection node_4;
insert into t1 values (2, 21, 1);
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,2-21-1
+1-11-7,2-21-4
select * from t1;
cluster_domain_id node_server_id seq_no
1 11 2
@@ -233,11 +233,11 @@ cluster 1 node 2
connection node_2;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,2-21-1
+1-11-7,2-21-4
insert into t1 values (1, 12, 3);
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,1-12-3,2-21-1
+1-11-8,2-21-4
#wait for sync cluster 1 and 2
connection node_1;
include/save_master_gtid.inc
@@ -247,11 +247,11 @@ cluster 1 node 3
connection node_3;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-11-2,1-12-3,2-21-1
+1-11-8,2-21-4
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
+1-11-9,2-21-4
#wait for sync cluster 1 and 2
connection node_1;
include/save_master_gtid.inc
@@ -261,11 +261,11 @@ cluster 2 node 2
connection node_5;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-12-3,1-11-2,1-13-4,2-21-1
+1-11-9,2-21-4
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
+1-11-9,2-21-5
#wait for sync cluster 2 and 1
connection node_4;
include/save_master_gtid.inc
@@ -275,11 +275,11 @@ cluster 2 node 3
connection node_6;
select @@gtid_binlog_state;
@@gtid_binlog_state
-1-12-3,1-11-2,1-13-4,2-21-1,2-22-2
+1-11-9,2-21-5
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
+1-11-9,2-21-6
#wait for sync cluster 2 and 1
connection node_4;
include/save_master_gtid.inc
@@ -289,7 +289,7 @@ cluster 1 node 1
connection 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
+1-11-9,2-21-6
drop table t1;
stop slave;
change master to master_use_gtid=no, ignore_server_ids=();
diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
index 67209c5e846..a1d66e4d112 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
@@ -241,6 +241,21 @@ ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
GLOBAL_VALUE_PATH NULL
+VARIABLE_NAME WSREP_GTID_SEQ_NO
+SESSION_VALUE 0
+GLOBAL_VALUE NULL
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE 0
+VARIABLE_SCOPE SESSION ONLY
+VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_COMMENT Internal server usage, manually set WSREP GTID seqno.
+NUMERIC_MIN_VALUE 0
+NUMERIC_MAX_VALUE 18446744073709551615
+NUMERIC_BLOCK_SIZE 1
+ENUM_VALUE_LIST NULL
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT NULL
+GLOBAL_VALUE_PATH NULL
VARIABLE_NAME WSREP_IGNORE_APPLY_ERRORS
SESSION_VALUE NULL
GLOBAL_VALUE 7
diff --git a/sql/handler.cc b/sql/handler.cc
index 0132f2dd027..68d7e3ac1fc 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2058,7 +2058,7 @@ static my_xid wsrep_order_and_check_continuity(XID *list, int len)
{
#ifdef WITH_WSREP
wsrep_sort_xid_array(list, len);
- wsrep::gtid cur_position= wsrep_get_SE_checkpoint();
+ wsrep::gtid cur_position= wsrep_get_SE_checkpoint<wsrep::gtid>();
long long cur_seqno= cur_position.seqno().get();
for (int i= 0; i < len; ++i)
{
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5fb7ee0ea61..b6dff93ba49 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -5236,28 +5236,33 @@ String *Item_temptable_rowid::val_str(String *str)
str_value.set((char*)(table->file->ref), max_length, &my_charset_bin);
return &str_value;
}
+
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
+/* Format is %d-%d-%llu */
+#define WSREP_MAX_WSREP_SERVER_GTID_STR_LEN 10+1+10+1+20
String *Item_func_wsrep_last_written_gtid::val_str_ascii(String *str)
{
- wsrep::gtid gtid= current_thd->wsrep_cs().last_written_gtid();
- if (gtid_str.alloc(wsrep::gtid_c_str_len()))
+ if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1))
{
- my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len());
- null_value= true;
- return NULL;
+ my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN);
+ null_value= TRUE;
+ return 0;
}
- ssize_t gtid_len= gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(),
- wsrep::gtid_c_str_len());
+ ssize_t gtid_len= my_snprintf((char*)gtid_str.ptr(),
+ WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1,
+ "%u-%u-%llu", wsrep_gtid_server.domain_id,
+ wsrep_gtid_server.server_id,
+ current_thd->wsrep_last_written_gtid_seqno);
if (gtid_len < 0)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
- "wsrep_gtid_print failed");
- null_value= true;
- return NULL;
+ "wsrep_gtid_print failed");
+ null_value= TRUE;
+ return 0;
}
gtid_str.length(gtid_len);
return &gtid_str;
@@ -5265,23 +5270,23 @@ String *Item_func_wsrep_last_written_gtid::val_str_ascii(String *str)
String *Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str)
{
- /* TODO: Should call Wsrep_server_state.instance().last_committed_gtid()
- instead. */
- wsrep::gtid gtid= Wsrep_server_state::instance().provider().last_committed_gtid();
- if (gtid_str.alloc(wsrep::gtid_c_str_len()))
+ if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1))
{
- my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len());
- null_value= true;
- return NULL;
+ my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN);
+ null_value= TRUE;
+ return 0;
}
- ssize_t gtid_len= wsrep::gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(),
- wsrep::gtid_c_str_len());
+ ssize_t gtid_len= my_snprintf((char*)gtid_str.ptr(),
+ WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1,
+ "%u-%u-%llu", wsrep_gtid_server.domain_id,
+ wsrep_gtid_server.server_id,
+ wsrep_gtid_server.seqno());
if (gtid_len < 0)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
"wsrep_gtid_print failed");
- null_value= true;
- return NULL;
+ null_value= TRUE;
+ return 0;
}
gtid_str.length(gtid_len);
return &gtid_str;
@@ -5289,49 +5294,52 @@ String *Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str)
longlong Item_func_wsrep_sync_wait_upto::val_int()
{
- int timeout= -1;
- String* gtid_str= args[0]->val_str(&value);
- if (gtid_str == NULL)
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
- return 0LL;
- }
-
- if (arg_count == 2)
- {
- timeout= args[1]->val_int();
- }
+ String *gtid_str __attribute__((unused)) = args[0]->val_str(&value);
+ null_value=0;
+ uint timeout;
+ rpl_gtid *gtid_list;
+ uint32 count;
+ int ret= 1;
- wsrep_gtid_t gtid;
- int gtid_len= wsrep_gtid_scan(gtid_str->ptr(), gtid_str->length(), &gtid);
- if (gtid_len < 0)
+ if (args[0]->null_value)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
- return 0LL;
+ null_value= TRUE;
+ return 0;
}
- if (gtid.seqno == WSREP_SEQNO_UNDEFINED &&
- wsrep_uuid_compare(&gtid.uuid, &WSREP_UUID_UNDEFINED) == 0)
+ if (arg_count==2 && !args[1]->null_value)
+ timeout= (uint)(args[1]->val_real());
+ else
+ timeout= (uint)-1;
+
+ if (!(gtid_list= gtid_parse_string_to_list(gtid_str->ptr(), gtid_str->length(),
+ &count)))
{
- return 1LL;
+ my_error(ER_INCORRECT_GTID_STATE, MYF(0), func_name());
+ null_value= TRUE;
+ return 0;
}
-
- enum wsrep::provider::status status=
- wsrep_sync_wait_upto(current_thd, &gtid, timeout);
-
- if (status)
+ if (count == 1)
{
- int err;
- switch (status) {
- case wsrep::provider::error_transaction_missing:
- err= ER_WRONG_ARGUMENTS;
- break;
- default:
- err= ER_LOCK_WAIT_TIMEOUT;
+ if (wsrep_check_gtid_seqno(gtid_list[0].domain_id, gtid_list[0].server_id,
+ gtid_list[0].seq_no))
+ {
+ if (wsrep_gtid_server.wait_gtid_upto(gtid_list[0].seq_no, timeout))
+ {
+ my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), func_name());
+ ret= 0;
+ }
}
- my_error(err, MYF(0), func_name());
- return 0LL;
}
- return 1LL;
+ else
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
+ null_value= TRUE;
+ ret= 0;
+ }
+ my_free(gtid_list);
+ return ret;
}
+
#endif /* WITH_WSREP */
diff --git a/sql/log.cc b/sql/log.cc
index bf19946210a..93b5d697d14 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5048,55 +5048,6 @@ 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.
@@ -5719,31 +5670,47 @@ THD::binlog_start_trans_and_stmt()
{
DBUG_VOID_RETURN;
}
- /* 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()
- */
+ /* If this event replicates through a master-slave then we need to
+ inject manually GTID so it is preserved in the cluster. We are writing
+ directly to WSREP buffer and not in IO cache because in case of IO cache
+ GTID event will be duplicated in binlog.
+ 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)
+ if (!ha_info->is_started() &&
+ (this->variables.gtid_seq_no || this->variables.wsrep_gtid_seq_no) &&
+ wsrep_on(this) &&
+ (this->wsrep_cs().mode() == wsrep::client_state::m_local))
{
- binlog_cache_mngr *const cache_mngr=
- (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
- binlog_cache_data *cache_data= cache_mngr->get_binlog_cache_data(1);
- IO_CACHE *file= &cache_data->cache_log;
- Log_event_writer writer(file, cache_data);
- 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);
+ uchar *buf= 0;
+ size_t len= 0;
+ IO_CACHE tmp_io_cache;
+ Log_event_writer writer(&tmp_io_cache, 0);
+ if(!open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX,
+ 128, MYF(MY_WME)))
+ {
+ uint64 seqno= this->variables.gtid_seq_no;
+ uint32 domain_id= this->variables.gtid_domain_id;
+ uint32 server_id= this->variables.server_id;
+ if (!this->variables.gtid_seq_no && this->variables.wsrep_gtid_seq_no)
+ {
+ seqno= this->variables.wsrep_gtid_seq_no;
+ domain_id= wsrep_gtid_server.domain_id;
+ server_id= wsrep_gtid_server.server_id;
+ }
+ Gtid_log_event gtid_event(this, seqno, domain_id, true,
+ LOG_EVENT_SUPPRESS_USE_F, true, 0);
+ gtid_event.server_id= server_id;
+ writer.write(&gtid_event);
+ wsrep_write_cache_buf(&tmp_io_cache, &buf, &len);
+ if (len > 0) this->wsrep_cs().append_data(wsrep::const_buffer(buf, len));
+ if (buf) my_free(buf);
+ close_cached_file(&tmp_io_cache);
+ }
}
#endif
if (mstmt_mode)
@@ -6024,20 +5991,9 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
DBUG_ENTER("write_gtid_event");
DBUG_PRINT("enter", ("standalone: %d", standalone));
-#ifdef WITH_WSREP
- if (WSREP(thd) &&
- (wsrep_thd_trx_seqno(thd) > 0) &&
- wsrep_gtid_mode && !thd->variables.gtid_seq_no)
- {
- domain_id= wsrep_gtid_domain_id;
- } else {
-#endif /* WITH_WSREP */
+ seq_no= thd->variables.gtid_seq_no;
domain_id= thd->variables.gtid_domain_id;
-#ifdef WITH_WSREP
- }
-#endif /* WITH_WSREP */
local_server_id= thd->variables.server_id;
- seq_no= thd->variables.gtid_seq_no;
DBUG_ASSERT(local_server_id != 0);
@@ -6084,8 +6040,11 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
DBUG_ASSERT(this == &mysql_bin_log);
#ifdef WITH_WSREP
- if (wsrep_gtid_mode && is_gtid_cached(thd))
- DBUG_RETURN(false);
+ if (wsrep_gtid_mode)
+ {
+ thd->variables.gtid_domain_id= global_system_variables.gtid_domain_id;
+ thd->variables.server_id= global_system_variables.server_id;
+ }
#endif
if (write_event(&gtid_event))
diff --git a/sql/log.h b/sql/log.h
index bf1dbd30c6c..7ccfd606f21 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -561,13 +561,6 @@ 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
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 09d8b4b7d1c..738c1d7e2c1 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5724,6 +5724,8 @@ int mysqld_main(int argc, char **argv)
{
wsrep_shutdown_replication();
}
+ /* Release threads if they are waiting in WSREP_SYNC_WAIT_UPTO_GTID */
+ wsrep_gtid_server.signal_waiters(0, true);
#endif
close_connections();
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index 36ea311f59f..68de55b5778 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -281,16 +281,34 @@ extern "C" int wsrep_thd_append_key(THD *thd,
}
ret= client_state.append_key(wsrep_key);
}
+ /*
+ In case of `wsrep_gtid_mode` when WS will be replicated, we need to set
+ `server_id` for events that are going to be written in IO, and in case of
+ manual SET gtid_seq_no=X we are ignoring value.
+ */
+ if (!ret && wsrep_gtid_mode && !thd->slave_thread && !wsrep_thd_is_applying(thd))
+ {
+ thd->variables.server_id= wsrep_gtid_server.server_id;
+ thd->variables.gtid_seq_no= 0;
+ }
return ret;
}
extern "C" void wsrep_commit_ordered(THD *thd)
{
if (wsrep_is_active(thd) &&
- thd->wsrep_trx().state() == wsrep::transaction::s_committing &&
- !wsrep_commit_will_write_binlog(thd))
+ (thd->wsrep_trx().state() == wsrep::transaction::s_committing ||
+ thd->wsrep_trx().state() == wsrep::transaction::s_ordered_commit))
{
- thd->wsrep_cs().ordered_commit();
+ wsrep_gtid_server.signal_waiters(thd->wsrep_current_gtid_seqno, false);
+ if (wsrep_thd_is_local(thd))
+ {
+ thd->wsrep_last_written_gtid_seqno= thd->wsrep_current_gtid_seqno;
+ }
+ if (!wsrep_commit_will_write_binlog(thd))
+ {
+ thd->wsrep_cs().ordered_commit();
+ }
}
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4577f1007be..34edea3a93c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -697,9 +697,10 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
wsrep_apply_format(0),
wsrep_rbr_buf(NULL),
wsrep_sync_wait_gtid(WSREP_GTID_UNDEFINED),
+ wsrep_last_written_gtid_seqno(0),
+ wsrep_current_gtid_seqno(0),
wsrep_affected_rows(0),
wsrep_has_ignored_error(false),
- wsrep_replicate_GTID(false),
wsrep_ignore_table(false),
/* wsrep-lib */
@@ -1313,7 +1314,6 @@ void THD::init()
wsrep_rbr_buf = NULL;
wsrep_affected_rows = 0;
m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID;
- wsrep_replicate_GTID = false;
#endif /* WITH_WSREP */
if (variables.sql_log_bin)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 8fc33523896..0a9878aad4d 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -629,6 +629,7 @@ typedef struct system_variables
are based on the cluster size):
*/
ulong saved_auto_increment_increment, saved_auto_increment_offset;
+ ulonglong wsrep_gtid_seq_no;
#endif /* WITH_WSREP */
uint eq_range_index_dive_limit;
ulong column_compression_zlib_strategy;
@@ -4875,17 +4876,13 @@ public:
size_t wsrep_TOI_pre_query_len;
wsrep_po_handle_t wsrep_po_handle;
size_t wsrep_po_cnt;
-#ifdef GTID_SUPPORT
- my_bool wsrep_po_in_trans;
- rpl_sid wsrep_po_sid;
-#endif /* GTID_SUPPORT */
void *wsrep_apply_format;
uchar* wsrep_rbr_buf;
wsrep_gtid_t wsrep_sync_wait_gtid;
- // wsrep_gtid_t wsrep_last_written_gtid;
+ uint64 wsrep_last_written_gtid_seqno;
+ uint64 wsrep_current_gtid_seqno;
ulong wsrep_affected_rows;
bool wsrep_has_ignored_error;
- bool wsrep_replicate_GTID;
/*
When enabled, do not replicate/binlog updates from the current table that's
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index de476042a80..ab382304973 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5792,9 +5792,17 @@ static Sys_var_uint Sys_wsrep_gtid_domain_id(
"wsrep_gtid_domain_id", "When wsrep_gtid_mode is set, this value is "
"used as gtid_domain_id for galera transactions and also copied to the "
"joiner nodes during state transfer. It is ignored, otherwise.",
- GLOBAL_VAR(wsrep_gtid_domain_id), CMD_LINE(REQUIRED_ARG),
+ GLOBAL_VAR(wsrep_gtid_server.domain_id), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1));
+static Sys_var_ulonglong Sys_wsrep_gtid_seq_no(
+ "wsrep_gtid_seq_no",
+ "Internal server usage, manually set WSREP GTID seqno.",
+ SESSION_ONLY(wsrep_gtid_seq_no),
+ NO_CMD_LINE, VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0),
+ BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(wsrep_gtid_seq_no_check));
+
static Sys_var_mybool Sys_wsrep_gtid_mode(
"wsrep_gtid_mode", "Automatically update the (joiner) node's "
"wsrep_gtid_domain_id value with that of donor's (received during "
diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc
index 1ab65df1ca3..25a4e22aeb4 100644
--- a/sql/wsrep_applier.cc
+++ b/sql/wsrep_applier.cc
@@ -131,6 +131,12 @@ int wsrep_apply_events(THD* thd,
if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld",
(long long) wsrep_thd_trx_seqno(thd));
+ thd->variables.gtid_seq_no= 0;
+ if (wsrep_gtid_mode)
+ thd->variables.gtid_domain_id= wsrep_gtid_server.domain_id;
+ else
+ thd->variables.gtid_domain_id= global_system_variables.gtid_domain_id;
+
while (buf_len)
{
int exec_res;
@@ -150,22 +156,38 @@ int wsrep_apply_events(THD* thd,
case FORMAT_DESCRIPTION_EVENT:
wsrep_set_apply_format(thd, (Format_description_log_event*)ev);
continue;
-#ifdef GTID_SUPPORT
- case GTID_LOG_EVENT:
- {
- Gtid_log_event* gev= (Gtid_log_event*)ev;
- if (gev->get_gno() == 0)
+ case GTID_EVENT:
{
- /* Skip GTID log event to make binlog to generate LTID on commit */
+ Gtid_log_event *gtid_ev= (Gtid_log_event*)ev;
+ thd->variables.server_id= gtid_ev->server_id;
+ thd->variables.gtid_domain_id= gtid_ev->domain_id;
+ if ((gtid_ev->server_id == wsrep_gtid_server.server_id) &&
+ (gtid_ev->domain_id == wsrep_gtid_server.domain_id))
+ {
+ thd->variables.wsrep_gtid_seq_no= gtid_ev->seq_no;
+ }
+ else
+ {
+ thd->variables.gtid_seq_no= gtid_ev->seq_no;
+ }
delete ev;
- continue;
}
- }
-#endif /* GTID_SUPPORT */
+ continue;
default:
break;
}
+
+ if (!thd->variables.gtid_seq_no && wsrep_thd_is_toi(thd) &&
+ (ev->get_type_code() == QUERY_EVENT))
+ {
+ uint64 seqno= wsrep_gtid_server.seqno_inc();
+ thd->wsrep_current_gtid_seqno= seqno;
+ if (mysql_bin_log.is_open() && wsrep_gtid_mode)
+ {
+ thd->variables.gtid_seq_no= seqno;
+ }
+ }
/* Use the original server id for logging. */
thd->set_server_id(ev->server_id);
thd->set_time(); // time the query
diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc
index 06d398baf5f..d73b9cb09ce 100644
--- a/sql/wsrep_high_priority_service.cc
+++ b/sql/wsrep_high_priority_service.cc
@@ -396,7 +396,8 @@ int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta,
thd->close_temporary_tables();
thd->lex->sql_command= SQLCOM_END;
- wsrep_set_SE_checkpoint(client_state.toi_meta().gtid());
+ wsrep_gtid_server.signal_waiters(thd->wsrep_current_gtid_seqno, false);
+ wsrep_set_SE_checkpoint(client_state.toi_meta().gtid(), wsrep_gtid_server.gtid());
must_exit_= check_exit_status();
@@ -448,7 +449,7 @@ int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_
cs.before_rollback();
cs.after_rollback();
}
- wsrep_set_SE_checkpoint(ws_meta.gtid());
+ wsrep_set_SE_checkpoint(ws_meta.gtid(), wsrep_gtid_server.gtid());
ret= ret || cs.provider().commit_order_leave(ws_handle, ws_meta, err);
cs.after_applying();
}
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 708c320c471..9a68282d9b8 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -52,11 +52,7 @@
/* wsrep-lib */
Wsrep_server_state* Wsrep_server_state::m_instance;
-my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface
-#ifdef GTID_SUPPORT
-/* Sidno in global_sid_map corresponding to group uuid */
-rpl_sidno wsrep_sidno= -1;
-#endif /* GTID_SUPPORT */
+my_bool wsrep_emulate_bin_log= FALSE; // activating parts of binlog interface
my_bool wsrep_preordered_opt= FALSE;
/* Streaming Replication */
@@ -106,10 +102,9 @@ ulong wsrep_max_ws_size; // Max allowed ws (RBR buffer) s
ulong wsrep_max_ws_rows; // Max number of rows in ws
ulong wsrep_forced_binlog_format;
ulong wsrep_mysql_replication_bundle;
-bool wsrep_gtid_mode; // Use wsrep_gtid_domain_id
- // for galera transactions?
-uint32 wsrep_gtid_domain_id; // gtid_domain_id for galera
- // transactions
+
+bool wsrep_gtid_mode; // Enable WSREP native GTID support
+Wsrep_gtid_server wsrep_gtid_server;
/* Other configuration variables and their default values. */
my_bool wsrep_incremental_data_collection= 0; // Incremental data collection
@@ -144,6 +139,7 @@ mysql_mutex_t LOCK_wsrep_replaying;
mysql_cond_t COND_wsrep_replaying;
mysql_mutex_t LOCK_wsrep_slave_threads;
mysql_cond_t COND_wsrep_slave_threads;
+mysql_mutex_t LOCK_wsrep_gtid_wait_upto;
mysql_mutex_t LOCK_wsrep_cluster_config;
mysql_mutex_t LOCK_wsrep_desync;
mysql_mutex_t LOCK_wsrep_config_state;
@@ -163,7 +159,8 @@ ulong my_bind_addr;
PSI_mutex_key
key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst,
key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init,
- key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync,
+ key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_gtid_wait_upto,
+ key_LOCK_wsrep_desync,
key_LOCK_wsrep_config_state, key_LOCK_wsrep_cluster_config,
key_LOCK_wsrep_group_commit,
key_LOCK_wsrep_SR_pool,
@@ -173,8 +170,8 @@ PSI_mutex_key
PSI_cond_key key_COND_wsrep_thd,
key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst,
key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread,
- key_COND_wsrep_thd_queue, key_COND_wsrep_slave_threads;
-
+ key_COND_wsrep_thd_queue, key_COND_wsrep_slave_threads, key_COND_wsrep_gtid_wait_upto,
+ key_COND_wsrep_joiner_monitor, key_COND_wsrep_donor_monitor;
PSI_file_key key_file_wsrep_gra_log;
@@ -187,6 +184,7 @@ static PSI_mutex_info wsrep_mutexes[]=
{ &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_gtid_wait_upto, "LOCK_wsrep_gtid_wait_upto", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_cluster_config, "LOCK_wsrep_cluster_config", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL},
@@ -203,7 +201,8 @@ static PSI_cond_info wsrep_conds[]=
{ &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0},
{ &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0},
{ &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL},
- { &key_COND_wsrep_slave_threads, "COND_wsrep_wsrep_slave_threads", PSI_FLAG_GLOBAL}
+ { &key_COND_wsrep_slave_threads, "COND_wsrep_wsrep_slave_threads", PSI_FLAG_GLOBAL},
+ { &key_COND_wsrep_gtid_wait_upto, "COND_wsrep_gtid_wait_upto", PSI_FLAG_GLOBAL},
};
static PSI_file_info wsrep_files[]=
@@ -289,6 +288,58 @@ static void wsrep_log_cb(wsrep::log::level level, const char *msg)
}
}
+void wsrep_init_gtid()
+{
+ wsrep_server_gtid_t stored_gtid= wsrep_get_SE_checkpoint<wsrep_server_gtid_t>();
+ if (stored_gtid.server_id == 0)
+ {
+ rpl_gtid wsrep_last_gtid;
+ stored_gtid.domain_id= wsrep_gtid_server.domain_id;
+ if (mysql_bin_log.is_open() &&
+ mysql_bin_log.lookup_domain_in_binlog_state(stored_gtid.domain_id,
+ &wsrep_last_gtid))
+ {
+ stored_gtid.server_id= wsrep_last_gtid.server_id;
+ stored_gtid.seqno= wsrep_last_gtid.seq_no;
+ }
+ else
+ {
+ stored_gtid.server_id= global_system_variables.server_id;
+ stored_gtid.seqno= 0;
+ }
+ }
+ wsrep_gtid_server.gtid(stored_gtid);
+}
+
+bool wsrep_get_binlog_gtid_seqno(wsrep_server_gtid_t& gtid)
+{
+ rpl_gtid binlog_gtid;
+ int ret= 0;
+ if (mysql_bin_log.is_open() &&
+ mysql_bin_log.find_in_binlog_state(gtid.domain_id,
+ gtid.server_id,
+ &binlog_gtid))
+ {
+ gtid.domain_id= binlog_gtid.domain_id;
+ gtid.server_id= binlog_gtid.server_id;
+ gtid.seqno= binlog_gtid.seq_no;
+ ret= 1;
+ }
+ return ret;
+}
+
+bool wsrep_check_gtid_seqno(const uint32& domain, const uint32& server,
+ uint64& seqno)
+{
+ if (domain == wsrep_gtid_server.domain_id &&
+ server == wsrep_gtid_server.server_id)
+ {
+ if (wsrep_gtid_server.seqno_committed() < seqno) return 1;
+ return 0;
+ }
+ return 0;
+}
+
void wsrep_init_sidno(const wsrep::id& uuid)
{
/*
@@ -679,6 +730,16 @@ int wsrep_init_server()
void wsrep_init_globals()
{
wsrep_init_sidno(Wsrep_server_state::instance().connected_gtid().id());
+ wsrep_init_gtid();
+ /* Recover last written wsrep gtid */
+ if (wsrep_new_cluster)
+ {
+ wsrep_server_gtid_t gtid= {wsrep_gtid_server.domain_id,
+ wsrep_gtid_server.server_id, 0};
+ wsrep_get_binlog_gtid_seqno(gtid);
+ wsrep_gtid_server.seqno(gtid.seqno);
+ }
+ wsrep_new_cluster= 0;
wsrep_init_schema();
if (WSREP_ON)
{
@@ -780,6 +841,7 @@ void wsrep_thr_init()
mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL);
mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_slave_threads, &COND_wsrep_slave_threads, NULL);
+ mysql_mutex_init(key_LOCK_wsrep_gtid_wait_upto, &LOCK_wsrep_gtid_wait_upto, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_cluster_config, &LOCK_wsrep_cluster_config, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST);
@@ -883,6 +945,7 @@ void wsrep_thr_deinit()
mysql_cond_destroy(&COND_wsrep_sst_init);
mysql_mutex_destroy(&LOCK_wsrep_replaying);
mysql_cond_destroy(&COND_wsrep_replaying);
+ mysql_mutex_destroy(&LOCK_wsrep_gtid_wait_upto);
mysql_mutex_destroy(&LOCK_wsrep_slave_threads);
mysql_cond_destroy(&COND_wsrep_slave_threads);
mysql_mutex_destroy(&LOCK_wsrep_cluster_config);
@@ -915,10 +978,20 @@ void wsrep_recover()
uuid_str, (long long)local_seqno);
return;
}
- wsrep::gtid gtid= wsrep_get_SE_checkpoint();
+ wsrep::gtid gtid= wsrep_get_SE_checkpoint<wsrep::gtid>();
std::ostringstream oss;
oss << gtid;
- WSREP_INFO("Recovered position: %s", oss.str().c_str());
+ if (wsrep_gtid_mode)
+ {
+ wsrep_server_gtid_t server_gtid= wsrep_get_SE_checkpoint<wsrep_server_gtid_t>();
+ WSREP_INFO("Recovered position: %s,%d-%d-%llu", oss.str().c_str(), server_gtid.domain_id,
+ server_gtid.server_id, server_gtid.seqno);
+ }
+ else
+ {
+ WSREP_INFO("Recovered position: %s", oss.str().c_str());
+ }
+
}
@@ -988,7 +1061,6 @@ bool wsrep_start_replication()
}
bool const bootstrap(TRUE == wsrep_new_cluster);
- wsrep_new_cluster= FALSE;
WSREP_INFO("Start replication");
@@ -1421,16 +1493,36 @@ 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)
+ /*
+ * Check if this is applier thread, slave_thread or
+ * we have set manually WSREP GTID seqno. Add GTID event.
+ */
+ if (thd->slave_thread || wsrep_thd_is_applying(thd) ||
+ thd->variables.wsrep_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;
+ uint64 seqno= thd->variables.gtid_seq_no;
+ uint32 domain_id= thd->variables.gtid_domain_id;
+ uint32 server_id= thd->variables.server_id;
+ if (!thd->variables.gtid_seq_no && thd->variables.wsrep_gtid_seq_no)
+ {
+ seqno= thd->variables.wsrep_gtid_seq_no;
+ domain_id= wsrep_gtid_server.domain_id;
+ server_id= wsrep_gtid_server.server_id;
+ }
+ Gtid_log_event gtid_event(thd, seqno, domain_id, true,
+ LOG_EVENT_SUPPRESS_USE_F, true, 0);
+ gtid_event.server_id= server_id;
if (!gtid_event.is_valid()) ret= 0;
ret= writer.write(&gtid_event);
}
+ /*
+ It's local DDL so in case of possible gtid seqno (SET gtid_seq_no=X)
+ manipulation, seqno value will be ignored.
+ */
+ else
+ {
+ thd->variables.gtid_seq_no= 0;
+ }
/* if there is prepare query, add event for it */
if (!ret && thd->wsrep_TOI_pre_query)
@@ -1444,6 +1536,9 @@ int wsrep_to_buf_helper(
/* continue to append the actual query */
Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0);
+ /* WSREP GTID mode, we need to change server_id */
+ if (wsrep_gtid_mode && !thd->variables.gtid_seq_no)
+ ev.server_id= wsrep_gtid_server.server_id;
ev.checksum_alg= current_binlog_check_alg;
if (!ret && writer.write(&ev)) ret= 1;
if (!ret && wsrep_write_cache_buf(&tmp_io_cache, buf, buf_len)) ret= 1;
@@ -1923,6 +2018,28 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
rc= -1;
}
else {
+ if (!thd->variables.gtid_seq_no)
+ {
+ uint64 seqno= 0;
+ if (thd->variables.wsrep_gtid_seq_no &&
+ thd->variables.wsrep_gtid_seq_no > wsrep_gtid_server.seqno())
+ {
+ seqno= thd->variables.wsrep_gtid_seq_no;
+ wsrep_gtid_server.seqno(thd->variables.wsrep_gtid_seq_no);
+ }
+ else
+ {
+ seqno= wsrep_gtid_server.seqno_inc();
+ }
+ thd->variables.wsrep_gtid_seq_no= 0;
+ thd->wsrep_current_gtid_seqno= seqno;
+ if (mysql_bin_log.is_open() && wsrep_gtid_mode)
+ {
+ thd->variables.gtid_seq_no= seqno;
+ thd->variables.gtid_domain_id= wsrep_gtid_server.domain_id;
+ thd->variables.server_id= wsrep_gtid_server.server_id;
+ }
+ }
++wsrep_to_isolation;
rc= 0;
}
@@ -1941,15 +2058,22 @@ static void wsrep_TOI_end(THD *thd) {
WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(),
WSREP_QUERY(thd));
+ wsrep_gtid_server.signal_waiters(thd->wsrep_current_gtid_seqno, false);
+
if (wsrep_thd_is_local_toi(thd))
{
- wsrep_set_SE_checkpoint(client_state.toi_meta().gtid());
wsrep::mutable_buffer err;
+
+ thd->wsrep_last_written_gtid_seqno= thd->wsrep_current_gtid_seqno;
+ wsrep_set_SE_checkpoint(client_state.toi_meta().gtid(), wsrep_gtid_server.gtid());
+
if (thd->is_error() && !wsrep_must_ignore_error(thd))
{
- wsrep_store_error(thd, err);
+ wsrep_store_error(thd, err);
}
+
int const ret= client_state.leave_toi_local(err);
+
if (!ret)
{
WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get());
@@ -2642,12 +2766,6 @@ void* start_wsrep_THD(void *arg)
statistic_increment(thread_created, &LOCK_status);
- if (wsrep_gtid_mode)
- {
- /* Adjust domain_id. */
- thd->variables.gtid_domain_id= wsrep_gtid_domain_id;
- }
-
thd->real_id=pthread_self(); // Keep purify happy
my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 497e5f7a086..b3986804770 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -38,6 +38,7 @@ typedef struct st_mysql_show_var SHOW_VAR;
#include "wsrep/streaming_context.hpp"
#include "wsrep_api.h"
#include <vector>
+#include <map>
#include "wsrep_server_state.h"
#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX
@@ -97,7 +98,6 @@ extern ulong wsrep_running_applier_threads;
extern ulong wsrep_running_rollbacker_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
-extern uint32 wsrep_gtid_domain_id;
enum enum_wsrep_reject_types {
WSREP_REJECT_NONE, /* nothing rejected */
@@ -303,6 +303,7 @@ extern mysql_mutex_t LOCK_wsrep_replaying;
extern mysql_cond_t COND_wsrep_replaying;
extern mysql_mutex_t LOCK_wsrep_slave_threads;
extern mysql_cond_t COND_wsrep_slave_threads;
+extern mysql_mutex_t LOCK_wsrep_gtid_wait_upto;
extern mysql_mutex_t LOCK_wsrep_cluster_config;
extern mysql_mutex_t LOCK_wsrep_desync;
extern mysql_mutex_t LOCK_wsrep_SR_pool;
@@ -311,9 +312,6 @@ extern mysql_mutex_t LOCK_wsrep_config_state;
extern mysql_mutex_t LOCK_wsrep_group_commit;
extern my_bool wsrep_emulate_bin_log;
extern int wsrep_to_isolation;
-#ifdef GTID_SUPPORT
-extern rpl_sidno wsrep_sidno;
-#endif /* GTID_SUPPORT */
extern my_bool wsrep_preordered_opt;
#ifdef HAVE_PSI_INTERFACE
@@ -332,6 +330,8 @@ extern PSI_mutex_key key_LOCK_wsrep_replaying;
extern PSI_cond_key key_COND_wsrep_replaying;
extern PSI_mutex_key key_LOCK_wsrep_slave_threads;
extern PSI_cond_key key_COND_wsrep_slave_threads;
+extern PSI_mutex_key key_LOCK_wsrep_gtid_wait_upto;
+extern PSI_cond_key key_COND_wsrep_gtid_wait_upto;
extern PSI_mutex_key key_LOCK_wsrep_cluster_config;
extern PSI_mutex_key key_LOCK_wsrep_desync;
extern PSI_mutex_key key_LOCK_wsrep_SR_pool;
@@ -378,7 +378,122 @@ class Log_event;
int wsrep_ignored_error_code(Log_event* ev, int error);
int wsrep_must_ignore_error(THD* thd);
-bool wsrep_replicate_GTID(THD* thd);
+struct wsrep_server_gtid_t
+{
+ uint32 domain_id;
+ uint32 server_id;
+ uint64 seqno;
+};
+class Wsrep_gtid_server
+{
+public:
+ uint32 domain_id;
+ uint32 server_id;
+ Wsrep_gtid_server()
+ : m_force_signal(false)
+ , m_seqno(0)
+ , m_committed_seqno(0)
+ { }
+ void gtid(const wsrep_server_gtid_t& gtid)
+ {
+ domain_id= gtid.domain_id;
+ server_id= gtid.server_id;
+ m_seqno= gtid.seqno;
+ }
+ wsrep_server_gtid_t gtid()
+ {
+ wsrep_server_gtid_t gtid;
+ gtid.domain_id= domain_id;
+ gtid.server_id= server_id;
+ gtid.seqno= m_seqno;
+ return gtid;
+ }
+ void seqno(const uint64 seqno) { m_seqno= seqno; }
+ uint64 seqno() const { return m_seqno; }
+ uint64 seqno_committed() const { return m_committed_seqno; }
+ uint64 seqno_inc()
+ {
+ m_seqno++;
+ return m_seqno;
+ }
+ const wsrep_server_gtid_t& undefined()
+ {
+ return m_undefined;
+ }
+ int wait_gtid_upto(const uint64_t seqno, uint timeout)
+ {
+ int wait_result;
+ struct timespec wait_time;
+ int ret= 0;
+ mysql_cond_t wait_cond;
+ mysql_cond_init(key_COND_wsrep_gtid_wait_upto, &wait_cond, NULL);
+ set_timespec(wait_time, timeout);
+ mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto);
+ std::multimap<uint64, mysql_cond_t*>::iterator it;
+ try
+ {
+ it= m_wait_map.insert(std::make_pair(seqno, &wait_cond));
+ }
+ catch (std::bad_alloc& e)
+ {
+ return 0;
+ }
+ while ((m_committed_seqno < seqno) && !m_force_signal)
+ {
+ wait_result= mysql_cond_timedwait(&wait_cond,
+ &LOCK_wsrep_gtid_wait_upto,
+ &wait_time);
+ if (wait_result == ETIMEDOUT || wait_result == ETIME)
+ {
+ ret= 1;
+ break;
+ }
+ }
+ m_wait_map.erase(it);
+ mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto);
+ mysql_cond_destroy(&wait_cond);
+ return ret;
+ }
+ void signal_waiters(uint64 seqno, bool signal_all)
+ {
+ if (!signal_all && (m_committed_seqno >= seqno))
+ {
+ return;
+ }
+ mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto);
+ m_force_signal= true;
+ std::multimap<uint64, mysql_cond_t*>::iterator it_end;
+ std::multimap<uint64, mysql_cond_t*>::iterator it_begin;
+ if (signal_all)
+ {
+ it_end= m_wait_map.end();
+ }
+ else
+ {
+ it_end= m_wait_map.upper_bound(seqno);
+ }
+ for (it_begin = m_wait_map.begin(); it_begin != it_end; ++it_begin)
+ {
+ mysql_cond_signal(it_begin->second);
+ }
+ m_force_signal= false;
+ mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto);
+ if (m_committed_seqno < seqno)
+ {
+ m_committed_seqno= seqno;
+ }
+ }
+private:
+ const wsrep_server_gtid_t m_undefined= {0,0,0};
+ std::multimap<uint64, mysql_cond_t*> m_wait_map;
+ bool m_force_signal;
+ Atomic_counter<uint64_t> m_seqno;
+ Atomic_counter<uint64_t> m_committed_seqno;
+};
+extern Wsrep_gtid_server wsrep_gtid_server;
+void wsrep_init_gtid();
+bool wsrep_check_gtid_seqno(const uint32&, const uint32&, uint64&);
+bool wsrep_get_binlog_gtid_seqno(wsrep_server_gtid_t&);
typedef struct wsrep_key_arr
{
diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc
index d0a9b54ac1b..6d737463f07 100644
--- a/sql/wsrep_server_service.cc
+++ b/sql/wsrep_server_service.cc
@@ -153,7 +153,7 @@ void Wsrep_server_service::bootstrap()
wsrep::log_info()
<< "Bootstrapping a new cluster, setting initial position to "
<< wsrep::gtid::undefined();
- wsrep_set_SE_checkpoint(wsrep::gtid::undefined());
+ wsrep_set_SE_checkpoint(wsrep::gtid::undefined(), wsrep_gtid_server.undefined());
}
void Wsrep_server_service::log_message(enum wsrep::log::level level,
@@ -212,7 +212,7 @@ void Wsrep_server_service::log_view(
if (prev_view.state_id().id() != view.state_id().id())
{
WSREP_DEBUG("New cluster UUID was generated, resetting position info");
- wsrep_set_SE_checkpoint(wsrep::gtid::undefined());
+ wsrep_set_SE_checkpoint(wsrep::gtid::undefined(), wsrep_gtid_server.undefined());
checkpoint_was_reset= true;
}
@@ -263,9 +263,9 @@ void Wsrep_server_service::log_view(
Wsrep_server_state::instance().provider().last_committed_gtid().seqno();
if (checkpoint_was_reset || last_committed != view.state_id().seqno())
{
- wsrep_set_SE_checkpoint(view.state_id());
+ wsrep_set_SE_checkpoint(view.state_id(), wsrep_gtid_server.gtid());
}
- DBUG_ASSERT(wsrep_get_SE_checkpoint().id() == view.state_id().id());
+ DBUG_ASSERT(wsrep_get_SE_checkpoint<wsrep::gtid>().id() == view.state_id().id());
}
else
{
@@ -299,13 +299,13 @@ wsrep::view Wsrep_server_service::get_view(wsrep::client_service& c,
wsrep::gtid Wsrep_server_service::get_position(wsrep::client_service&)
{
- return wsrep_get_SE_checkpoint();
+ return wsrep_get_SE_checkpoint<wsrep::gtid>();
}
void Wsrep_server_service::set_position(wsrep::client_service&,
const wsrep::gtid& gtid)
{
- wsrep_set_SE_checkpoint(gtid);
+ wsrep_set_SE_checkpoint(gtid, wsrep_gtid_server.gtid());
}
void Wsrep_server_service::log_state_change(
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 74a8b9dff05..ea526e52515 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -230,8 +230,8 @@ void wsrep_sst_received (THD* thd,
wsrep::seqno(seqno));
if (!wsrep_before_SE()) {
- wsrep_set_SE_checkpoint(wsrep::gtid::undefined());
- wsrep_set_SE_checkpoint(sst_gtid);
+ wsrep_set_SE_checkpoint(wsrep::gtid::undefined(), wsrep_gtid_server.undefined());
+ wsrep_set_SE_checkpoint(sst_gtid, wsrep_gtid_server.gtid());
}
wsrep_verify_SE_checkpoint(uuid, seqno);
@@ -495,7 +495,7 @@ static void* sst_joiner_thread (void* a)
err= EINVAL;
goto err;
} else {
- wsrep_gtid_domain_id= (uint32) domain_id;
+ wsrep_gtid_server.domain_id= (uint32) domain_id;
}
}
}
@@ -1248,13 +1248,15 @@ static int sst_donate_mysqldump (const char* addr,
WSREP_SST_OPT_LPORT " '%u' "
WSREP_SST_OPT_SOCKET " '%s' "
"%s"
- WSREP_SST_OPT_GTID " '%s:%lld' "
+ WSREP_SST_OPT_GTID " '%s:%lld,%d-%d-%llu' "
WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
addr, port, mysqld_port, mysqld_unix_port,
wsrep_defaults_file,
uuid_oss.str().c_str(), gtid.seqno().get(),
- wsrep_gtid_domain_id,
+ wsrep_gtid_server.domain_id, wsrep_gtid_server.server_id,
+ wsrep_gtid_server.seqno(),
+ wsrep_gtid_server.domain_id,
bypass ? " " WSREP_SST_OPT_BYPASS : "");
if (ret < 0 || size_t(ret) >= cmd_len)
@@ -1421,7 +1423,7 @@ static int sst_flush_tables(THD* thd)
*/
char content[100];
snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid,
- (long long)wsrep_locked_seqno, wsrep_gtid_domain_id);
+ (long long)wsrep_locked_seqno, wsrep_gtid_server.domain_id);
err= sst_create_file(flush_success, content);
const char base_name[]= "tables_flushed";
@@ -1446,7 +1448,7 @@ static int sst_flush_tables(THD* thd)
fprintf(file, "%s:%lld %u\n",
uuid_oss.str().c_str(), server_state.pause_seqno().get(),
- wsrep_gtid_domain_id);
+ wsrep_gtid_server.domain_id);
fsync(fileno(file));
fclose(file);
if (rename(tmp_name, real_name) == -1)
@@ -1661,7 +1663,7 @@ static int sst_donate_other (const char* method,
"%s",
method, addr, mysqld_unix_port, mysql_real_data_home,
wsrep_defaults_file,
- uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id,
+ uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_server.domain_id,
binlog_opt_val, binlog_index_opt_val,
bypass ? " " WSREP_SST_OPT_BYPASS : "");
diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h
index b8ce7eb42d0..006d412e6aa 100644
--- a/sql/wsrep_trans_observer.h
+++ b/sql/wsrep_trans_observer.h
@@ -233,7 +233,8 @@ static inline int wsrep_before_prepare(THD* thd, bool all)
{
DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined());
wsrep_xid_init(&thd->wsrep_xid,
- thd->wsrep_trx().ws_meta().gtid());
+ thd->wsrep_trx().ws_meta().gtid(),
+ wsrep_gtid_server.gtid());
}
DBUG_RETURN(ret);
}
@@ -273,8 +274,33 @@ static inline int wsrep_before_commit(THD* thd, bool all)
if ((ret= thd->wsrep_cs().before_commit()) == 0)
{
DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined());
+ if (!thd->variables.gtid_seq_no &&
+ (thd->wsrep_trx().ws_meta().flags() & wsrep::provider::flag::commit))
+ {
+ uint64 seqno= 0;
+ if (thd->variables.wsrep_gtid_seq_no &&
+ thd->variables.wsrep_gtid_seq_no > wsrep_gtid_server.seqno())
+ {
+ seqno= thd->variables.wsrep_gtid_seq_no;
+ wsrep_gtid_server.seqno(thd->variables.wsrep_gtid_seq_no);
+ }
+ else
+ {
+ seqno= wsrep_gtid_server.seqno_inc();
+ }
+ thd->variables.wsrep_gtid_seq_no= 0;
+ thd->wsrep_current_gtid_seqno= seqno;
+ if (mysql_bin_log.is_open() && wsrep_gtid_mode)
+ {
+ thd->variables.gtid_seq_no= seqno;
+ thd->variables.gtid_domain_id= wsrep_gtid_server.domain_id;
+ thd->variables.server_id= wsrep_gtid_server.server_id;
+ }
+ }
+
wsrep_xid_init(&thd->wsrep_xid,
- thd->wsrep_trx().ws_meta().gtid());
+ thd->wsrep_trx().ws_meta().gtid(),
+ wsrep_gtid_server.gtid());
wsrep_register_for_group_commit(thd);
}
DBUG_RETURN(ret);
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 5f76f650b34..daf12f94fb9 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -37,7 +37,10 @@ int wsrep_init_vars()
wsrep_node_name = my_strdup("", MYF(MY_WME));
wsrep_node_address = my_strdup("", MYF(MY_WME));
wsrep_node_incoming_address= my_strdup(WSREP_NODE_INCOMING_AUTO, MYF(MY_WME));
- wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME));
+ if (wsrep_gtid_mode)
+ wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO_GTID, MYF(MY_WME));
+ else
+ wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME));
return 0;
}
@@ -103,6 +106,13 @@ bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type)
return false;
}
+template<typename T>
+static T parse_value(char** startptr, char** endptr)
+{
+ T val= strtoll(*startptr, *&endptr, 10);
+ *startptr= *endptr;
+ return val;
+}
/*
Verify the format of the given UUID:seqno.
@@ -136,8 +146,25 @@ bool wsrep_start_position_verify (const char* start_str)
return true;
char* endptr;
+ char* startptr= (char *)start_str + uuid_len + 1;
wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings
- (strtoll(&start_str[uuid_len + 1], &endptr, 10));
+ (parse_value<uint64_t>(&startptr, &endptr));
+
+ // Start parsing native GTID part
+ if (*startptr == ',')
+ {
+ startptr++;
+ uint32_t domain __attribute__((unused))
+ (parse_value<uint32_t>(&startptr, &endptr));
+ if (*endptr != '-') return true;
+ startptr++;
+ uint32_t server __attribute__((unused))
+ (parse_value<uint32_t>(&startptr, &endptr));
+ if (*endptr != '-') return true;
+ startptr++;
+ uint64_t seq __attribute__((unused))
+ (parse_value<uint64_t>(&startptr, &endptr));
+ }
// Remaining string was seqno.
if (*endptr == '\0') return false;
@@ -150,9 +177,22 @@ static
bool wsrep_set_local_position(THD* thd, const char* const value,
size_t length, bool const sst)
{
+ char* endptr;
+ char* startptr;
wsrep_uuid_t uuid;
size_t const uuid_len= wsrep_uuid_scan(value, length, &uuid);
- wsrep_seqno_t const seqno= strtoll(value + uuid_len + 1, NULL, 10);
+ startptr= (char *)value + uuid_len + 1;
+ wsrep_seqno_t const seqno= parse_value<uint64_t>(&startptr, &endptr);
+
+ if (*startptr == ',')
+ {
+ startptr++;
+ wsrep_gtid_server.domain_id= parse_value<uint32_t>(&startptr, &endptr);
+ startptr++;
+ wsrep_gtid_server.server_id= parse_value<uint32_t>(&startptr, &endptr);
+ startptr++;
+ wsrep_gtid_server.seqno(parse_value<uint64_t>(&startptr, &endptr));
+ }
if (sst) {
wsrep_sst_received (thd, uuid, seqno, NULL, 0);
@@ -436,6 +476,15 @@ bool wsrep_debug_update(sys_var *self, THD* thd, enum_var_type type)
return false;
}
+bool
+wsrep_gtid_seq_no_check(sys_var *self, THD *thd, set_var *var)
+{
+ ulonglong new_wsrep_gtid_seq_no= var->save_result.ulonglong_value;
+ if (wsrep_gtid_mode && new_wsrep_gtid_seq_no > wsrep_gtid_server.seqno())
+ return false;
+ return true;
+}
+
static int wsrep_cluster_address_verify (const char* cluster_address_str)
{
/* There is no predefined address format, it depends on provider. */
diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h
index 481df02f2d5..810ed4f3dd7 100644
--- a/sql/wsrep_var.h
+++ b/sql/wsrep_var.h
@@ -20,9 +20,10 @@
#ifdef WITH_WSREP
-#define WSREP_CLUSTER_NAME "my_wsrep_cluster"
-#define WSREP_NODE_INCOMING_AUTO "AUTO"
-#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1"
+#define WSREP_CLUSTER_NAME "my_wsrep_cluster"
+#define WSREP_NODE_INCOMING_AUTO "AUTO"
+#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1"
+#define WSREP_START_POSITION_ZERO_GTID "00000000-0000-0000-0000-000000000000:-1,0-0-0"
// MySQL variables funcs
@@ -102,6 +103,8 @@ extern bool wsrep_reject_queries_update UPDATE_ARGS;
extern bool wsrep_debug_update UPDATE_ARGS;
+extern bool wsrep_gtid_seq_no_check CHECK_ARGS;
+
#else /* WITH_WSREP */
#define wsrep_provider_init(X)
diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc
index d8f6e013820..c84071e13d0 100644
--- a/sql/wsrep_xid.cc
+++ b/sql/wsrep_xid.cc
@@ -33,20 +33,24 @@
#define WSREP_XID_VERSION_OFFSET WSREP_XID_PREFIX_LEN
#define WSREP_XID_VERSION_1 'd'
#define WSREP_XID_VERSION_2 'e'
+#define WSREP_XID_VERSION_3 'f'
#define WSREP_XID_UUID_OFFSET 8
#define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t))
-#define WSREP_XID_GTRID_LEN (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
+#define WSREP_XID_GTRID_LEN_V_1_2 (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
+#define WSREP_XID_RPL_GTID_OFFSET (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
+#define WSREP_XID_GTRID_LEN_V_3 (WSREP_XID_RPL_GTID_OFFSET + sizeof(wsrep_server_gtid_t))
-void wsrep_xid_init(XID* xid, const wsrep::gtid& wsgtid)
+void wsrep_xid_init(XID* xid, const wsrep::gtid& wsgtid, const wsrep_server_gtid_t& gtid)
{
xid->formatID= 1;
- xid->gtrid_length= WSREP_XID_GTRID_LEN;
+ xid->gtrid_length= WSREP_XID_GTRID_LEN_V_3;
xid->bqual_length= 0;
memset(xid->data, 0, sizeof(xid->data));
memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN);
- xid->data[WSREP_XID_VERSION_OFFSET]= WSREP_XID_VERSION_2;
+ xid->data[WSREP_XID_VERSION_OFFSET]= WSREP_XID_VERSION_3;
memcpy(xid->data + WSREP_XID_UUID_OFFSET, wsgtid.id().data(),sizeof(wsrep::id));
int8store(xid->data + WSREP_XID_SEQNO_OFFSET, wsgtid.seqno().get());
+ memcpy(xid->data + WSREP_XID_RPL_GTID_OFFSET, &gtid, sizeof(wsrep_server_gtid_t));
}
extern "C"
@@ -54,11 +58,13 @@ int wsrep_is_wsrep_xid(const void* xid_ptr)
{
const XID* xid= static_cast<const XID*>(xid_ptr);
return (xid->formatID == 1 &&
- xid->gtrid_length == WSREP_XID_GTRID_LEN &&
xid->bqual_length == 0 &&
- !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN) &&
- (xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_1 ||
- xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2));
+ !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN) &&
+ (((xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_1 ||
+ xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2) &&
+ xid->gtrid_length == WSREP_XID_GTRID_LEN_V_1_2) ||
+ (xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_3 &&
+ xid->gtrid_length == WSREP_XID_GTRID_LEN_V_3)));
}
const unsigned char* wsrep_xid_uuid(const xid_t* xid)
@@ -90,6 +96,7 @@ long long wsrep_xid_seqno(const xid_t* xid)
memcpy(&ret, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof ret);
break;
case WSREP_XID_VERSION_2:
+ case WSREP_XID_VERSION_3:
ret= sint8korr(xid->data + WSREP_XID_SEQNO_OFFSET);
break;
default:
@@ -127,10 +134,10 @@ bool wsrep_set_SE_checkpoint(XID& xid)
&xid);
}
-bool wsrep_set_SE_checkpoint(const wsrep::gtid& wsgtid)
+bool wsrep_set_SE_checkpoint(const wsrep::gtid& wsgtid, const wsrep_server_gtid_t& gtid)
{
XID xid;
- wsrep_xid_init(&xid, wsgtid);
+ wsrep_xid_init(&xid, wsgtid, gtid);
return wsrep_set_SE_checkpoint(xid);
}
@@ -158,30 +165,61 @@ bool wsrep_get_SE_checkpoint(XID& xid)
&xid);
}
-wsrep::gtid wsrep_get_SE_checkpoint()
+static bool wsrep_get_SE_checkpoint_common(XID& xid)
{
- XID xid;
xid.null();
if (wsrep_get_SE_checkpoint(xid))
{
- return wsrep::gtid();
+ return FALSE;
}
if (xid.is_null())
{
- return wsrep::gtid();
+ return FALSE;
}
if (!wsrep_is_wsrep_xid(&xid))
{
WSREP_WARN("Read non-wsrep XID from storage engines.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+template<>
+wsrep::gtid wsrep_get_SE_checkpoint()
+{
+ XID xid;
+
+ if (!wsrep_get_SE_checkpoint_common(xid))
+ {
return wsrep::gtid();
}
return wsrep::gtid(wsrep_xid_uuid(xid),wsrep_xid_seqno(xid));
}
+template<>
+wsrep_server_gtid_t wsrep_get_SE_checkpoint()
+{
+ XID xid;
+ wsrep_server_gtid_t gtid= {0,0,0};
+
+ if (!wsrep_get_SE_checkpoint_common(xid))
+ {
+ return gtid;
+ }
+
+ if (xid.data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_3)
+ {
+ memcpy(&gtid, &xid.data[WSREP_XID_RPL_GTID_OFFSET], sizeof(wsrep_server_gtid_t));
+ }
+
+ return gtid;
+}
+
/*
Sort order for XIDs. Wsrep XIDs are sorted according to
seqno in ascending order. Non-wsrep XIDs are considered
diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h
index a1b9afc1817..45ba6ffee6b 100644
--- a/sql/wsrep_xid.h
+++ b/sql/wsrep_xid.h
@@ -20,15 +20,16 @@
#ifdef WITH_WSREP
+#include "wsrep_mysqld.h"
#include "wsrep/gtid.hpp"
#include "handler.h" // XID typedef
-void wsrep_xid_init(xid_t*, const wsrep::gtid&);
+void wsrep_xid_init(xid_t*, const wsrep::gtid&, const wsrep_server_gtid_t&);
const wsrep::id& wsrep_xid_uuid(const XID&);
wsrep::seqno wsrep_xid_seqno(const XID&);
-wsrep::gtid wsrep_get_SE_checkpoint();
-bool wsrep_set_SE_checkpoint(const wsrep::gtid& gtid);
+template<typename T> T wsrep_get_SE_checkpoint();
+bool wsrep_set_SE_checkpoint(const wsrep::gtid& gtid, const wsrep_server_gtid_t&);
//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */
//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */