17 Oct '18
revision-id: 2432c973aea5b4e2d2d831b71c8b26f40d90205b (mariadb-10.3.6-161-g2432c97)
parent(s): a53b99bf1333722b8f30fdbba7d7a40ce2485976
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-10-17 01:27:25 -0700
message:
MDEV-17027 server crashes in Bitmap<64u>::merge
The function and_new_conditions_to_optimized_cond() incorrectly handled
the WHERE conditions with one multiple equality and one IN subquery predicate
that could be converted into a jtbm semi-join. This could cause crashes.
The fix code was prepared by Galina Shalygina.
---
mysql-test/main/in_subq_cond_pushdown.result | 19 ++++++++++++
mysql-test/main/in_subq_cond_pushdown.test | 22 ++++++++++++++
sql/opt_subselect.cc | 44 ++++++++++++++--------------
3 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result
index 077edf7..0624889 100644
--- a/mysql-test/main/in_subq_cond_pushdown.result
+++ b/mysql-test/main/in_subq_cond_pushdown.result
@@ -3868,3 +3868,22 @@ WHERE dt1.id1 IN (SELECT t2.id2 FROM t2
HAVING t2.id2 >= 1));
r
DROP TABLE t1,t2;
+#
+# MDEV-17027: IN subquery predicate with outer reference in the left part
+# conjuncted with equality predicate
+#
+CREATE TABLE t1 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t1 VALUES (3,2,'x'), (1,1,'y'), (4,2,'z');
+CREATE TABLE t2 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t2 VALUES (5,2,'x'), (7,1,'x');
+CREATE TABLE t3 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t3 VALUES (8,2,'x'), (7,1,'z');
+SELECT t3.i1 FROM t3
+WHERE EXISTS ( SELECT t2.v1 FROM t1,t2
+WHERE t1.v1 = t2.v1 AND
+t3.i1 IN (SELECT t.i1 FROM t1 as t
+GROUP BY i1 HAVING t.i1 < 3));
+i1
+2
+1
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/main/in_subq_cond_pushdown.test b/mysql-test/main/in_subq_cond_pushdown.test
index 4c0dd3d..2482fd9 100644
--- a/mysql-test/main/in_subq_cond_pushdown.test
+++ b/mysql-test/main/in_subq_cond_pushdown.test
@@ -838,3 +838,25 @@ SELECT 1 AS r FROM t2,t1,(SELECT * FROM t1) dt1
HAVING t2.id2 >= 1));
DROP TABLE t1,t2;
+
+--echo #
+--echo # MDEV-17027: IN subquery predicate with outer reference in the left part
+--echo # conjuncted with equality predicate
+--echo #
+
+CREATE TABLE t1 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t1 VALUES (3,2,'x'), (1,1,'y'), (4,2,'z');
+
+CREATE TABLE t2 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t2 VALUES (5,2,'x'), (7,1,'x');
+
+CREATE TABLE t3 (pk int, i1 int, v1 varchar(1));
+INSERT INTO t3 VALUES (8,2,'x'), (7,1,'z');
+
+SELECT t3.i1 FROM t3
+ WHERE EXISTS ( SELECT t2.v1 FROM t1,t2
+ WHERE t1.v1 = t2.v1 AND
+ t3.i1 IN (SELECT t.i1 FROM t1 as t
+ GROUP BY i1 HAVING t.i1 < 3));
+
+DROP TABLE t1,t2,t3;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 4eeaefa..c4c30c9 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5667,31 +5667,31 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
}
}
+ if (is_mult_eq)
+ {
+ Item_equal *eq_cond= (Item_equal *)cond;
+ eq_cond->upper_levels= 0;
+ eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
+ false, false);
+
+ while ((equality= it++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ is_simplified_cond= true;
+ }
+ (*cond_eq)->copy(new_cond_equal);
+ }
+
if (new_cond_equal.current_level.elements > 0)
{
- if (is_mult_eq)
+ if (new_cond_equal.current_level.elements +
+ new_conds_list.elements == 1)
{
- Item_equal *eq_cond= (Item_equal *)cond;
- eq_cond->upper_levels= 0;
- eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
- false, false);
-
- while ((equality= it++))
- {
- if (equality->const_item() && !equality->val_int())
- is_simplified_cond= true;
- }
-
- if (new_cond_equal.current_level.elements +
- new_conds_list.elements == 1)
- {
- it.rewind();
- equality= it++;
- equality->fixed= 0;
- if (equality->fix_fields(thd, NULL))
- return NULL;
- }
- (*cond_eq)->copy(new_cond_equal);
+ it.rewind();
+ equality= it++;
+ equality->fixed= 0;
+ if (equality->fix_fields(thd, NULL))
+ return NULL;
}
new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
}
1
0
[Commits] 737de39: Issue #885: Can't locate lib/mtr_process.pl in @INC on Ubuntu 18.04.1
by psergey@askmonty.org 15 Oct '18
by psergey@askmonty.org 15 Oct '18
15 Oct '18
revision-id: 737de3973373eb1a10ad81eadfb92286c7534e57
parent(s): c036201540e8c99b92f1c8ecdba13def31edd7d1
committer: Sergei Petrunia
branch nick: mysql-5.6-rocksdb-spetrunia
timestamp: 2018-10-15 18:17:43 +0300
message:
Issue #885: Can't locate lib/mtr_process.pl in @INC on Ubuntu 18.04.1
Add "." to @INC array like upstream does.
---
mysql-test/mysql-test-run.pl | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 38e2180..3a90cfe 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -101,6 +101,8 @@ use mtr_results;
use IO::Socket::INET;
use IO::Select;
+push @INC, ".";
+
require "lib/mtr_process.pl";
require "lib/mtr_io.pl";
require "lib/mtr_gcov.pl";
1
0
[Commits] a97c190d95b: MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling
by andrei.elkin@pp.inet.fi 15 Oct '18
by andrei.elkin@pp.inet.fi 15 Oct '18
15 Oct '18
revision-id: a97c190d95bc9f3be0c0fa75abe56422927e7d82 (mariadb-10.3.7-98-ga97c190d95b)
parent(s): 93b6552182740d1a66cf41c30811e7275d31b07f
author: Andrei Elkin
committer: Andrei Elkin
timestamp: 2018-07-26 10:54:13 +0300
message:
MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling
When the semisync slave is being stopped with STOP SLAVE just after
the master was shut down it attempts to reconnect with the master
anyway per a semisync routine. Instead of an expected error the
io-thread segfauls in mysql_real_connect() execution at
!mysql->options.extension->async_context
check trying to reach the extension's member while mysql->options.extension is
actually and correctly NULL.
Apparently not-NULL check for mysql->options.extension was missed and
it's deployed by the patch to fix this issue.
As a bonus it also tackles an assert
Thread 0x7f16c72148c0 (LWP 24639) 0x00007f16c53b3bf2 in __GI___assert_fail (assertion=0x55a686117558 "global_status_var.global_memory_used == 0", file=0x55a6861171e8 "/home/andrei/MDB/WTs/10.3-clean/sql/mysqld.cc", line=2201, function=0x55a68611fa80 <mysqld_exit(int)::__PRETTY_FUNCTION__> "void mysqld_exit(int)") at assert.c:101
in a new test of the patch. The reason of the assert was insufficient cleanup
in Repl_semi_sync_slave::kill_connection() which has a branch where a MYSQL instance
was left out unfred.
---
.../rpl/r/rpl_semi_sync_master_shutdown.result | 33 ++++++++++++
.../suite/rpl/t/rpl_semi_sync_master_shutdown.test | 60 ++++++++++++++++++++++
sql-common/client.c | 2 +-
sql/semisync_slave.cc | 3 +-
4 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result
new file mode 100644
index 00000000000..786e1682bb0
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result
@@ -0,0 +1,33 @@
+include/master-slave.inc
+[connection master]
+connection master;
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+connection slave;
+include/stop_slave.inc
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+include/start_slave.inc
+connection master;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a=1;
+connection slave;
+connection master;
+# Shutdown master
+include/rpl_stop_server.inc [server_number=1]
+connection slave;
+include/stop_slave.inc
+# Restart master
+include/rpl_start_server.inc [server_number=1]
+connection slave;
+include/stop_slave.inc
+Warnings:
+Note 1255 Slave already has been stopped
+include/start_slave.inc
+connection master;
+SET @@GLOBAL.debug_dbug="";
+SET @@GLOBAL. rpl_semi_sync_master_enabled = 0;
+connection master;
+DROP TABLE t1;
+connection slave;
+include/stop_slave.inc
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 0;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test
new file mode 100644
index 00000000000..2224f78d6d0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test
@@ -0,0 +1,60 @@
+# MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling
+#
+# The test verifies that the semisync-enabled slave io thread
+# finishes off as specified in particular trying to connect even to a shut down
+# master for a semisync firewell routine.
+
+source include/not_embedded.inc;
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+--connection master
+
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled `
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--connection slave
+source include/stop_slave.inc;
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled `
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a=1;
+
+--sync_slave_with_master
+
+connection master;
+--echo # Shutdown master
+--let $rpl_server_number=1
+source include/rpl_stop_server.inc;
+
+--connection slave
+--source include/stop_slave.inc
+
+#connection master;
+--echo # Restart master
+--let $rpl_server_number=1
+source include/rpl_start_server.inc;
+
+#
+# Clean up
+#
+--connection slave
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+--connection master
+SET @@GLOBAL.debug_dbug="";
+--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--connection master
+DROP TABLE t1;
+
+--sync_slave_with_master
+source include/stop_slave.inc;
+--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/sql-common/client.c b/sql-common/client.c
index 088377f8c52..8bbe08a504a 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -3657,7 +3657,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
end_server(mysql);
mysql_close_free(mysql);
if (!(client_flag & CLIENT_REMEMBER_OPTIONS) &&
- !mysql->options.extension->async_context)
+ !(mysql->options.extension && mysql->options.extension->async_context))
mysql_close_free_options(mysql);
}
DBUG_RETURN(0);
diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc
index 86d0176dac1..df8baf045ac 100644
--- a/sql/semisync_slave.cc
+++ b/sql/semisync_slave.cc
@@ -144,8 +144,7 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql)
{
sql_print_information("cannot connect to master to kill slave io_thread's "
"connection");
- if (!ret)
- mysql_close(kill_mysql);
+ mysql_close(kill_mysql);
return;
}
size_t kill_buffer_length = my_snprintf(kill_buffer, 30, "KILL %lu",
1
0
[Commits] ca3254b: MDEV-17222 Reproducible server crash in String_list::append_str or
by IgorBabaev 14 Oct '18
by IgorBabaev 14 Oct '18
14 Oct '18
revision-id: ca3254b90e23d0c33fafda5be181051a0c7f28ff (mariadb-10.3.10-23-gca3254b)
parent(s): 2fd770641ecb476038576cdf3e8829599633292e
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-10-14 15:20:25 -0700
message:
MDEV-17222 Reproducible server crash in String_list::append_str or
in Field_iterator_table::create_item
When IN predicate is converted to IN subquery we have to ensure that
any item from the select list of the subquery has some name and this name
is unique across the select list.
This was not guaranteed by the code before the patch for MDEV-17222.
If the name of an item of the select list was not set, and this happened
for binary constants, then the server crashed. If the first row in the IN
list contained the same constant in two different positions then the server
returned an error message.
This was fixed by providing all constants in the first row of the IN list
with generated names.
---
mysql-test/main/opt_tvc.result | 67 +++++++++++++++++++++++++++++++-----------
mysql-test/main/opt_tvc.test | 40 +++++++++++++++++++++++--
sql/sql_tvc.cc | 19 ++++++++++--
3 files changed, 105 insertions(+), 21 deletions(-)
diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result
index fdbd932..d503dab 100644
--- a/mysql-test/main/opt_tvc.result
+++ b/mysql-test/main/opt_tvc.result
@@ -51,7 +51,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
explain extended select * from t1
where a in
(
@@ -98,7 +98,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`_col_1`
explain extended select * from t1
where a in
(
@@ -154,7 +154,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`_col_1`
explain extended select * from t1
where a in
(
@@ -211,7 +211,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
explain extended select * from
(
select *
@@ -270,7 +270,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
explain extended select * from
(
select *
@@ -321,7 +321,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
explain extended select * from v2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
@@ -386,7 +386,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`_col_1`
explain extended select * from t1
where a in
(
@@ -507,11 +507,11 @@ a b
explain extended select * from t3 where a in (1,4);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t3 ref idx idx 5 tvc_0.1 3 100.00
+1 PRIMARY t3 ref idx idx 5 tvc_0._col_1 3 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`_col_1`
# use vectors in IN predeicate
set @@in_predicate_conversion_threshold= 4;
select * from t1 where (a,b) in ((1,2),(3,4));
@@ -524,7 +524,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` and `test`.`t1`.`b` = `tvc_0`.`2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` and `test`.`t1`.`b` = `tvc_0`.`_col_2`
set @@in_predicate_conversion_threshold= 2;
# trasformation works for the one IN predicate and doesn't work for the other
set @@in_predicate_conversion_threshold= 5;
@@ -543,7 +543,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`1` and `test`.`t2`.`c` = `tvc_0`.`3` and (`tvc_0`.`1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`_col_1` and `test`.`t2`.`c` = `tvc_0`.`_col_2` and (`tvc_0`.`_col_1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
set @@in_predicate_conversion_threshold= 2;
#
# mdev-14281: conversion of NOT IN predicate into subquery predicate
@@ -571,7 +571,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( <materialize> (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`1` and `test`.`t1`.`b` = `<subquery2>`.`2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( <materialize> (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`_col_1` and `test`.`t1`.`b` = `<subquery2>`.`_col_2`))))
explain extended select * from t1
where (a,b) not in (select * from (values (1,2),(8,9), (5,1)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -593,7 +593,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` < 7 and !<expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( <materialize> (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`1` and `test`.`t1`.`b` = `<subquery2>`.`2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` < 7 and !<expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( <materialize> (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`_col_1` and `test`.`t1`.`b` = `<subquery2>`.`_col_2`))))
select * from t2
where (a,c) not in ((1,2),(8,9), (5,1));
a b c
@@ -609,11 +609,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`c`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`c`),(`test`.`t2`.`a`,`test`.`t2`.`c`) in ( <materialize> (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`1` and `test`.`t2`.`c` = `<subquery2>`.`2`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`c`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`c`),(`test`.`t2`.`a`,`test`.`t2`.`c`) in ( <materialize> (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`_col_1` and `test`.`t2`.`c` = `<subquery2>`.`_col_2`))))
drop table t1, t2, t3;
set @@in_predicate_conversion_threshold= default;
#
-# MDEV-14947: conversion of TVC with only NULL values
+# MDEV-14947: conversion to TVC with only NULL values
#
CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (3), (2), (7);
@@ -633,11 +633,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join ((values (NULL),(NULL),(NULL),(NULL),(NULL)) `tvc_0`) where `test`.`t1`.`i` = `tvc_0`.`NULL`
+Note 1003 /* select#1 */ select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join ((values (NULL),(NULL),(NULL),(NULL),(NULL)) `tvc_0`) where `test`.`t1`.`i` = `tvc_0`.`_col_1`
SET in_predicate_conversion_threshold= default;
DROP TABLE t1;
#
-# MDEV-14835: conversion of TVC with BIGINT or YEAR values
+# MDEV-14835: conversion to TVC with BIGINT or YEAR values
#
SET @@in_predicate_conversion_threshold= 2;
CREATE TABLE t1 (a BIGINT);
@@ -654,3 +654,36 @@ y
2011
DROP TABLE t1,t2;
SET @@in_predicate_conversion_threshold= default;
+#
+# MDEV-17222: conversion to TVC with no names for constants
+# conversion to TVC with the same constants in the first row
+#
+SET @@in_predicate_conversion_threshold= 2;
+CREATE TABLE t1 (f BINARY(16)) ENGINE=MYISAM;
+INSERT INTO t1 VALUES
+(x'BAE56AF2B1C2397D99D58E2A06761DDB'), (x'9B9B698BCCB939EE8F1EA56C1A2E5DAA'),
+(x'A0A1C4FE39A239BABD3E0D8985E6BEA5');
+SELECT COUNT(*) FROM t1 WHERE f IN
+(x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2',
+x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB');
+COUNT(*)
+2
+CREATE TABLE t2 (f1 BINARY(16), f2 BINARY(16)) ENGINE=MYISAM;
+INSERT INTO t2 VALUES
+(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'),
+(x'86052C062AAF368D84247ED0F6346A70', x'BF5C35045C6037C79E11026ABB9A3A4E');
+SELECT COUNT(*) FROM t2 WHERE (f1,f2) IN
+((x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2'),
+(x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'),
+(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'),
+(x'1606014E7C4A312F83EDC9D91BBFCACA', x'33F6068E56FD3A1D8326517F0D81CB5A'));
+COUNT(*)
+1
+CREATE TABLE t3 (f1 int, f2 int) ENGINE=MYISAM;
+INSERT INTO t3 VALUES (2,5), (2,3), (1,2), (7,8), (1,1);
+SELECT * FROM t3 WHERE (f1,f2) IN ((2, 2), (1, 2), (3, 5), (1, 1));
+f1 f2
+1 2
+1 1
+DROP TABLE t1,t2,t3;
+SET @@in_predicate_conversion_threshold= default;
diff --git a/mysql-test/main/opt_tvc.test b/mysql-test/main/opt_tvc.test
index 2d06a0a..733ee07 100644
--- a/mysql-test/main/opt_tvc.test
+++ b/mysql-test/main/opt_tvc.test
@@ -320,7 +320,7 @@ drop table t1, t2, t3;
set @@in_predicate_conversion_threshold= default;
--echo #
---echo # MDEV-14947: conversion of TVC with only NULL values
+--echo # MDEV-14947: conversion to TVC with only NULL values
--echo #
CREATE TABLE t1 (i INT);
@@ -342,7 +342,7 @@ SET in_predicate_conversion_threshold= default;
DROP TABLE t1;
--echo #
---echo # MDEV-14835: conversion of TVC with BIGINT or YEAR values
+--echo # MDEV-14835: conversion to TVC with BIGINT or YEAR values
--echo #
SET @@in_predicate_conversion_threshold= 2;
@@ -360,3 +360,39 @@ SELECT * FROM t2 WHERE y IN ('2009','2011');
DROP TABLE t1,t2;
SET @@in_predicate_conversion_threshold= default;
+
+--echo #
+--echo # MDEV-17222: conversion to TVC with no names for constants
+--echo # conversion to TVC with the same constants in the first row
+--echo #
+
+SET @@in_predicate_conversion_threshold= 2;
+
+CREATE TABLE t1 (f BINARY(16)) ENGINE=MYISAM;
+INSERT INTO t1 VALUES
+(x'BAE56AF2B1C2397D99D58E2A06761DDB'), (x'9B9B698BCCB939EE8F1EA56C1A2E5DAA'),
+(x'A0A1C4FE39A239BABD3E0D8985E6BEA5');
+
+SELECT COUNT(*) FROM t1 WHERE f IN
+(x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2',
+ x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB');
+
+CREATE TABLE t2 (f1 BINARY(16), f2 BINARY(16)) ENGINE=MYISAM;
+INSERT INTO t2 VALUES
+(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'),
+(x'86052C062AAF368D84247ED0F6346A70', x'BF5C35045C6037C79E11026ABB9A3A4E');
+
+SELECT COUNT(*) FROM t2 WHERE (f1,f2) IN
+((x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2'),
+ (x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'),
+ (x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'),
+ (x'1606014E7C4A312F83EDC9D91BBFCACA', x'33F6068E56FD3A1D8326517F0D81CB5A'));
+
+CREATE TABLE t3 (f1 int, f2 int) ENGINE=MYISAM;
+INSERT INTO t3 VALUES (2,5), (2,3), (1,2), (7,8), (1,1);
+
+SELECT * FROM t3 WHERE (f1,f2) IN ((2, 2), (1, 2), (3, 5), (1, 1));
+
+DROP TABLE t1,t2,t3;
+
+SET @@in_predicate_conversion_threshold= default;
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index 188ba8c..a5085fd 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -470,6 +470,7 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd,
for (uint i=1; i < arg_count; i++)
{
+ char col_name[8];
List<Item> *tvc_value;
if (!(tvc_value= new (thd->mem_root) List<Item>()))
return true;
@@ -480,13 +481,27 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd,
for (uint j=0; j < row_list->cols(); j++)
{
+ if (i == 1)
+ {
+ sprintf(col_name, "_col_%i", j+1);
+ row_list->element_index(j)->set_name(thd, col_name, strlen(col_name),
+ thd->charset());
+ }
if (tvc_value->push_back(row_list->element_index(j),
thd->mem_root))
return true;
}
}
- else if (tvc_value->push_back(args[i]->real_item()))
- return true;
+ else
+ {
+ if (i == 1)
+ {
+ sprintf(col_name, "_col_%i", 1);
+ args[i]->set_name(thd, col_name, strlen(col_name), thd->charset());
+ }
+ if (tvc_value->push_back(args[i]->real_item()))
+ return true;
+ }
if (values->push_back(tvc_value, thd->mem_root))
return true;
1
0
[Commits] 0445203d: Merge remote-tracking branch 'galera-bugs/4.x' into mariadb-4.x
by jan 13 Oct '18
by jan 13 Oct '18
13 Oct '18
revision-id: 0445203d134526d7129ffdb05719933fd01edc71 (mariadb-25.3.19-8-g0445203d)
parent(s): 6bd3eb12e1f6bf9001cf7975f87d58d996580b53 1d7a57b01490b43f3a32dd4b423883e8821727b5
author: Jan Lindström
committer: Jan Lindström
timestamp: 2018-10-13 17:34:00 +0300
message:
Merge remote-tracking branch 'galera-bugs/4.x' into mariadb-4.x
.gitignore | 5 +-
.gitmodules | 4 +
SConstruct | 52 +-
asio/asio.hpp | 2 +-
asio/asio/async_result.hpp | 2 +-
asio/asio/basic_datagram_socket.hpp | 2 +-
asio/asio/basic_deadline_timer.hpp | 2 +-
asio/asio/basic_io_object.hpp | 9 +-
asio/asio/basic_raw_socket.hpp | 2 +-
asio/asio/basic_seq_packet_socket.hpp | 2 +-
asio/asio/basic_serial_port.hpp | 4 +-
asio/asio/basic_signal_set.hpp | 2 +-
asio/asio/basic_socket.hpp | 2 +-
asio/asio/basic_socket_acceptor.hpp | 2 +-
asio/asio/basic_socket_iostream.hpp | 2 +-
asio/asio/basic_socket_streambuf.hpp | 2 +-
asio/asio/basic_stream_socket.hpp | 2 +-
asio/asio/basic_streambuf.hpp | 2 +-
asio/asio/basic_streambuf_fwd.hpp | 2 +-
asio/asio/basic_waitable_timer.hpp | 2 +-
asio/asio/buffer.hpp | 2 +-
asio/asio/buffered_read_stream.hpp | 2 +-
asio/asio/buffered_read_stream_fwd.hpp | 2 +-
asio/asio/buffered_stream.hpp | 2 +-
asio/asio/buffered_stream_fwd.hpp | 2 +-
asio/asio/buffered_write_stream.hpp | 2 +-
asio/asio/buffered_write_stream_fwd.hpp | 2 +-
asio/asio/buffers_iterator.hpp | 2 +-
asio/asio/completion_condition.hpp | 2 +-
asio/asio/connect.hpp | 2 +-
asio/asio/coroutine.hpp | 2 +-
asio/asio/datagram_socket_service.hpp | 2 +-
asio/asio/deadline_timer.hpp | 2 +-
asio/asio/deadline_timer_service.hpp | 2 +-
asio/asio/detail/addressof.hpp | 2 +-
asio/asio/detail/array.hpp | 2 +-
asio/asio/detail/array_fwd.hpp | 2 +-
asio/asio/detail/assert.hpp | 2 +-
asio/asio/detail/atomic_count.hpp | 2 +-
asio/asio/detail/base_from_completion_cond.hpp | 2 +-
asio/asio/detail/bind_handler.hpp | 2 +-
asio/asio/detail/buffer_resize_guard.hpp | 2 +-
asio/asio/detail/buffer_sequence_adapter.hpp | 2 +-
asio/asio/detail/buffered_stream_storage.hpp | 2 +-
asio/asio/detail/call_stack.hpp | 2 +-
asio/asio/detail/chrono_time_traits.hpp | 2 +-
asio/asio/detail/completion_handler.hpp | 2 +-
asio/asio/detail/config.hpp | 67 +-
asio/asio/detail/consuming_buffers.hpp | 2 +-
asio/asio/detail/cstdint.hpp | 2 +-
asio/asio/detail/date_time_fwd.hpp | 2 +-
asio/asio/detail/deadline_timer_service.hpp | 2 +-
asio/asio/detail/dependent_type.hpp | 2 +-
asio/asio/detail/descriptor_ops.hpp | 2 +-
asio/asio/detail/descriptor_read_op.hpp | 2 +-
asio/asio/detail/descriptor_write_op.hpp | 2 +-
asio/asio/detail/dev_poll_reactor.hpp | 2 +-
asio/asio/detail/epoll_reactor.hpp | 2 +-
asio/asio/detail/event.hpp | 2 +-
asio/asio/detail/eventfd_select_interrupter.hpp | 2 +-
asio/asio/detail/fd_set_adapter.hpp | 2 +-
asio/asio/detail/fenced_block.hpp | 2 +-
asio/asio/detail/function.hpp | 2 +-
asio/asio/detail/gcc_arm_fenced_block.hpp | 2 +-
asio/asio/detail/gcc_hppa_fenced_block.hpp | 2 +-
asio/asio/detail/gcc_sync_fenced_block.hpp | 2 +-
asio/asio/detail/gcc_x86_fenced_block.hpp | 2 +-
asio/asio/detail/handler_alloc_helpers.hpp | 2 +-
asio/asio/detail/handler_cont_helpers.hpp | 2 +-
asio/asio/detail/handler_invoke_helpers.hpp | 2 +-
asio/asio/detail/handler_tracking.hpp | 2 +-
asio/asio/detail/handler_type_requirements.hpp | 16 +-
asio/asio/detail/hash_map.hpp | 2 +-
asio/asio/detail/impl/buffer_sequence_adapter.ipp | 2 +-
asio/asio/detail/impl/descriptor_ops.ipp | 2 +-
asio/asio/detail/impl/dev_poll_reactor.hpp | 2 +-
asio/asio/detail/impl/dev_poll_reactor.ipp | 2 +-
asio/asio/detail/impl/epoll_reactor.hpp | 2 +-
asio/asio/detail/impl/epoll_reactor.ipp | 2 +-
.../detail/impl/eventfd_select_interrupter.ipp | 2 +-
asio/asio/detail/impl/handler_tracking.ipp | 2 +-
asio/asio/detail/impl/kqueue_reactor.hpp | 2 +-
asio/asio/detail/impl/kqueue_reactor.ipp | 2 +-
asio/asio/detail/impl/pipe_select_interrupter.ipp | 2 +-
asio/asio/detail/impl/posix_event.ipp | 2 +-
asio/asio/detail/impl/posix_mutex.ipp | 2 +-
asio/asio/detail/impl/posix_thread.ipp | 2 +-
asio/asio/detail/impl/posix_tss_ptr.ipp | 2 +-
.../detail/impl/reactive_descriptor_service.ipp | 2 +-
.../detail/impl/reactive_serial_port_service.ipp | 2 +-
.../detail/impl/reactive_socket_service_base.ipp | 2 +-
asio/asio/detail/impl/resolver_service_base.ipp | 2 +-
asio/asio/detail/impl/select_reactor.hpp | 2 +-
asio/asio/detail/impl/select_reactor.ipp | 2 +-
asio/asio/detail/impl/service_registry.hpp | 2 +-
asio/asio/detail/impl/service_registry.ipp | 2 +-
asio/asio/detail/impl/signal_set_service.ipp | 2 +-
asio/asio/detail/impl/socket_ops.ipp | 14 +-
.../asio/detail/impl/socket_select_interrupter.ipp | 5 +-
asio/asio/detail/impl/strand_service.hpp | 2 +-
asio/asio/detail/impl/strand_service.ipp | 2 +-
asio/asio/detail/impl/task_io_service.hpp | 2 +-
asio/asio/detail/impl/task_io_service.ipp | 2 +-
asio/asio/detail/impl/throw_error.ipp | 2 +-
asio/asio/detail/impl/timer_queue_ptime.ipp | 2 +-
asio/asio/detail/impl/timer_queue_set.ipp | 2 +-
asio/asio/detail/impl/win_event.ipp | 14 +-
asio/asio/detail/impl/win_iocp_handle_service.ipp | 4 +-
asio/asio/detail/impl/win_iocp_io_service.hpp | 2 +-
asio/asio/detail/impl/win_iocp_io_service.ipp | 2 +-
.../detail/impl/win_iocp_serial_port_service.ipp | 2 +-
.../detail/impl/win_iocp_socket_service_base.ipp | 2 +-
asio/asio/detail/impl/win_mutex.ipp | 7 +-
.../asio/detail/impl/win_object_handle_service.ipp | 2 +-
asio/asio/detail/impl/win_static_mutex.ipp | 20 +-
asio/asio/detail/impl/win_thread.ipp | 14 +-
asio/asio/detail/impl/win_tss_ptr.ipp | 2 +-
.../detail/impl/winrt_ssocket_service_base.ipp | 2 +-
asio/asio/detail/impl/winrt_timer_scheduler.hpp | 2 +-
asio/asio/detail/impl/winrt_timer_scheduler.ipp | 2 +-
asio/asio/detail/impl/winsock_init.ipp | 2 +-
asio/asio/detail/io_control.hpp | 2 +-
asio/asio/detail/keyword_tss_ptr.hpp | 2 +-
asio/asio/detail/kqueue_reactor.hpp | 2 +-
asio/asio/detail/local_free_on_block_exit.hpp | 4 +-
asio/asio/detail/macos_fenced_block.hpp | 2 +-
asio/asio/detail/mutex.hpp | 2 +-
asio/asio/detail/noncopyable.hpp | 2 +-
asio/asio/detail/null_event.hpp | 2 +-
asio/asio/detail/null_fenced_block.hpp | 2 +-
asio/asio/detail/null_mutex.hpp | 2 +-
asio/asio/detail/null_reactor.hpp | 2 +-
asio/asio/detail/null_signal_blocker.hpp | 2 +-
asio/asio/detail/null_socket_service.hpp | 2 +-
asio/asio/detail/null_static_mutex.hpp | 2 +-
asio/asio/detail/null_thread.hpp | 2 +-
asio/asio/detail/null_tss_ptr.hpp | 2 +-
asio/asio/detail/object_pool.hpp | 2 +-
asio/asio/detail/old_win_sdk_compat.hpp | 2 +-
asio/asio/detail/op_queue.hpp | 2 +-
asio/asio/detail/operation.hpp | 2 +-
asio/asio/detail/pipe_select_interrupter.hpp | 2 +-
asio/asio/detail/pop_options.hpp | 2 +-
asio/asio/detail/posix_event.hpp | 2 +-
asio/asio/detail/posix_fd_set_adapter.hpp | 2 +-
asio/asio/detail/posix_mutex.hpp | 2 +-
asio/asio/detail/posix_signal_blocker.hpp | 2 +-
asio/asio/detail/posix_static_mutex.hpp | 2 +-
asio/asio/detail/posix_thread.hpp | 2 +-
asio/asio/detail/posix_tss_ptr.hpp | 2 +-
asio/asio/detail/push_options.hpp | 2 +-
asio/asio/detail/reactive_descriptor_service.hpp | 2 +-
asio/asio/detail/reactive_null_buffers_op.hpp | 2 +-
asio/asio/detail/reactive_serial_port_service.hpp | 2 +-
asio/asio/detail/reactive_socket_accept_op.hpp | 2 +-
asio/asio/detail/reactive_socket_connect_op.hpp | 2 +-
asio/asio/detail/reactive_socket_recv_op.hpp | 2 +-
asio/asio/detail/reactive_socket_recvfrom_op.hpp | 2 +-
asio/asio/detail/reactive_socket_recvmsg_op.hpp | 2 +-
asio/asio/detail/reactive_socket_send_op.hpp | 2 +-
asio/asio/detail/reactive_socket_sendto_op.hpp | 2 +-
asio/asio/detail/reactive_socket_service.hpp | 2 +-
asio/asio/detail/reactive_socket_service_base.hpp | 2 +-
asio/asio/detail/reactor.hpp | 2 +-
asio/asio/detail/reactor_fwd.hpp | 2 +-
asio/asio/detail/reactor_op.hpp | 2 +-
asio/asio/detail/reactor_op_queue.hpp | 2 +-
asio/asio/detail/regex_fwd.hpp | 2 +-
asio/asio/detail/resolve_endpoint_op.hpp | 2 +-
asio/asio/detail/resolve_op.hpp | 2 +-
asio/asio/detail/resolver_service.hpp | 2 +-
asio/asio/detail/resolver_service_base.hpp | 2 +-
asio/asio/detail/scoped_lock.hpp | 2 +-
asio/asio/detail/scoped_ptr.hpp | 2 +-
asio/asio/detail/select_interrupter.hpp | 2 +-
asio/asio/detail/select_reactor.hpp | 2 +-
asio/asio/detail/service_registry.hpp | 2 +-
asio/asio/detail/shared_ptr.hpp | 2 +-
asio/asio/detail/signal_blocker.hpp | 2 +-
asio/asio/detail/signal_handler.hpp | 2 +-
asio/asio/detail/signal_init.hpp | 2 +-
asio/asio/detail/signal_op.hpp | 2 +-
asio/asio/detail/signal_set_service.hpp | 2 +-
asio/asio/detail/socket_holder.hpp | 2 +-
asio/asio/detail/socket_ops.hpp | 2 +-
asio/asio/detail/socket_option.hpp | 2 +-
asio/asio/detail/socket_select_interrupter.hpp | 2 +-
asio/asio/detail/socket_types.hpp | 10 +-
asio/asio/detail/solaris_fenced_block.hpp | 2 +-
asio/asio/detail/static_mutex.hpp | 2 +-
asio/asio/detail/std_event.hpp | 2 +-
asio/asio/detail/std_mutex.hpp | 2 +-
asio/asio/detail/std_static_mutex.hpp | 2 +-
asio/asio/detail/std_thread.hpp | 2 +-
asio/asio/detail/strand_service.hpp | 2 +-
asio/asio/detail/task_io_service.hpp | 2 +-
asio/asio/detail/task_io_service_operation.hpp | 2 +-
asio/asio/detail/task_io_service_thread_info.hpp | 2 +-
asio/asio/detail/thread.hpp | 10 +-
asio/asio/detail/thread_info_base.hpp | 2 +-
asio/asio/detail/throw_error.hpp | 2 +-
asio/asio/detail/throw_exception.hpp | 2 +-
asio/asio/detail/timer_queue.hpp | 2 +-
asio/asio/detail/timer_queue_base.hpp | 2 +-
asio/asio/detail/timer_queue_ptime.hpp | 2 +-
asio/asio/detail/timer_queue_set.hpp | 2 +-
asio/asio/detail/timer_scheduler.hpp | 2 +-
asio/asio/detail/timer_scheduler_fwd.hpp | 2 +-
asio/asio/detail/tss_ptr.hpp | 2 +-
asio/asio/detail/type_traits.hpp | 2 +-
asio/asio/detail/variadic_templates.hpp | 2 +-
asio/asio/detail/wait_handler.hpp | 2 +-
asio/asio/detail/wait_op.hpp | 2 +-
asio/asio/detail/weak_ptr.hpp | 2 +-
asio/asio/detail/win_event.hpp | 6 +-
asio/asio/detail/win_fd_set_adapter.hpp | 2 +-
asio/asio/detail/win_fenced_block.hpp | 2 +-
asio/asio/detail/win_iocp_handle_read_op.hpp | 2 +-
asio/asio/detail/win_iocp_handle_service.hpp | 2 +-
asio/asio/detail/win_iocp_handle_write_op.hpp | 2 +-
asio/asio/detail/win_iocp_io_service.hpp | 2 +-
asio/asio/detail/win_iocp_null_buffers_op.hpp | 2 +-
asio/asio/detail/win_iocp_operation.hpp | 2 +-
asio/asio/detail/win_iocp_overlapped_op.hpp | 2 +-
asio/asio/detail/win_iocp_overlapped_ptr.hpp | 2 +-
asio/asio/detail/win_iocp_serial_port_service.hpp | 2 +-
asio/asio/detail/win_iocp_socket_accept_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_connect_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_recv_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_recvfrom_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_recvmsg_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_send_op.hpp | 2 +-
asio/asio/detail/win_iocp_socket_service.hpp | 2 +-
asio/asio/detail/win_iocp_socket_service_base.hpp | 2 +-
asio/asio/detail/win_iocp_thread_info.hpp | 2 +-
asio/asio/detail/win_mutex.hpp | 2 +-
asio/asio/detail/win_object_handle_service.hpp | 2 +-
asio/asio/detail/win_static_mutex.hpp | 2 +-
asio/asio/detail/win_thread.hpp | 10 +-
asio/asio/detail/win_tss_ptr.hpp | 2 +-
asio/asio/detail/winrt_async_manager.hpp | 2 +-
asio/asio/detail/winrt_async_op.hpp | 2 +-
asio/asio/detail/winrt_resolve_op.hpp | 2 +-
asio/asio/detail/winrt_resolver_service.hpp | 2 +-
asio/asio/detail/winrt_socket_connect_op.hpp | 2 +-
asio/asio/detail/winrt_socket_recv_op.hpp | 2 +-
asio/asio/detail/winrt_socket_send_op.hpp | 2 +-
asio/asio/detail/winrt_ssocket_service.hpp | 2 +-
asio/asio/detail/winrt_ssocket_service_base.hpp | 2 +-
asio/asio/detail/winrt_timer_scheduler.hpp | 2 +-
asio/asio/detail/winrt_utils.hpp | 2 +-
asio/asio/detail/winsock_init.hpp | 2 +-
asio/asio/detail/wrapped_handler.hpp | 2 +-
asio/asio/error.hpp | 2 +-
asio/asio/error_code.hpp | 2 +-
asio/asio/generic/basic_endpoint.hpp | 2 +-
asio/asio/generic/datagram_protocol.hpp | 2 +-
asio/asio/generic/detail/endpoint.hpp | 2 +-
asio/asio/generic/detail/impl/endpoint.ipp | 2 +-
asio/asio/generic/raw_protocol.hpp | 2 +-
asio/asio/generic/seq_packet_protocol.hpp | 2 +-
asio/asio/generic/stream_protocol.hpp | 2 +-
asio/asio/handler_alloc_hook.hpp | 2 +-
asio/asio/handler_continuation_hook.hpp | 2 +-
asio/asio/handler_invoke_hook.hpp | 2 +-
asio/asio/handler_type.hpp | 2 +-
asio/asio/high_resolution_timer.hpp | 2 +-
asio/asio/impl/buffered_read_stream.hpp | 2 +-
asio/asio/impl/buffered_write_stream.hpp | 2 +-
asio/asio/impl/connect.hpp | 4 +-
asio/asio/impl/error.ipp | 2 +-
asio/asio/impl/error_code.ipp | 54 +-
asio/asio/impl/handler_alloc_hook.ipp | 2 +-
asio/asio/impl/io_service.hpp | 2 +-
asio/asio/impl/io_service.ipp | 2 +-
asio/asio/impl/read.hpp | 2 +-
asio/asio/impl/read_at.hpp | 2 +-
asio/asio/impl/read_until.hpp | 2 +-
asio/asio/impl/serial_port_base.hpp | 2 +-
asio/asio/impl/serial_port_base.ipp | 2 +-
asio/asio/impl/spawn.hpp | 2 +-
asio/asio/impl/src.cpp | 2 +-
asio/asio/impl/src.hpp | 2 +-
asio/asio/impl/use_future.hpp | 18 +-
asio/asio/impl/write.hpp | 2 +-
asio/asio/impl/write_at.hpp | 2 +-
asio/asio/io_service.hpp | 2 +-
asio/asio/ip/address.hpp | 2 +-
asio/asio/ip/address_v4.hpp | 2 +-
asio/asio/ip/address_v6.hpp | 2 +-
asio/asio/ip/basic_endpoint.hpp | 2 +-
asio/asio/ip/basic_resolver.hpp | 2 +-
asio/asio/ip/basic_resolver_entry.hpp | 2 +-
asio/asio/ip/basic_resolver_iterator.hpp | 2 +-
asio/asio/ip/basic_resolver_query.hpp | 2 +-
asio/asio/ip/detail/endpoint.hpp | 2 +-
asio/asio/ip/detail/impl/endpoint.ipp | 2 +-
asio/asio/ip/detail/socket_option.hpp | 2 +-
asio/asio/ip/host_name.hpp | 2 +-
asio/asio/ip/icmp.hpp | 2 +-
asio/asio/ip/impl/address.hpp | 2 +-
asio/asio/ip/impl/address.ipp | 2 +-
asio/asio/ip/impl/address_v4.hpp | 2 +-
asio/asio/ip/impl/address_v4.ipp | 2 +-
asio/asio/ip/impl/address_v6.hpp | 2 +-
asio/asio/ip/impl/address_v6.ipp | 2 +-
asio/asio/ip/impl/basic_endpoint.hpp | 2 +-
asio/asio/ip/impl/host_name.ipp | 2 +-
asio/asio/ip/multicast.hpp | 2 +-
asio/asio/ip/resolver_query_base.hpp | 2 +-
asio/asio/ip/resolver_service.hpp | 2 +-
asio/asio/ip/tcp.hpp | 2 +-
asio/asio/ip/udp.hpp | 2 +-
asio/asio/ip/unicast.hpp | 2 +-
asio/asio/ip/v6_only.hpp | 2 +-
asio/asio/is_read_buffered.hpp | 2 +-
asio/asio/is_write_buffered.hpp | 2 +-
asio/asio/local/basic_endpoint.hpp | 2 +-
asio/asio/local/connect_pair.hpp | 2 +-
asio/asio/local/datagram_protocol.hpp | 2 +-
asio/asio/local/detail/endpoint.hpp | 2 +-
asio/asio/local/detail/impl/endpoint.ipp | 2 +-
asio/asio/local/stream_protocol.hpp | 2 +-
asio/asio/placeholders.hpp | 2 +-
asio/asio/posix/basic_descriptor.hpp | 2 +-
asio/asio/posix/basic_stream_descriptor.hpp | 2 +-
asio/asio/posix/descriptor_base.hpp | 2 +-
asio/asio/posix/stream_descriptor.hpp | 2 +-
asio/asio/posix/stream_descriptor_service.hpp | 2 +-
asio/asio/raw_socket_service.hpp | 2 +-
asio/asio/read.hpp | 2 +-
asio/asio/read_at.hpp | 2 +-
asio/asio/read_until.hpp | 2 +-
asio/asio/seq_packet_socket_service.hpp | 2 +-
asio/asio/serial_port.hpp | 2 +-
asio/asio/serial_port_base.hpp | 2 +-
asio/asio/serial_port_service.hpp | 2 +-
asio/asio/signal_set.hpp | 2 +-
asio/asio/signal_set_service.hpp | 2 +-
asio/asio/socket_acceptor_service.hpp | 2 +-
asio/asio/socket_base.hpp | 2 +-
asio/asio/spawn.hpp | 2 +-
asio/asio/ssl.hpp | 2 +-
asio/asio/ssl/basic_context.hpp | 2 +-
asio/asio/ssl/context.hpp | 2 +-
asio/asio/ssl/context_base.hpp | 2 +-
asio/asio/ssl/context_service.hpp | 2 +-
asio/asio/ssl/detail/buffered_handshake_op.hpp | 2 +-
asio/asio/ssl/detail/engine.hpp | 2 +-
asio/asio/ssl/detail/handshake_op.hpp | 2 +-
asio/asio/ssl/detail/impl/engine.ipp | 12 +-
asio/asio/ssl/detail/impl/openssl_init.ipp | 44 +-
asio/asio/ssl/detail/io.hpp | 2 +-
asio/asio/ssl/detail/openssl_init.hpp | 2 +-
asio/asio/ssl/detail/openssl_types.hpp | 4 +-
asio/asio/ssl/detail/password_callback.hpp | 2 +-
asio/asio/ssl/detail/read_op.hpp | 2 +-
asio/asio/ssl/detail/shutdown_op.hpp | 2 +-
asio/asio/ssl/detail/stream_core.hpp | 2 +-
asio/asio/ssl/detail/verify_callback.hpp | 2 +-
asio/asio/ssl/detail/write_op.hpp | 2 +-
asio/asio/ssl/error.hpp | 42 +-
asio/asio/ssl/impl/context.hpp | 2 +-
asio/asio/ssl/impl/context.ipp | 100 +-
asio/asio/ssl/impl/error.ipp | 47 +-
asio/asio/ssl/impl/rfc2818_verification.ipp | 2 +-
asio/asio/ssl/impl/src.hpp | 2 +-
asio/asio/ssl/old/basic_context.hpp | 2 +-
asio/asio/ssl/old/context_service.hpp | 2 +-
.../ssl/old/detail/openssl_context_service.hpp | 10 +-
.../asio/ssl/old/detail/openssl_stream_service.hpp | 2 +-
asio/asio/ssl/old/stream.hpp | 2 +-
asio/asio/ssl/old/stream_service.hpp | 2 +-
asio/asio/ssl/rfc2818_verification.hpp | 2 +-
asio/asio/ssl/stream.hpp | 2 +-
asio/asio/ssl/stream_base.hpp | 2 +-
asio/asio/ssl/stream_service.hpp | 2 +-
asio/asio/ssl/verify_context.hpp | 2 +-
asio/asio/ssl/verify_mode.hpp | 2 +-
asio/asio/steady_timer.hpp | 2 +-
asio/asio/strand.hpp | 2 +-
asio/asio/stream_socket_service.hpp | 2 +-
asio/asio/streambuf.hpp | 2 +-
asio/asio/system_error.hpp | 2 +-
asio/asio/system_timer.hpp | 2 +-
asio/asio/thread.hpp | 2 +-
asio/asio/time_traits.hpp | 2 +-
asio/asio/unyield.hpp | 2 +-
asio/asio/use_future.hpp | 2 +-
asio/asio/version.hpp | 4 +-
asio/asio/wait_traits.hpp | 2 +-
asio/asio/waitable_timer_service.hpp | 2 +-
asio/asio/windows/basic_handle.hpp | 2 +-
asio/asio/windows/basic_object_handle.hpp | 2 +-
asio/asio/windows/basic_random_access_handle.hpp | 2 +-
asio/asio/windows/basic_stream_handle.hpp | 2 +-
asio/asio/windows/object_handle.hpp | 2 +-
asio/asio/windows/object_handle_service.hpp | 2 +-
asio/asio/windows/overlapped_ptr.hpp | 2 +-
asio/asio/windows/random_access_handle.hpp | 2 +-
asio/asio/windows/random_access_handle_service.hpp | 2 +-
asio/asio/windows/stream_handle.hpp | 2 +-
asio/asio/windows/stream_handle_service.hpp | 2 +-
asio/asio/write.hpp | 2 +-
asio/asio/write_at.hpp | 2 +-
asio/asio/yield.hpp | 2 +-
common/wsrep_api.h | 1270 ------------
debian/control | 33 +-
debian/{galera-3.docs => galera-4.docs} | 0
debian/{galera-3.install => galera-4.install} | 0
debian/{galera-3.links => galera-4.links} | 0
...rb.default => galera-arbitrator-4.garb.default} | 0
...r-3.garb.init => galera-arbitrator-4.garb.init} | 0
debian/rules | 4 +-
galera/src/SConscript | 3 +-
galera/src/certification.cpp | 872 +++++++--
galera/src/certification.hpp | 84 +-
galera/src/fsm.hpp | 47 +-
galera/src/galera_gcs.hpp | 43 +-
galera/src/galera_info.cpp | 89 +-
galera/src/galera_info.hpp | 12 +-
galera/src/galera_service_thd.hpp | 3 +-
galera/src/galera_view.cpp | 33 +
galera/src/galera_view.hpp | 54 +
galera/src/gcs_action_source.cpp | 140 +-
galera/src/gcs_action_source.hpp | 34 +-
galera/src/gcs_dummy.cpp | 74 +-
galera/src/ist.cpp | 83 +-
galera/src/ist.hpp | 16 +-
galera/src/ist_proto.hpp | 84 +-
galera/src/key_entry_ng.hpp | 47 +-
galera/src/key_entry_os.cpp | 8 +-
galera/src/key_entry_os.hpp | 34 +-
galera/src/key_set.cpp | 77 +-
galera/src/key_set.hpp | 91 +-
galera/src/monitor.hpp | 28 +-
galera/src/nbo.hpp | 191 ++
galera/src/replicator.hpp | 38 +-
galera/src/replicator_smm.cpp | 2044 ++++++++++++++------
galera/src/replicator_smm.hpp | 236 ++-
galera/src/replicator_smm_params.cpp | 9 +-
galera/src/replicator_smm_stats.cpp | 89 +-
galera/src/replicator_str.cpp | 488 ++++-
galera/src/saved_state.cpp | 41 +-
galera/src/saved_state.hpp | 33 +-
galera/src/trx_handle.cpp | 464 +++--
galera/src/trx_handle.hpp | 1231 ++++++++----
galera/src/uuid.hpp | 59 -
galera/src/write_set.cpp | 5 +
galera/src/write_set.hpp | 4 +-
galera/src/write_set_ng.cpp | 5 +-
galera/src/write_set_ng.hpp | 43 +-
galera/src/wsdb.cpp | 42 +-
galera/src/wsdb.hpp | 47 +-
galera/src/wsrep_params.cpp | 3 +-
galera/src/wsrep_provider.cpp | 405 ++--
galera/tests/SConscript | 1 +
galera/tests/certification_check.cpp | 491 +++++
galera/tests/galera_check.cpp | 5 +-
galera/tests/ist_check.cpp | 95 +-
galera/tests/key_set_check.cpp | 120 +-
galera/tests/test_key.hpp | 22 +-
galera/tests/trx_handle_check.cpp | 405 ++--
galera/tests/write_set_check.cpp | 6 +-
galera/tests/write_set_ng_check.cpp | 36 +-
galerautils/src/gu_asio.cpp | 47 +-
galerautils/src/gu_digest.hpp | 1 -
galerautils/src/gu_mmh3.h | 4 +
galerautils/src/gu_shared_ptr.hpp | 17 +
galerautils/src/gu_vec16.h | 96 -
galerautils/tests/SConscript | 9 +-
galerautils/tests/gu_tests.c | 2 -
galerautils/tests/gu_vec_test.c | 53 -
galerautils/tests/gu_vec_test.h | 12 -
garb/garb_gcs.cpp | 2 +-
garb/garb_gcs.hpp | 4 +-
garb/garb_recv_loop.cpp | 42 +-
garb/garb_recv_loop.hpp | 3 +-
gcomm/src/evs_proto.cpp | 3 +-
gcomm/src/evs_proto.hpp | 3 +-
gcomm/src/gcomm/protolay.hpp | 7 +-
gcomm/src/gcomm/protonet.hpp | 3 +-
gcomm/src/gcomm/protostack.hpp | 3 +-
gcomm/src/gmcast.cpp | 9 +-
gcomm/src/gmcast.hpp | 3 +-
gcomm/src/pc_proto.cpp | 44 +-
gcomm/src/pc_proto.hpp | 66 +-
gcomm/src/protonet.cpp | 5 +-
gcomm/src/protostack.cpp | 5 +-
gcomm/src/view.cpp | 18 +-
gcomm/test/check_evs2.cpp | 24 +-
gcomm/test/check_pc.cpp | 31 +-
gcs/src/SConscript | 1 +
gcs/src/gcs.cpp | 318 ++-
gcs/src/gcs.hpp | 91 +-
gcs/src/gcs_act.hpp | 4 +-
gcs/src/gcs_act_cchange.cpp | 292 +++
gcs/src/gcs_core.cpp | 159 +-
gcs/src/gcs_core.hpp | 15 +-
gcs/src/gcs_fifo_lite.cpp | 4 +-
gcs/src/gcs_gcomm.cpp | 29 +-
gcs/src/gcs_group.cpp | 438 ++++-
gcs/src/gcs_group.hpp | 21 +-
gcs/src/gcs_msg_type.cpp | 3 +-
gcs/src/gcs_msg_type.hpp | 7 +-
gcs/src/gcs_node.cpp | 70 +-
gcs/src/gcs_node.hpp | 31 +-
gcs/src/gcs_params.cpp | 4 +-
gcs/src/gcs_state_msg.cpp | 69 +-
gcs/src/gcs_state_msg.hpp | 22 +-
gcs/src/gcs_test.cpp | 65 +-
gcs/src/unit_tests/SConscript | 2 +
gcs/src/unit_tests/gcs_act_cchange_test.cpp | 118 ++
gcs/src/unit_tests/gcs_act_cchange_test.hpp | 12 +
gcs/src/unit_tests/gcs_backend_test.cpp | 9 +-
gcs/src/unit_tests/gcs_backend_test.hpp | 2 +-
gcs/src/unit_tests/gcs_comp_test.cpp | 10 +-
gcs/src/unit_tests/gcs_comp_test.hpp | 4 +-
gcs/src/unit_tests/gcs_core_test.cpp | 105 +-
gcs/src/unit_tests/gcs_defrag_test.cpp | 11 +-
gcs/src/unit_tests/gcs_defrag_test.hpp | 2 +-
gcs/src/unit_tests/gcs_fc_test.cpp | 6 +-
gcs/src/unit_tests/gcs_fifo_test.cpp | 7 +-
gcs/src/unit_tests/gcs_fifo_test.hpp | 2 +-
gcs/src/unit_tests/gcs_group_test.cpp | 24 +-
gcs/src/unit_tests/gcs_memb_test.cpp | 10 +-
gcs/src/unit_tests/gcs_node_test.hpp | 2 +-
gcs/src/unit_tests/gcs_proto_test.cpp | 8 +-
gcs/src/unit_tests/gcs_proto_test.hpp | 2 +-
gcs/src/unit_tests/gcs_state_msg_test.cpp | 102 +-
gcs/src/unit_tests/gcs_tests.cpp | 2 +
scripts/mysql/build.sh | 1 +
scripts/mysql/mysql-galera | 8 +-
scripts/mysql/rpm.sh | 2 +-
scripts/packages/galera-dev.list | 2 +-
scripts/packages/galera-obs.spec | 19 +-
tests/run_sqlgen.sh | 36 +
tests/scripts/install.sh | 6 +-
wsrep/src | 1 +
539 files changed, 9111 insertions(+), 4850 deletions(-)
diff --cc SConstruct
index 5f0f20a9,32f5476c..7fbc3d57
--- a/SConstruct
+++ b/SConstruct
@@@ -72,8 -72,8 +72,9 @@@ Commandline Options
revno=XXXX source code revision number
bpostatic=path a path to static libboost_program_options.a
extra_sysroot=path a path to extra development environment (Fink, Homebrew, MacPorts, MinGW)
+ version=X.X.X galera version
bits=[32bit|64bit]
+ gcov=[True|False] compile Galera for code coverage reporting
''')
# bpostatic option added on Percona request
diff --cc debian/rules
index be915db2,0b2c532e..1cd3d9ef
--- a/debian/rules
+++ b/debian/rules
@@@ -58,12 -46,9 +58,12 @@@ override_dh_installinit-arch
dh_installinit -n --name=garb -- defaults 18 22
override_dh_strip:
- dh_strip -pgalera-3 --dbg-package=galera-3-dbg
- dh_strip -pgalera-arbitrator-3 --dbg-package=galera-arbitrator-3-dbg
+ dh_strip -pgalera-4 --dbg-package=galera-4-dbg
+ dh_strip -pgalera-arbitrator-4 --dbg-package=galera-arbitrator-4-dbg
+override_dh_shlibdeps:
+ dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
+
%:
dh $@
1
0
[Commits] 89137263ae4: Merge remote-tracking branch 'maria-wsrep/10.4-wsrep_api-26' into 10.4
by jan 13 Oct '18
by jan 13 Oct '18
13 Oct '18
revision-id: 89137263ae49d2818e1a4ff9b3726c0cf6bdd6bc (mariadb-10.3.6-159-g89137263ae4)
parent(s): 0f85f09fd77be9479bd603e467c76b8856deafed 187f570b239749224c0a1b25d5cc458459f926a4
author: Jan Lindström
committer: Jan Lindström
timestamp: 2018-10-13 15:54:22 +0300
message:
Merge remote-tracking branch 'maria-wsrep/10.4-wsrep_api-26' into 10.4
CMakeLists.txt | 8 +-
cmake/wsrep.cmake | 11 +
include/mysql/service_wsrep.h | 2 +-
include/wsrep.h | 29 +--
mysql-test/suite/galera/r/galera_defaults.result | 5 +
.../galera/r/galera_ist_innodb_flush_logs.result | 11 +
.../suite/galera/r/galera_ist_xtrabackup-v2.result | 11 +
mysql-test/suite/galera/r/galera_kill_ddl.result | 2 +-
.../suite/galera/r/galera_kill_largechanges.result | 2 +-
.../suite/galera/r/galera_kill_smallchanges.result | 2 +-
.../suite/galera/r/galera_var_slave_threads.result | 92 ++++++++
mysql-test/suite/galera/r/galera_wan.result | 4 +-
sql/handler.cc | 20 +-
sql/handler.h | 2 +
sql/log.cc | 11 +-
sql/log.h | 5 +-
sql/mysqld.cc | 13 +-
sql/protocol.cc | 2 +
sql/sp_head.cc | 4 +-
sql/sql_alter.cc | 4 +-
sql/sql_base.cc | 5 +-
sql/sql_basic_types.h | 2 +
sql/sql_class.cc | 5 +-
sql/sql_class.h | 5 +-
sql/sql_insert.cc | 8 +-
sql/sql_parse.cc | 26 ++-
sql/sql_plugin.cc | 2 -
sql/sql_truncate.cc | 9 +-
sql/table_cache.cc | 4 +-
sql/wsrep_client_service.cc | 2 +-
sql/wsrep_client_service.h | 6 +-
sql/wsrep_client_state.h | 2 +-
sql/wsrep_condition_variable.h | 2 +-
sql/wsrep_dummy.cc | 31 +--
sql/wsrep_high_priority_service.cc | 2 +-
sql/wsrep_mutex.h | 2 +-
sql/wsrep_mysqld.cc | 241 +++++++++------------
sql/wsrep_mysqld.h | 90 ++++----
sql/wsrep_server_service.cc | 8 +-
sql/wsrep_server_service.h | 6 +-
sql/wsrep_server_state.h | 4 +-
sql/wsrep_sst.cc | 20 +-
sql/wsrep_sst.h | 4 +-
sql/wsrep_storage_service.cc | 14 +-
sql/wsrep_thd.h | 6 +-
sql/wsrep_trans_observer.h | 6 +-
sql/wsrep_var.cc | 12 +-
sql/wsrep_var.h | 5 +-
storage/innobase/handler/ha_innodb.cc | 32 ++-
storage/innobase/row/row0upd.cc | 3 +-
storage/innobase/srv/srv0srv.cc | 2 +
wsrep-lib | 2 +-
52 files changed, 467 insertions(+), 341 deletions(-)
diff --cc include/mysql/service_wsrep.h
index 82fecdb3d2e,0f6d2a46108..e695229fb9d
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@@ -134,9 -132,8 +134,9 @@@ extern my_bool wsrep_load_data_splittin
extern my_bool wsrep_drupal_282555_workaround;
extern my_bool wsrep_recovery;
extern long wsrep_protocol_version;
+extern my_thread_id wsrep_thd_thread_id(THD *thd);
-
+
-extern "C" bool wsrep_consistency_check(THD *thd);
+bool wsrep_consistency_check(THD *thd);
bool wsrep_prepare_key_for_innodb(THD* thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len);
extern "C" const char *wsrep_thd_query(const void* thd);
int wsrep_is_wsrep_xid(const void* xid);
diff --cc include/wsrep.h
index 77d50fc7678,9dd99b92056..f0e1d2087db
--- a/include/wsrep.h
+++ b/include/wsrep.h
@@@ -33,9 -33,9 +33,9 @@@
table_list_, alter_info_)) \
goto error;
--#define WSREP_TO_ISOLATION_END \
- if ((WSREP(thd) && thd && wsrep_thd_is_local_toi(thd)) || \
- if ((WSREP(thd) && thd && wsrep_thd_is_local_toi(thd)) || \
-- wsrep_thd_is_in_rsu(thd)) \
++#define WSREP_TO_ISOLATION_END \
++ if (WSREP_ON && WSREP(thd) && (wsrep_thd_is_local_toi(thd) || \
++ wsrep_thd_is_in_rsu(thd))) \
wsrep_to_isolation_end(thd);
/*
diff --cc mysql-test/suite/galera/r/galera_defaults.result
index 9590ed2963b,381b334908e..39345036876
--- a/mysql-test/suite/galera/r/galera_defaults.result
+++ b/mysql-test/suite/galera/r/galera_defaults.result
@@@ -63,8 -63,76 +63,13 @@@ WSREP_SYNC_WAIT 1
WSREP_TRX_FRAGMENT_SIZE 0
WSREP_TRX_FRAGMENT_UNIT bytes
<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 1; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = yes; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <G
MCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>; socket.checksum = 2; socket.recv_buf_size = 212992;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS
-WHERE VARIABLE_NAME LIKE 'wsrep_%'
-AND VARIABLE_NAME != 'wsrep_debug_sync_waiters';
-COUNT(*)
-63
-SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_STATUS
-WHERE VARIABLE_NAME LIKE 'wsrep_%'
-AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'
-ORDER BY VARIABLE_NAME;
-VARIABLE_NAME
-WSREP_APPLY_OOOE
-WSREP_APPLY_OOOL
-WSREP_APPLY_WINDOW
-WSREP_CAUSAL_READS
-WSREP_CERT_DEPS_DISTANCE
-WSREP_CERT_INDEX_SIZE
-WSREP_CERT_INTERVAL
WSREP_CLUSTER_CAPABILITIES
-WSREP_CLUSTER_CONF_ID
-WSREP_CLUSTER_SIZE
-WSREP_CLUSTER_STATE_UUID
-WSREP_CLUSTER_STATUS
WSREP_CLUSTER_WEIGHT
-WSREP_COMMIT_OOOE
-WSREP_COMMIT_OOOL
-WSREP_COMMIT_WINDOW
-WSREP_CONNECTED
-WSREP_DESYNC_COUNT
-WSREP_EVS_DELAYED
-WSREP_EVS_EVICT_LIST
-WSREP_EVS_REPL_LATENCY
-WSREP_EVS_STATE
-WSREP_FLOW_CONTROL_PAUSED
-WSREP_FLOW_CONTROL_PAUSED_NS
-WSREP_FLOW_CONTROL_RECV
-WSREP_FLOW_CONTROL_SENT
-WSREP_GCOMM_UUID
-WSREP_INCOMING_ADDRESSES
-WSREP_LAST_COMMITTED
-WSREP_LOCAL_BF_ABORTS
-WSREP_LOCAL_CACHED_DOWNTO
-WSREP_LOCAL_CERT_FAILURES
-WSREP_LOCAL_COMMITS
-WSREP_LOCAL_INDEX
-WSREP_LOCAL_RECV_QUEUE
-WSREP_LOCAL_RECV_QUEUE_AVG
-WSREP_LOCAL_RECV_QUEUE_MAX
-WSREP_LOCAL_RECV_QUEUE_MIN
-WSREP_LOCAL_REPLAYS
-WSREP_LOCAL_SEND_QUEUE
-WSREP_LOCAL_SEND_QUEUE_AVG
-WSREP_LOCAL_SEND_QUEUE_MAX
-WSREP_LOCAL_SEND_QUEUE_MIN
-WSREP_LOCAL_STATE
-WSREP_LOCAL_STATE_COMMENT
-WSREP_LOCAL_STATE_UUID
WSREP_OPEN_CONNECTIONS
WSREP_OPEN_TRANSACTIONS
-WSREP_PROTOCOL_VERSION
WSREP_PROVIDER_CAPABILITIES
-WSREP_PROVIDER_NAME
-WSREP_PROVIDER_VENDOR
-WSREP_PROVIDER_VERSION
-WSREP_READY
-WSREP_RECEIVED
-WSREP_RECEIVED_BYTES
-WSREP_REPLICATED
-WSREP_REPLICATED_BYTES
-WSREP_REPL_DATA_BYTES
-WSREP_REPL_KEYS
-WSREP_REPL_KEYS_BYTES
-WSREP_REPL_OTHER_BYTES
-WSREP_THREAD_COUNT
++WSREP_CLUSTER_CAPABILITIES
++WSREP_CLUSTER_WEIGHT
++WSREP_OPEN_CONNECTIONS
++WSREP_OPEN_TRANSACTIONS
++WSREP_PROVIDER_CAPABILITIES
diff --cc mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
index 146cae1e896,cad00aaee48..2f74beb7e82
--- a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
+++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
@@@ -96,15 -96,111 +96,26 @@@ COUNT(*) =
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
-Performing State Transfer on a server that has been killed and restarted
-while a DDL was in progress on it
connection node_1;
-CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
connection node_2;
-START TRANSACTION;
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-COMMIT;
+connection node_1;
+connection node_2;
+connection node_1;
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_2;
+connection node_2;
+connection node_1;
+connection node_1a_galera_st_kill_slave_ddl;
+connection node_1;
++connection node_2;
+ SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+ connection node_1;
-ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+ connection node_2;
-SET wsrep_sync_wait = 0;
-Killing server ...
+ connection node_1;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-COMMIT;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+ connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ connection node_2;
-Performing --wsrep-recover ...
+ connection node_2;
-Starting server ...
-Using --wsrep-start-position when starting mysqld ...
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-COMMIT;
+ connection node_1;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-COMMIT;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-COMMIT;
+ connection node_1a_galera_st_kill_slave_ddl;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-ROLLBACK;
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-COUNT(*) = 2
-1
-SELECT COUNT(*) = 35 FROM t1;
-COUNT(*) = 35
-1
-SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
-COUNT(*) = 0
-1
-COMMIT;
-SET AUTOCOMMIT=ON;
+ connection node_1;
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-COUNT(*) = 2
-1
-SELECT COUNT(*) = 35 FROM t1;
-COUNT(*) = 35
-1
-SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
-COUNT(*) = 0
-1
-DROP TABLE t1;
-COMMIT;
-SET AUTOCOMMIT=ON;
SET GLOBAL debug_dbug = $debug_orig;
diff --cc mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
index f9fdc70e9d0,579370fb25c..a5a776d3b77
--- a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
+++ b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
@@@ -285,15 -285,111 +285,26 @@@ COUNT(*) =
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
-Performing State Transfer on a server that has been killed and restarted
-while a DDL was in progress on it
connection node_1;
-CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
-INSERT INTO t1 VALUES ('node1_committed_before');
connection node_2;
-START TRANSACTION;
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-INSERT INTO t1 VALUES ('node2_committed_before');
-COMMIT;
+connection node_1;
+connection node_2;
+connection node_1;
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_2;
+connection node_2;
+connection node_1;
+connection node_1a_galera_st_kill_slave_ddl;
+connection node_1;
++connection node_2;
+ SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+ connection node_1;
-ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+ connection node_2;
-SET wsrep_sync_wait = 0;
-Killing server ...
+ connection node_1;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-INSERT INTO t1 (f1) VALUES ('node1_committed_during');
-COMMIT;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+ connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ connection node_2;
-Performing --wsrep-recover ...
+ connection node_2;
-Starting server ...
-Using --wsrep-start-position when starting mysqld ...
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-INSERT INTO t1 (f1) VALUES ('node2_committed_after');
-COMMIT;
+ connection node_1;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
-COMMIT;
-SET AUTOCOMMIT=OFF;
-START TRANSACTION;
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-INSERT INTO t1 (f1) VALUES ('node1_committed_after');
-COMMIT;
+ connection node_1a_galera_st_kill_slave_ddl;
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
-ROLLBACK;
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-COUNT(*) = 2
-1
-SELECT COUNT(*) = 35 FROM t1;
-COUNT(*) = 35
-1
-SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
-COUNT(*) = 0
-1
-COMMIT;
-SET AUTOCOMMIT=ON;
+ connection node_1;
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-COUNT(*) = 2
-1
-SELECT COUNT(*) = 35 FROM t1;
-COUNT(*) = 35
-1
-SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
-COUNT(*) = 0
-1
-DROP TABLE t1;
-COMMIT;
-SET AUTOCOMMIT=ON;
SET GLOBAL debug_dbug = $debug_orig;
diff --cc mysql-test/suite/galera/r/galera_var_slave_threads.result
index e774e620ccd,6196e6b1b78..0ba64da318c
--- a/mysql-test/suite/galera/r/galera_var_slave_threads.result
+++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result
@@@ -79,6 -43,106 +79,98 @@@ INSERT INTO t2 VALUES (DEFAULT)
INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
-connection node_2;
-SELECT COUNT(*) = 64 FROM t2;
-COUNT(*) = 64
-1
+ SET wsrep_sync_wait=0;
+ SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+ COUNT(*) = @@wsrep_slave_threads + 2
+ 1
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+ COUNT(*) = 1
+ 1
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
-COUNT(*)
-1
+ SET GLOBAL wsrep_slave_threads = 5;
-SET GLOBAL wsrep_slave_threads = 1;
+ connection node_2;
+ Shutting down server ...
+ connection node_1;
+ SET wsrep_sync_wait=0;
+ show status like 'wsrep_cluster_size';
+ Variable_name Value
+ wsrep_cluster_size 1
+ SET GLOBAL wsrep_slave_threads = 6;
+ SET GLOBAL wsrep_slave_threads = 1;
+ SET GLOBAL wsrep_cluster_address='';
+ SET GLOBAL wsrep_cluster_address='gcomm://';
+ SET GLOBAL wsrep_slave_threads = 10;
+ connection node_2;
+ SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+ COUNT(*) = @@wsrep_slave_threads + 2
+ 1
+ connection node_1;
+ SET GLOBAL wsrep_slave_threads = 1;
+ connection node_2;
+ SET GLOBAL wsrep_slave_threads = 1;
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
+ INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
diff --cc mysql-test/suite/galera/r/galera_wan.result
index 41b915fa5bf,ff961c6e633..24be2330297
--- a/mysql-test/suite/galera/r/galera_wan.result
+++ b/mysql-test/suite/galera/r/galera_wan.result
@@@ -1,7 -1,5 +1,7 @@@
- CALL mtr.add_suppression("WSREP: Stray state UUID msg:.*");
- CALL mtr.add_suppression("WSREP: Sending JOIN failed:.*");
+ connection node_2;
+ connection node_1;
+CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside");
+call mtr.add_suppression("WSREP: Sending JOIN failed:.*");
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4
1
diff --cc sql/handler.cc
index 19d31b32381,c9880b1c98b..eabc17db627
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@@ -54,8 -53,8 +54,8 @@@
#include "semisync_master.h"
#include "mysql/service_wsrep.h"
- #include "wsrep.h"
-#include "wsrep_mysqld.h"
+ #ifdef WITH_WSREP
+#include "wsrep_mysqld.h"
#include "wsrep_binlog.h"
#include "wsrep_xid.h"
#include "wsrep_thd.h"
diff --cc sql/log.h
index 1aa83eaabb1,bae48c493ad..77855484468
--- a/sql/log.h
+++ b/sql/log.h
@@@ -1221,16 -1220,11 +1220,20 @@@ static inline TC_LOG *get_tc_log_implem
return &mysql_bin_log;
return &tc_log_mmap;
}
+#ifdef WITH_WSREP
+IO_CACHE* wsrep_get_trans_cache(THD *);
+void wsrep_thd_binlog_trx_reset(THD * thd);
+#define WSREP_BINLOG_FORMAT(my_format) \
+ ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
+ wsrep_forced_binlog_format : my_format)
+#else
+#define WSREP_BINLOG_FORMAT(my_format) my_format
+#endif /* WITH_WSREP */
+ #ifdef WITH_WSREP
+ IO_CACHE* wsrep_get_trans_cache(THD *);
+ void wsrep_thd_binlog_trx_reset(THD * thd);
+ #endif /* WITH_WSREP */
class Gtid_list_log_event;
const char *
diff --cc sql/mysqld.cc
index 0758603a810,02d95c88a2f..2a38f0036fd
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@@ -8535,8 -8832,8 +8536,10 @@@ static int mysql_init_variables(void
set_sys_var_value_origin(&mysql_home_ptr, sys_var::ENV);
#endif
++#ifdef WITH_WSREP
if (wsrep_init_vars())
return 1;
++#endif
return 0;
}
diff --cc sql/sql_alter.cc
index 06147a52004,fb89e0bc5b2..92717760cb1
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@@ -476,17 -476,15 +476,19 @@@ bool Sql_cmd_alter_table::execute(THD *
thd->work_part_info= 0;
#endif
+ #ifdef WITH_WSREP
- if ((!thd->is_current_stmt_binlog_format_row() ||
+ if (WSREP(thd) &&
+ (!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
- WSREP_TO_ISOLATION_BEGIN(((lex->name.str) ? select_lex->db.str : NULL),
- ((lex->name.str) ? lex->name.str : NULL),
- first_table);
+ WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL),
+ (lex->name.str ? lex->name.str : NULL),
+ first_table, &alter_info);
+
+ thd->variables.auto_increment_offset = 1;
+ thd->variables.auto_increment_increment = 1;
}
+ #endif /* WITH_WSREP */
result= mysql_alter_table(thd, &select_lex->db, &lex->name,
&create_info,
@@@ -499,12 -497,10 +501,12 @@@
DBUG_RETURN(result);
#ifdef WITH_WSREP
-error:
- // Jump to error may happen from WSREP_TO_ISOLATION_BEGIN
- DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
+error: /* Used by WSREP_TO_ISOLATION_BEGIN_ALTER */
- #endif
+ {
+ WSREP_WARN("ALTER TABLE isolation failure");
+ DBUG_RETURN(TRUE);
+ }
++#endif
}
bool Sql_cmd_discard_import_tablespace::execute(THD *thd)
diff --cc sql/sql_base.cc
index 9d2c6b81169,829c8dc9efc..83fcfe4f8f3
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@@ -61,8 -61,8 +61,9 @@@
#ifdef __WIN__
#include <io.h>
#endif
- #ifdef WITH_WSREP
++
#include "wsrep_mysqld.h"
+ #ifdef WITH_WSREP
#include "wsrep_thd.h"
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
diff --cc sql/sql_class.cc
index a3cabaf7c5d,097c76ee3ed..4543f6f39e6
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@@ -65,14 -65,13 +65,13 @@@
#include "sql_parse.h" // is_update_query
#include "sql_callback.h"
#include "lock.h"
-#include "wsrep_mysqld.h"
+ #include "sql_connect.h"
-#include "my_atomic.h"
#ifdef WITH_WSREP
#include "mysql/service_wsrep.h"
+//#include "wsrep_client_service.h"
+#include "wsrep_mysqld.h"
#include "wsrep_binlog.h" /* wsrep_fragment_unit() */
#include "wsrep_thd.h"
- #include "sql_connect.h"
- #include "my_atomic.h"
#endif /* WITH_WSREP */
#ifdef HAVE_SYS_SYSCALL_H
@@@ -538,12 -537,6 +537,12 @@@ char *thd_security_context(THD *thd
return thd_get_error_context_description(thd, buffer, length, max_query_len);
}
#endif
+#ifdef WITH_WSREP
+extern "C" bool wsrep_consistency_check(void *thd)
+{
- return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
++ return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
+}
+#endif /* WITH_WSREP */
/**
Implementation of Drop_table_error_handler::handle_condition().
diff --cc sql/sql_class.h
index c97c1d55c1a,56e9563a526..8aadfd26f4c
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@@ -69,10 -70,9 +69,11 @@@ void set_thd_stage_info(void *thd
#include "wsrep_mutex.h"
#include "wsrep_condition_variable.h"
+#include "wsrep_mysqld.h"
++
class Wsrep_applier_service;
- #endif
+ #endif /* WITH_WSREP */
class Reprepare_observer;
class Relay_log_info;
struct rpl_group_info;
diff --cc sql/sql_insert.cc
index ff4ebc8d986,57596ce3f1d..28cebc23cb8
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@@ -4617,12 -4617,12 +4617,12 @@@ bool select_create::send_eof(
mysql_mutex_lock(&thd->LOCK_thd_data);
if (thd->wsrep_trx().state() != wsrep::transaction::s_executing)
{
- WSREP_DEBUG("select_create commit failed, thd: %lu err: %s %s",
- thd->thread_id, wsrep_thd_transaction_state_str(thd),
- WSREP_QUERY(thd));
+ WSREP_DEBUG("select_create commit failed, thd: %llu err: %s %s",
+ thd->thread_id,
+ wsrep_thd_transaction_state_str(thd), WSREP_QUERY(thd));
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- abort_result_set();
- DBUG_RETURN(true);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ abort_result_set();
+ DBUG_RETURN(true);
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
thd->wsrep_cs().after_statement();
diff --cc sql/sql_parse.cc
index 71bdec30a08,78fa984f270..a1310a52dbb
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@@ -109,8 -109,9 +109,10 @@@
#include "../storage/maria/ha_maria.h"
#endif
+#include "mysql/service_wsrep.h"
#include "wsrep_mysqld.h"
+ #ifdef WITH_WSREP
+ #include "mysql/service_wsrep.h"
#include "wsrep_thd.h"
#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
@@@ -7957,10 -7967,8 +7966,9 @@@ static bool wsrep_mysql_parse(THD *thd
"WAIT_FOR wsrep_retry_autocommit_continue";
DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
});
+ WSREP_DEBUG("Retry autocommit query: %s", thd->query());
mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, is_next_command);
-
/*
Convert all ER_QUERY_INTERRUPTED errors to ER_LOCK_DEADLOCK
if the transaction was BF aborted. This can happen when the
diff --cc sql/wsrep_mysqld.cc
index c314fc65ce4,0362958c30b..39ce4aaa8ca
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@@ -517,9 -521,6 +521,10 @@@ static std::string wsrep_server_node_ad
char node_addr[512] = {0, };
const size_t node_addr_max= sizeof(node_addr) - 1;
size_t guess_ip_ret= wsrep_guess_ip(node_addr, node_addr_max);
++
++ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
++ wsrep_data_home_dir = mysql_real_data_home;
++
if (!(guess_ip_ret > 0 && guess_ip_ret < node_addr_max))
{
WSREP_WARN("Failed to guess base node address. Set it explicitly via "
@@@ -759,6 -760,6 +764,9 @@@ int wsrep_init(
wsrep_capabilities_export(Wsrep_server_state::instance().provider().capabilities(),
&wsrep_provider_capabilities);
++ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
++ wsrep_data_home_dir = mysql_real_data_home;
++
WSREP_DEBUG("SR storage init for: %s",
(wsrep_SR_store_type == WSREP_SR_STORE_TABLE) ? "table" :
(wsrep_SR_store_type == WSREP_SR_STORE_FILE) ? "file" : "void");
@@@ -2080,7 -2032,7 +2037,7 @@@ static void wsrep_TOI_end(THD *thd)
if (ret == 0)
{
-- WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get());
++ WSREP_DEBUG("TO END: %ld", client_state.toi_meta().seqno().get());
}
else
{
@@@ -2098,7 -2050,7 +2055,7 @@@
static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
{
-- WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd),
++ WSREP_DEBUG("RSU BEGIN: %ld, : %s", wsrep_thd_trx_seqno(thd),
WSREP_QUERY(thd));
if (thd->wsrep_cs().begin_rsu(5000))
{
diff --cc sql/wsrep_mysqld.h
index 09f09d495e0,88ae0c77e36..b242ace3bd1
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@@ -581,7 -548,7 +549,6 @@@ bool wsrep_node_is_synced()
* @return true if SR capable
*/
bool wsrep_provider_is_SR_capable();
--
/**
* Mark current commit ordered if binlogging is not enabled.
*
@@@ -625,4 -592,40 +592,39 @@@ void wsrep_init_globals()
* Deinit and release WSREP resources.
*/
void wsrep_deinit_server();
+
+ #else /* !WITH_WSREP */
+
+ /* These macros are needed to compile MariaDB without WSREP support
+ * (e.g. embedded) */
-
+ #define WSREP(T) (0)
+ #define WSREP_ON (0)
+ #define WSREP_EMULATE_BINLOG(thd) (0)
+ #define WSREP_EMULATE_BINLOG_NNULL(thd) (0)
+ //#define WSREP_CLIENT(thd) (0)
+ #define WSREP_BINLOG_FORMAT(my_format) ((ulong)my_format)
+ #define WSREP_PROVIDER_EXISTS (0)
+ #define wsrep_emulate_bin_log (0)
+ #define wsrep_to_isolation (0)
+ //#define wsrep_init() (1)
+ //#define wsrep_prepend_PATH(X)
+ //#define wsrep_before_SE() (0)
+ //#define wsrep_init_startup(X)
+ //#define wsrep_must_sync_wait(...) (0)
+ //#define wsrep_sync_wait(...) (0)
+ //#define wsrep_to_isolation_begin(...) (0)
+ //#define wsrep_register_hton(...) do { } while(0)
+ //#define wsrep_check_opts() (0)
+ //#define wsrep_stop_replication(X) do { } while(0)
+ //#define wsrep_inited (0)
+ //#define wsrep_deinit(X) do { } while(0)
+ //#define wsrep_recover() do { } while(0)
+ //#define wsrep_slave_threads (1)
+ //#define wsrep_replicate_myisam (0)
+ //#define wsrep_thr_init() do {} while(0)
+ #define wsrep_thr_deinit() do {} while(0)
+ //#define wsrep_running_threads (0)
+
+ #endif /* WITH_WSREP */
+
#endif /* WSREP_MYSQLD_H */
diff --cc sql/wsrep_sst.h
index 79d0d9e8a1e,0d0ccfc4482..65c7d12d717
--- a/sql/wsrep_sst.h
+++ b/sql/wsrep_sst.h
@@@ -16,8 -16,8 +16,8 @@@
#ifndef WSREP_SST_H
#define WSREP_SST_H
+ #include <my_config.h>
-
++#include <my_global.h>
#include "wsrep/gtid.hpp"
#include <my_global.h>
#include <string>
diff --cc sql/wsrep_thd.h
index a2fdd7d1a36,f6e749fd559..f6179d784d7
--- a/sql/wsrep_thd.h
+++ b/sql/wsrep_thd.h
@@@ -16,9 -16,10 +16,9 @@@
#ifndef WSREP_THD_H
#define WSREP_THD_H
+ #include <my_config.h>
-
#include "mysql/service_wsrep.h"
+ #include "wsrep/client_state.hpp"
#include "sql_class.h"
#include "wsrep_utils.h"
#include <deque>
diff --cc sql/wsrep_var.cc
index 791bd1c2b2a,85297d8fc3f..37c29944d8a
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@@ -579,8 -579,9 +579,8 @@@ static void wsrep_slave_count_change_up
{
// wsrep_running_threads = appliers threads + 2 rollbacker threads
wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_threads + 2);
- WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %lu",
+ WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %d",
- wsrep_slave_threads, wsrep_running_threads,
- wsrep_slave_count_change);
+ wsrep_slave_threads, wsrep_running_threads, wsrep_slave_count_change);
}
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
@@@ -755,6 -756,6 +755,7 @@@ wsrep_assign_to_mysql (SHOW_VAR* mysql
}
}
++
#ifdef OLD_MARIADB
int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
diff --cc storage/innobase/handler/ha_innodb.cc
index 0f703c53dca,f622af0fa35..9b1fb0f1f36
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@@ -18527,16 -18594,15 +18526,13 @@@ wsrep_innobase_kill_one_trx
WSREP_LOG_CONFLICT((const void*)bf_thd, (const void*)thd, TRUE);
wsrep_thd_LOCK(thd);
- WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%llu) trx: %llu",
- signal, (long long)bf_seqno,
- (long long)thd_get_thread_id(thd),
+ WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu",
+ signal, (long long)bf_seqno, thd_get_thread_id(thd),
(long long)victim_trx->id);
--
WSREP_DEBUG("Aborting query: %s conf %s trx: %lld",
(thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void",
wsrep_thd_transaction_state_str(thd),
wsrep_thd_transaction_id(thd));
--
wsrep_thd_UNLOCK(thd);
if (wsrep_thd_bf_abort(bf_thd, thd, signal))
{
@@@ -18552,7 -18618,7 +18548,7 @@@
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
lock_cancel_waiting_and_release(wait_lock);
}
-- wsrep_thd_awake((const void*)thd, signal);
++ wsrep_thd_awake((const void*)thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
@@@ -18641,10 -18707,9 +18637,10 @@@ static void wsrep_fake_trx_id(handlerto
trx_id_t trx_id = trx_sys.get_new_trx_id();
WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
trx_id, wsrep_thd_query(thd));
+
wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
}
-
+ #endif /* UNUSED */
#endif /* WITH_WSREP */
/* plugin options */
1
0
[Commits] 0f85f09fd77: MDEV-16405: Merge Galera 4 changes from mariaDB_wsrep to 10.4
by jan 13 Oct '18
by jan 13 Oct '18
13 Oct '18
revision-id: 0f85f09fd77be9479bd603e467c76b8856deafed (mariadb-10.3.6-158-g0f85f09fd77)
parent(s): f545e3cfa9fcc6b706a6e0ee6f2af2124e514e18
author: Jan Lindström
committer: Jan Lindström
timestamp: 2018-10-13 08:41:48 +0300
message:
MDEV-16405: Merge Galera 4 changes from mariaDB_wsrep to 10.4
Phase I.
---
.gitmodules | 4 +
CMakeLists.txt | 16 +-
cmake/plugin.cmake | 4 +
cmake/wsrep.cmake | 2 +-
extra/mariabackup/CMakeLists.txt | 2 +-
extra/mariabackup/wsrep.cc | 4 +-
include/mysql/service_wsrep.h | 239 +-
include/thr_lock.h | 6 +-
include/wsrep.h | 38 +-
mysql-test/include/check-testcase.test | 46 +
mysql-test/include/galera_cluster.inc | 6 +
.../galera => }/include/galera_have_debug_sync.inc | 0
mysql-test/include/galera_wait_sync_point.inc | 11 +
mysql-test/include/have_ipv6.inc | 20 +
mysql-test/include/kill_galera.inc | 20 +
mysql-test/include/mtr_warnings.sql | 46 +
mysql-test/include/restart_mysqld.inc | 1 -
mysql-test/include/wait_until_connected_again.inc | 2 +-
mysql-test/include/wait_wsrep_ready.inc | 13 +
mysql-test/include/wsrep_wait_disconnect.inc | 20 +
mysql-test/lib/My/ConfigFactory.pm | 6 +-
mysql-test/mysql-test-run.pl | 125 +
mysql-test/r/mysqld--help-notwin.result | 1472 +++++++++++
mysql-test/r/query_cache_size_functionality.result | 226 ++
mysql-test/r/query_cache_type_functionality.result | 250 ++
mysql-test/suite/galera/disabled.def | 2 +-
mysql-test/suite/galera/galera_2nodes.cnf | 25 +-
.../suite/galera/galera_2nodes_as_master.cnf | 12 +
mysql-test/suite/galera/galera_2nodes_as_slave.cnf | 47 +-
mysql-test/suite/galera/galera_3nodes_as_slave.cnf | 59 +-
mysql-test/suite/galera/galera_4nodes.cnf | 15 +
.../suite/galera/include/galera_load_provider.inc | 68 +
mysql-test/suite/galera/include/galera_resume.inc | 2 +-
.../suite/galera/include/galera_sst_restore.inc | 2 +-
.../suite/galera/include/galera_st_clean_slave.inc | 1 +
.../galera/include/galera_st_disconnect_slave.inc | 8 +
.../galera/include/galera_unload_provider.inc | 8 +
mysql-test/suite/galera/r/GAL-382.result | 2 +
mysql-test/suite/galera/r/GAL-401.result | 2 +
mysql-test/suite/galera/r/GAL-480.result | 2 +
mysql-test/suite/galera/r/GCF-1081.result | 47 +
mysql-test/suite/galera/r/GCF-939.result | 13 +
mysql-test/suite/galera/r/MDEV-15443.result | 2 +
mysql-test/suite/galera/r/MW-252.result | 2 +
mysql-test/suite/galera/r/MW-258.result | 2 +
mysql-test/suite/galera/r/MW-259.result | 2 +
mysql-test/suite/galera/r/MW-284.result | 4 +
mysql-test/suite/galera/r/MW-285.result | 2 +
mysql-test/suite/galera/r/MW-292.result | 27 +-
mysql-test/suite/galera/r/MW-309.result | 2 +
mysql-test/suite/galera/r/MW-313.result | 2 +
mysql-test/suite/galera/r/MW-328A.result | 18 +-
mysql-test/suite/galera/r/MW-328B.result | 2 +
mysql-test/suite/galera/r/MW-328C.result | 2 +
mysql-test/suite/galera/r/MW-328D.result | 2 +
mysql-test/suite/galera/r/MW-328E.result | 2 +
mysql-test/suite/galera/r/MW-329.result | 9 +-
mysql-test/suite/galera/r/MW-336.result | 2 +
mysql-test/suite/galera/r/MW-357.result | 2 +
mysql-test/suite/galera/r/MW-360.result | 41 +
mysql-test/suite/galera/r/MW-369.result | 65 +-
mysql-test/suite/galera/r/MW-388.result | 6 +-
mysql-test/suite/galera/r/MW-402.result | 76 +-
mysql-test/suite/galera/r/MW-416.result | 6 +-
mysql-test/suite/galera/r/MW-86-wait1.result | 17 +-
mysql-test/suite/galera/r/MW-86-wait8.result | 16 +-
mysql-test/suite/galera/r/MW-86.result | 78 +
mysql-test/suite/galera/r/basic.result | 2 +
mysql-test/suite/galera/r/binlog_checksum.result | 2 +
mysql-test/suite/galera/r/create.result | 2 +
.../suite/galera/r/enforce_storage_engine.result | 2 +
.../suite/galera/r/enforce_storage_engine2.result | 2 +
mysql-test/suite/galera/r/ev51914.result | 2 +
mysql-test/suite/galera/r/fk.result | 2 +
mysql-test/suite/galera/r/galera#414.result | 2 +
mysql-test/suite/galera/r/galera_admin.result | 2 +
.../galera/r/galera_alter_engine_innodb.result | 2 +
.../galera/r/galera_alter_engine_myisam.result | 2 +
.../suite/galera/r/galera_alter_table_force.result | 2 +
.../galera/r/galera_applier_ftwrl_table.result | 2 +
.../r/galera_applier_ftwrl_table_alter.result | 2 +
mysql-test/suite/galera/r/galera_as_master.result | 4 +
.../suite/galera/r/galera_as_master_gtid.result | 44 +-
.../suite/galera/r/galera_as_master_large.result | 2 +
.../suite/galera/r/galera_as_slave_autoinc.result | 4 +
.../suite/galera/r/galera_as_slave_gtid.result | 2 +
.../r/galera_as_slave_gtid_replicate_do_db.result | 160 ++
.../galera_as_slave_gtid_replicate_do_db_cc.result | 315 +++
.../suite/galera/r/galera_as_slave_nonprim.result | 18 +
.../galera/r/galera_autoinc_sst_xtrabackup.result | 2 +
mysql-test/suite/galera/r/galera_bf_abort.result | 4 +-
.../r/galera_bf_abort_flush_for_export.result | 2 +
.../galera/r/galera_bf_abort_for_update.result | 6 +-
.../suite/galera/r/galera_bf_abort_ftwrl.result | 2 +
.../suite/galera/r/galera_bf_abort_get_lock.result | 4 +-
.../galera/r/galera_bf_abort_group_commit.result | 685 +++++
.../galera/r/galera_bf_abort_lock_table.result | 2 +
.../suite/galera/r/galera_bf_abort_shutdown.result | 9 +
.../suite/galera/r/galera_bf_abort_sleep.result | 4 +-
.../r/galera_bf_background_statistics.result | 4 +-
.../suite/galera/r/galera_bf_lock_wait.result | 2 +
.../suite/galera/r/galera_binlog_cache_size.result | 2 +
.../suite/galera/r/galera_binlog_checksum.result | 2 +
.../r/galera_binlog_event_max_size_max.result | 2 +
.../r/galera_binlog_event_max_size_min.result | 2 +
.../suite/galera/r/galera_binlog_row_image.result | 2 +
.../suite/galera/r/galera_commit_empty.result | 15 +
.../suite/galera/r/galera_create_function.result | 2 +
.../suite/galera/r/galera_create_procedure.result | 2 +
.../galera/r/galera_create_table_as_select.result | 103 +
.../suite/galera/r/galera_create_table_like.result | 2 +
.../suite/galera/r/galera_create_trigger.result | 2 +
.../suite/galera/r/galera_ddl_multiline.result | 2 +
mysql-test/suite/galera/r/galera_defaults.result | 23 +-
.../suite/galera/r/galera_delete_limit.result | 2 +
.../suite/galera/r/galera_desync_overlapped.result | 2 +
mysql-test/suite/galera/r/galera_drop_multi.result | 2 +
mysql-test/suite/galera/r/galera_enum.result | 4 +-
mysql-test/suite/galera/r/galera_events.result | 2 +
.../suite/galera/r/galera_fk_cascade_delete.result | 2 +
.../suite/galera/r/galera_fk_cascade_update.result | 2 +
.../suite/galera/r/galera_fk_conflict.result | 4 +-
.../suite/galera/r/galera_fk_mismatch.result | 2 +
.../suite/galera/r/galera_fk_multicolumn.result | 2 +
.../suite/galera/r/galera_fk_multitable.result | 2 +
mysql-test/suite/galera/r/galera_fk_no_pk.result | 2 +
.../galera/r/galera_fk_selfreferential.result | 2 +
mysql-test/suite/galera/r/galera_fk_setnull.result | 2 +
.../suite/galera/r/galera_flush_local.result | 2 +
.../galera/r/galera_forced_binlog_format.result | 20 +-
mysql-test/suite/galera/r/galera_ftwrl.result | 2 +
.../suite/galera/r/galera_ftwrl_drain.result | 2 +
mysql-test/suite/galera/r/galera_fulltext.result | 2 +
.../r/galera_gcache_recover_full_gcache.result | 2 +-
.../suite/galera/r/galera_gcs_fc_limit.result | 2 +
.../suite/galera/r/galera_gcs_fragment.result | 2 +-
.../galera/r/galera_gcs_max_packet_size.result | 2 +
mysql-test/suite/galera/r/galera_gra_log.result | 2 +
mysql-test/suite/galera/r/galera_gtid.result | 2 +
mysql-test/suite/galera/r/galera_gtid_slave.result | 11 +-
.../galera/r/galera_gtid_slave_sst_rsync.result | 106 +-
.../suite/galera/r/galera_insert_ignore.result | 2 +
.../suite/galera/r/galera_insert_multi.result | 4 +-
.../galera/r/galera_ist_innodb_flush_logs.result | 22 +
.../suite/galera/r/galera_ist_progress.result | 5 +
.../suite/galera/r/galera_ist_recv_bind.result | 2 +
.../galera/r/galera_ist_restart_joiner.result | 3 +-
mysql-test/suite/galera/r/galera_ist_rsync.result | 2 +
.../suite/galera/r/galera_ist_xtrabackup-v2.result | 38 +
mysql-test/suite/galera/r/galera_kill_ddl.result | 1 +
.../suite/galera/r/galera_kill_largechanges.result | 1 +
.../suite/galera/r/galera_kill_smallchanges.result | 1 +
mysql-test/suite/galera/r/galera_lock_table.result | 2 +
mysql-test/suite/galera/r/galera_log_bin.result | 4 +
.../suite/galera/r/galera_log_output_csv.result | 2 +
.../suite/galera/r/galera_many_columns.result | 4 +-
.../suite/galera/r/galera_many_indexes.result | 4 +-
mysql-test/suite/galera/r/galera_many_rows.result | 4 +-
.../suite/galera/r/galera_many_tables_nopk.result | 4 +-
.../suite/galera/r/galera_many_tables_pk.result | 4 +-
mysql-test/suite/galera/r/galera_mdev_10812.result | 2 +
mysql-test/suite/galera/r/galera_mdev_13787.result | 2 +
mysql-test/suite/galera/r/galera_mdl_race.result | 4 +-
.../suite/galera/r/galera_multi_database.result | 2 +
.../suite/galera/r/galera_myisam_autocommit.result | 2 +
.../galera/r/galera_myisam_transactions.result | 2 +
mysql-test/suite/galera/r/galera_nopk_bit.result | 4 +-
mysql-test/suite/galera/r/galera_nopk_blob.result | 4 +-
.../galera/r/galera_nopk_large_varchar.result | 4 +-
.../suite/galera/r/galera_nopk_unicode.result | 4 +-
.../r/galera_parallel_apply_lock_table.result | 8 +-
.../r/galera_parallel_autoinc_largetrx.result | 4 +-
.../r/galera_parallel_autoinc_manytrx.result | 4 +-
.../suite/galera/r/galera_parallel_simple.result | 2 +
.../suite/galera/r/galera_pk_bigint_signed.result | 4 +-
.../galera/r/galera_pk_bigint_unsigned.result | 4 +-
.../galera/r/galera_prepared_statement.result | 2 +
.../suite/galera/r/galera_query_cache.result | 2 +
.../galera/r/galera_query_cache_sync_wait.result | 2 +
mysql-test/suite/galera/r/galera_read_only.result | 2 +
.../galera/r/galera_repl_key_format_flat16.result | 2 +
.../suite/galera/r/galera_repl_max_ws_size.result | 4 +-
.../suite/galera/r/galera_restart_nochanges.result | 2 +
.../r/galera_restart_on_unknown_option.result | 2 +
mysql-test/suite/galera/r/galera_rsu_add_pk.result | 2 +
.../suite/galera/r/galera_rsu_drop_pk.result | 2 +
mysql-test/suite/galera/r/galera_rsu_error.result | 2 +
mysql-test/suite/galera/r/galera_rsu_simple.result | 2 +
.../suite/galera/r/galera_rsu_wsrep_desync.result | 2 +
mysql-test/suite/galera/r/galera_sbr.result | 2 +
mysql-test/suite/galera/r/galera_sbr_binlog.result | 2 +
.../galera/r/galera_schema_dirty_reads.result | 2 +
.../suite/galera/r/galera_serializable.result | 8 +-
mysql-test/suite/galera/r/galera_server.result | 2 +
.../suite/galera/r/galera_sql_log_bin_zero.result | 2 +
mysql-test/suite/galera/r/galera_ssl.result | 2 +
.../suite/galera/r/galera_ssl_compression.result | 2 +
.../suite/galera/r/galera_sst_mysqldump.result | 114 +
mysql-test/suite/galera/r/galera_sst_rsync.result | 2 +-
.../suite/galera/r/galera_sst_xtrabackup-v2.result | 110 +
...alera_sst_xtrabackup-v2_encrypt_with_key.result | 2 +
.../suite/galera/r/galera_status_cluster.result | 2 +
.../galera/r/galera_status_local_index.result | 2 +
.../galera/r/galera_status_local_state.result | 2 +
.../suite/galera/r/galera_suspend_slave.result | 2 +
.../suite/galera/r/galera_sync_wait_show.result | 2 +
.../r/galera_toi_alter_auto_increment.result | 2 +
.../suite/galera/r/galera_toi_ddl_error.result | 5 +
.../suite/galera/r/galera_toi_ddl_fk_update.result | 2 +
.../suite/galera/r/galera_toi_ddl_locking.result | 32 +-
.../galera/r/galera_toi_ddl_nonconflicting.result | 2 +
.../galera/r/galera_toi_ddl_sequential.result | 2 +
.../suite/galera/r/galera_toi_drop_database.result | 6 +-
mysql-test/suite/galera/r/galera_toi_ftwrl.result | 2 +
.../galera/r/galera_toi_lock_exclusive.result | 4 +-
.../suite/galera/r/galera_toi_lock_shared.result | 2 +
.../suite/galera/r/galera_toi_truncate.result | 4 +-
.../galera/r/galera_transaction_read_only.result | 2 +
.../galera/r/galera_transaction_replay.result | 96 +-
mysql-test/suite/galera/r/galera_truncate.result | 2 +
.../galera/r/galera_truncate_temporary.result | 2 +
.../galera/r/galera_unicode_identifiers.result | 2 +
mysql-test/suite/galera/r/galera_unicode_pk.result | 6 +-
.../suite/galera/r/galera_update_limit.result | 2 +
.../suite/galera/r/galera_v1_row_events.result | 2 +
.../suite/galera/r/galera_var_OSU_method.result | 2 +
.../suite/galera/r/galera_var_OSU_method2.result | 2 +
.../r/galera_var_auto_inc_control_off.result | 4 +-
.../galera/r/galera_var_auto_inc_control_on.result | 2 +
.../galera/r/galera_var_certify_nonPK_off.result | 2 +
.../galera/r/galera_var_cluster_address.result | 8 +-
.../suite/galera/r/galera_var_desync_on.result | 2 +
.../suite/galera/r/galera_var_dirty_reads.result | 4 +-
.../suite/galera/r/galera_var_fkchecks.result | 2 +
.../galera/r/galera_var_gtid_domain_id.result | 2 +
.../galera/r/galera_var_ignore_apply_errors.result | 154 ++
.../r/galera_var_innodb_disallow_writes.result | 2 +
.../galera/r/galera_var_load_data_splitting.result | 2 +
.../suite/galera/r/galera_var_log_bin.result | 2 +
.../suite/galera/r/galera_var_max_ws_rows.result | 2 +
.../suite/galera/r/galera_var_max_ws_size.result | 4 +-
.../r/galera_var_mysql_replication_bundle.result | 2 +
.../suite/galera/r/galera_var_node_address.result | 2 +
.../galera/r/galera_var_reject_queries.result | 2 +
.../r/galera_var_replicate_myisam_off.result | 2 +
.../galera/r/galera_var_replicate_myisam_on.result | 2 +
.../suite/galera/r/galera_var_slave_threads.result | 207 +-
.../suite/galera/r/galera_var_sst_auth.result | 2 +
.../suite/galera/r/galera_var_sync_wait.result | 2 +
.../suite/galera/r/galera_var_wsrep_on_off.result | 2 +
.../suite/galera/r/galera_wan_restart_ist.result | 2 +
.../suite/galera/r/galera_wan_restart_sst.result | 2 +
.../galera/r/galera_wsrep_desync_wsrep_on.result | 2 +
.../galera/r/galera_wsrep_log_conficts.result | 4 +-
.../suite/galera/r/galera_wsrep_new_cluster.result | 2 +
.../r/galera_wsrep_provider_options_syntax.result | 2 +
.../galera/r/galera_zero_length_column.result | 2 +
mysql-test/suite/galera/r/grant.result | 2 +
mysql-test/suite/galera/r/lp1276424.result | 2 +
mysql-test/suite/galera/r/lp1347768.result | 2 +
mysql-test/suite/galera/r/lp1376747-2.result | 2 +
mysql-test/suite/galera/r/lp1376747-3.result | 2 +
mysql-test/suite/galera/r/lp1376747-4.result | 2 +
mysql-test/suite/galera/r/lp1376747.result | 2 +
mysql-test/suite/galera/r/lp1438990.result | 2 +
mysql-test/suite/galera/r/lp959512.result | 2 +
mysql-test/suite/galera/r/mdev_10518.result | 2 +
mysql-test/suite/galera/r/mdev_9290.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#110.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#198.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#201.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#216.result | 11 +
mysql-test/suite/galera/r/mysql-wsrep#237.result | 4 +-
mysql-test/suite/galera/r/mysql-wsrep#247.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#31.result | 2 +
mysql-test/suite/galera/r/mysql-wsrep#90.result | 2 +
mysql-test/suite/galera/r/partition.result | 6 +-
mysql-test/suite/galera/r/pxc-421.result | 2 +
mysql-test/suite/galera/r/query_cache.result | 2 +
mysql-test/suite/galera/r/rename.result | 2 +
mysql-test/suite/galera/r/rpl_row_annotate.result | 8 +-
mysql-test/suite/galera/r/sql_log_bin.result | 2 +
mysql-test/suite/galera/r/unique_key.result | 2 +
mysql-test/suite/galera/r/view.result | 2 +
.../galera/r/wsrep_trx_fragment_size_non_sr.result | 25 +
.../galera/r/wsrep_trx_fragment_size_sr.result | 15 +
mysql-test/suite/galera/suite.pm | 2 +
mysql-test/suite/galera/t/GAL-419.test | 4 +-
mysql-test/suite/galera/t/GCF-1081.test | 72 +
mysql-test/suite/galera/t/GCF-939.test | 31 +
mysql-test/suite/galera/t/MW-284.test | 2 +
mysql-test/suite/galera/t/MW-292.test | 50 +-
mysql-test/suite/galera/t/MW-328A.test | 40 +-
mysql-test/suite/galera/t/MW-329.test | 28 +-
mysql-test/suite/galera/t/MW-336.test | 9 +-
mysql-test/suite/galera/t/MW-360-master.opt | 2 +
mysql-test/suite/galera/t/MW-360.test | 100 +
mysql-test/suite/galera/t/MW-369.inc | 7 +-
mysql-test/suite/galera/t/MW-369.test | 1 -
mysql-test/suite/galera/t/MW-388.test | 5 +-
mysql-test/suite/galera/t/MW-402.test | 56 +-
mysql-test/suite/galera/t/MW-416.test | 8 +-
mysql-test/suite/galera/t/MW-86-master.opt | 1 +
mysql-test/suite/galera/t/MW-86-wait1.test | 13 +-
mysql-test/suite/galera/t/MW-86-wait8.test | 11 +-
mysql-test/suite/galera/t/MW-86.test | 193 ++
mysql-test/suite/galera/t/disabled.def | 13 +
.../t/galera_applier_ftwrl_table_alter-master.opt | 2 +-
mysql-test/suite/galera/t/galera_as_master.test | 2 +
.../suite/galera/t/galera_as_master_gtid.cnf | 2 -
.../suite/galera/t/galera_as_master_gtid.test | 24 +-
.../t/galera_as_master_gtid_change_master.cnf | 2 -
.../t/galera_as_master_gtid_change_master.test | 2 +
mysql-test/suite/galera/t/galera_as_slave.test | 19 +-
.../suite/galera/t/galera_as_slave_autoinc.test | 20 +-
.../suite/galera/t/galera_as_slave_gtid.test | 21 +-
.../t/galera_as_slave_gtid_replicate_do_db.cnf | 17 +
.../t/galera_as_slave_gtid_replicate_do_db.test | 150 ++
.../t/galera_as_slave_gtid_replicate_do_db_cc.test | 176 ++
.../suite/galera/t/galera_as_slave_nonprim.test | 28 +-
.../suite/galera/t/galera_as_slave_preordered.test | 19 +-
.../t/galera_as_slave_replication_bundle.test | 13 +-
.../galera/t/galera_autoinc_sst_xtrabackup.cnf | 2 +-
.../galera/t/galera_bf_abort_group_commit.cnf | 15 +
.../galera/t/galera_bf_abort_group_commit.test | 76 +
.../suite/galera/t/galera_bf_abort_shutdown.test | 22 +
mysql-test/suite/galera/t/galera_commit_empty.test | 35 +
.../galera/t/galera_create_table_as_select.test | 145 ++
mysql-test/suite/galera/t/galera_defaults.test | 4 +-
.../galera/t/galera_forced_binlog_format.test | 5 +-
mysql-test/suite/galera/t/galera_ftwrl_drain.test | 2 +-
.../t/galera_gcache_recover_full_gcache.test | 4 +-
mysql-test/suite/galera/t/galera_gcs_fragment.test | 2 +-
mysql-test/suite/galera/t/galera_gtid-master.opt | 2 +-
mysql-test/suite/galera/t/galera_gtid_slave.test | 14 +
.../galera/t/galera_gtid_slave_sst_rsync.test | 109 +-
.../galera/t/galera_ist_innodb_flush_logs.cnf | 2 +-
mysql-test/suite/galera/t/galera_ist_progress.test | 4 +-
.../suite/galera/t/galera_ist_restart_joiner.test | 2 +-
.../suite/galera/t/galera_ist_xtrabackup-v2.cnf | 2 +-
mysql-test/suite/galera/t/galera_kill_applier.test | 1 -
mysql-test/suite/galera/t/galera_log_bin.test | 2 +
mysql-test/suite/galera/t/galera_migrate.cnf | 2 +
.../galera/t/galera_parallel_apply_lock_table.test | 6 +-
.../galera/t/galera_parallel_autoinc_manytrx.test | 2 +-
.../suite/galera/t/galera_parallel_simple.test | 2 +-
mysql-test/suite/galera/t/galera_pc_recovery.test | 93 +
mysql-test/suite/galera/t/galera_split_brain.test | 6 +-
mysql-test/suite/galera/t/galera_ssl_upgrade.test | 4 +
mysql-test/suite/galera/t/galera_sst_mysqldump.cnf | 6 +-
.../suite/galera/t/galera_sst_mysqldump.test | 3 +-
.../galera/t/galera_sst_mysqldump_with_key.cnf | 4 +
.../galera/t/galera_sst_xtrabackup-v2-options.cnf | 2 +-
.../suite/galera/t/galera_sst_xtrabackup-v2.cnf | 2 +-
.../galera_sst_xtrabackup-v2_encrypt_with_key.cnf | 2 +-
.../suite/galera/t/galera_toi_ddl_error.test | 5 +
.../suite/galera/t/galera_toi_ddl_locking.test | 53 +-
.../suite/galera/t/galera_transaction_replay.test | 201 +-
.../suite/galera/t/galera_var_cluster_address.test | 11 +-
.../suite/galera/t/galera_var_dirty_reads.test | 6 +-
.../galera/t/galera_var_ignore_apply_errors.test | 235 ++
mysql-test/suite/galera/t/galera_var_log_bin.cnf | 5 +
.../galera/t/galera_var_retry_autocommit.test | 18 +-
.../suite/galera/t/galera_var_slave_threads.test | 123 +-
.../galera/t/galera_vote_drop_temporary-master.opt | 1 +
.../suite/galera/t/galera_wsrep_new_cluster.test | 1 -
.../suite/galera/t/mysql-wsrep#198-master.opt | 1 +
mysql-test/suite/galera/t/mysql-wsrep#237.test | 4 +-
mysql-test/suite/galera/t/partition.test | 16 +-
mysql-test/suite/galera/t/rpl_row_annotate.test | 6 +-
.../galera/t/wsrep_trx_fragment_size_non_sr.test | 26 +
.../suite/galera/t/wsrep_trx_fragment_size_sr.test | 22 +
mysql-test/suite/galera_3nodes/galera_3nodes.cnf | 1 +
.../suite/galera_3nodes/include/galera_suspend.inc | 2 +-
.../r/galera_certification_ccc.result | 2 +
.../r/galera_certification_double_failure.result | 5 +-
.../r/galera_ipv6_xtrabackup-v2.result | 3 -
.../r/galera_ist_gcache_rollover.result | 2 +
.../r/galera_parallel_apply_3nodes.result | 4 +-
.../galera_3nodes/r/galera_pc_bootstrap.result | 13 +
.../suite/galera_3nodes/r/galera_pc_weight.result | 1 -
.../galera_3nodes/r/galera_wsrep_schema.result | 77 +
mysql-test/suite/galera_3nodes/t/GAL-501.test | 6 +
.../t/galera_certification_double_failure.test | 2 +
.../t/galera_evs_suspect_timeout.test | 6 +-
mysql-test/suite/galera_3nodes/t/galera_garbd.test | 5 +-
.../galera_3nodes/t/galera_ipv6_mysqldump.cnf | 6 +
.../galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf | 4 +
.../galera_3nodes/t/galera_ipv6_xtrabackup-v2.test | 30 +-
.../t/galera_ist_gcache_rollover.test | 2 +-
.../t/galera_parallel_apply_3nodes.test | 2 +-
.../suite/galera_3nodes/t/galera_pc_weight.cnf | 8 +-
.../suite/galera_3nodes/t/galera_pc_weight.test | 27 +-
.../t/galera_slave_options_ignore.test | 1 +
.../suite/galera_3nodes/t/galera_wsrep_schema.test | 74 +
.../suite/galera_3nodes_ee/galera_3nodes.cnf | 1 +
.../include/galera_check_voting_recovery.inc | 58 +
mysql-test/suite/galera_3nodes_ee/my.cnf | 1 +
mysql-test/suite/galera_3nodes_ee/r/GCF-354.result | 23 +
mysql-test/suite/galera_3nodes_ee/r/GCF-361.result | 16 +
mysql-test/suite/galera_3nodes_ee/r/GCF-363.result | 31 +
mysql-test/suite/galera_3nodes_ee/r/GCF-376.result | 48 +
.../galera_3nodes_ee/r/galera-features#115.result | 21 +
.../galera_3nodes_ee/r/galera-features#119.result | 19 +
.../galera_3nodes_ee/r/galera-features#79.result | 32 +
.../r/galera_nbo_kill_master.result | 27 +
.../r/galera_nbo_kill_slave_ist.result | 35 +
.../r/galera_nbo_kill_slave_sst.result | 33 +
.../r/galera_nbo_master_majority_failure.result | 46 +
.../r/galera_nbo_master_majority_success.result | 50 +
.../r/galera_nbo_master_minority_failure.result | 52 +
.../r/galera_nbo_master_minority_success.result | 52 +
.../r/galera_nbo_master_non_prim_failure.result | 42 +
.../r/galera_nbo_master_non_prim_success.result | 32 +
.../r/galera_nbo_shutdown_slave_ist.result | 28 +
.../r/galera_nbo_slave_non_prim.result | 35 +
.../galera_3nodes_ee/r/galera_toi_vote.result | 19 +
.../r/galera_vote_rejoin_mysqldump.result | 60 +
.../suite/galera_3nodes_ee/r/galera_vote_sr.result | 52 +
.../r/mysql-wsrep-features#131.result | 12 +
mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf | 4 +
mysql-test/suite/galera_3nodes_ee/t/GCF-354.test | 59 +
mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf | 4 +
mysql-test/suite/galera_3nodes_ee/t/GCF-361.test | 47 +
mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf | 8 +
mysql-test/suite/galera_3nodes_ee/t/GCF-363.test | 68 +
mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf | 4 +
mysql-test/suite/galera_3nodes_ee/t/GCF-376.test | 84 +
.../galera_3nodes_ee/t/galera-features#115.cnf | 4 +
.../galera_3nodes_ee/t/galera-features#115.test | 67 +
.../galera_3nodes_ee/t/galera-features#119.test | 61 +
.../galera_3nodes_ee/t/galera-features#79.test | 75 +
.../galera_3nodes_ee/t/galera_nbo_kill_master.test | 73 +
.../t/galera_nbo_kill_slave_ist.test | 73 +
.../t/galera_nbo_kill_slave_sst.cnf | 11 +
.../t/galera_nbo_kill_slave_sst.test | 70 +
.../t/galera_nbo_master_majority_failure.cnf | 4 +
.../t/galera_nbo_master_majority_failure.test | 38 +
.../t/galera_nbo_master_majority_success.cnf | 4 +
.../t/galera_nbo_master_majority_success.test | 38 +
.../t/galera_nbo_master_minority_failure.cnf | 4 +
.../t/galera_nbo_master_minority_failure.test | 35 +
.../t/galera_nbo_master_minority_success.cnf | 4 +
.../t/galera_nbo_master_minority_success.test | 41 +
.../t/galera_nbo_master_non_prim_failure.test | 92 +
.../t/galera_nbo_master_non_prim_success.test | 80 +
.../t/galera_nbo_shutdown_slave_ist.test | 66 +
.../t/galera_nbo_slave_non_prim.test | 69 +
.../suite/galera_3nodes_ee/t/galera_toi_vote.cnf | 4 +
.../suite/galera_3nodes_ee/t/galera_toi_vote.test | 63 +
.../t/galera_vote_rejoin_mysqldump.cnf | 4 +
.../t/galera_vote_rejoin_mysqldump.test | 80 +
.../galera_3nodes_ee/t/galera_vote_sr-master.opt | 2 +
.../suite/galera_3nodes_ee/t/galera_vote_sr.test | 87 +
.../t/mysql-wsrep-features#131.test | 39 +
.../suite/galera_3nodes_sr/galera_3nodes.cnf | 1 +
mysql-test/suite/galera_3nodes_sr/my.cnf | 1 +
mysql-test/suite/galera_3nodes_sr/r/GCF-336.result | 26 +
mysql-test/suite/galera_3nodes_sr/r/GCF-582.result | 23 +
mysql-test/suite/galera_3nodes_sr/r/GCF-606.result | 23 +
mysql-test/suite/galera_3nodes_sr/r/GCF-609.result | 20 +
.../suite/galera_3nodes_sr/r/GCF-810A.result | 256 ++
.../suite/galera_3nodes_sr/r/GCF-810B.result | 100 +
.../suite/galera_3nodes_sr/r/GCF-810C.result | 177 ++
mysql-test/suite/galera_3nodes_sr/r/GCF-817.result | 33 +
mysql-test/suite/galera_3nodes_sr/r/GCF-832.result | 15 +
.../r/galera_sr_isolate_master.result | 62 +
.../galera_3nodes_sr/r/galera_sr_join_slave.result | 25 +
.../r/galera_sr_kill_master.result | 22 +
.../r/galera_sr_kill_slave_after_apply.result | 38 +
...alera_sr_kill_slave_after_apply_rollback.result | 44 +
...lera_sr_kill_slave_after_apply_rollback2.result | 31 +
.../r/galera_sr_kill_slave_before_apply.result | 27 +
.../r/galera_sr_threeway_split.result | 84 +
mysql-test/suite/galera_3nodes_sr/t/GCF-336.test | 47 +
mysql-test/suite/galera_3nodes_sr/t/GCF-582.test | 39 +
mysql-test/suite/galera_3nodes_sr/t/GCF-606.test | 80 +
mysql-test/suite/galera_3nodes_sr/t/GCF-609.test | 30 +
mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test | 137 +
mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test | 49 +
mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test | 70 +
mysql-test/suite/galera_3nodes_sr/t/GCF-817.test | 101 +
mysql-test/suite/galera_3nodes_sr/t/GCF-832.test | 36 +
mysql-test/suite/galera_3nodes_sr/t/disabled.def | 0
.../t/galera_sr_isolate_master.test | 127 +
.../galera_3nodes_sr/t/galera_sr_join_slave.test | 56 +
.../galera_3nodes_sr/t/galera_sr_kill_master.test | 56 +
.../t/galera_sr_kill_slave_after_apply.test | 75 +
.../galera_sr_kill_slave_after_apply_rollback.test | 76 +
...galera_sr_kill_slave_after_apply_rollback2.test | 56 +
.../t/galera_sr_kill_slave_before_apply.test | 71 +
.../t/galera_sr_threeway_split.cnf | 5 +
.../t/galera_sr_threeway_split.test | 169 ++
mysql-test/suite/galera_ee/galera_2nodes.cnf | 1 +
mysql-test/suite/galera_ee/galera_4nodes.cnf | 1 +
mysql-test/suite/galera_ee/my.cnf | 1 +
mysql-test/suite/galera_ee/r/GCF-329A.result | 30 +
mysql-test/suite/galera_ee/r/GCF-329B.result | 16 +
mysql-test/suite/galera_ee/r/GCF-360.result | 416 ++++
mysql-test/suite/galera_ee/r/GCF-421.result | 14 +
mysql-test/suite/galera_ee/r/GCF-546.result | 28 +
mysql-test/suite/galera_ee/r/GCF-563.result | 52 +
mysql-test/suite/galera_ee/r/GCF-849.result | 11 +
mysql-test/suite/galera_ee/r/GCF-854.result | 16 +
.../suite/galera_ee/r/galera-features#117.result | 29 +
.../r/galera_nbo_alter_conflicting.result | 14 +
.../suite/galera_ee/r/galera_nbo_alter_copy.result | 44 +
.../galera_ee/r/galera_nbo_alter_engine.result | 22 +
.../r/galera_nbo_alter_error_duplicate.result | 30 +
.../galera_ee/r/galera_nbo_alter_exclusive.result | 37 +
.../galera_ee/r/galera_nbo_alter_inplace.result | 39 +
.../galera_ee/r/galera_nbo_alter_multi.result | 11 +
.../r/galera_nbo_alter_nonconflicting.result | 29 +
.../galera_ee/r/galera_nbo_alter_parallel.result | 45 +
.../galera_ee/r/galera_nbo_alter_partition.result | 26 +
.../galera_ee/r/galera_nbo_alter_rename.result | 19 +
.../suite/galera_ee/r/galera_nbo_alter_toi.result | 38 +
.../galera_ee/r/galera_nbo_create_index.result | 36 +
.../suite/galera_ee/r/galera_nbo_ddl_error.result | 22 +
.../galera_ee/r/galera_nbo_error_on_all.result | 13 +
.../suite/galera_ee/r/galera_nbo_local_mdl.result | 12 +
.../galera_ee/r/galera_nbo_processlist.result | 35 +
.../suite/galera_ee/r/galera_nbo_sst_slave.result | 23 +
.../galera_ee/r/galera_nbo_temporary_table.result | 14 +
.../galera_ee/r/galera_nbo_unsupported.result | 26 +
.../galera_ee/r/galera_vote_rejoin_ddl.result | 44 +
.../galera_ee/r/galera_vote_rejoin_dml.result | 47 +
.../galera_ee/r/mysql-wsrep-features#127.result | 5 +
.../galera_ee/r/mysql-wsrep-features#128.result | 7 +
.../galera_ee/r/mysql-wsrep-features#131.result | 12 +
.../galera_ee/r/mysql-wsrep-features#132.result | 18 +
mysql-test/suite/galera_ee/t/GCF-329A.test | 42 +
mysql-test/suite/galera_ee/t/GCF-329B.test | 53 +
mysql-test/suite/galera_ee/t/GCF-360.cnf | 17 +
mysql-test/suite/galera_ee/t/GCF-360.test | 64 +
mysql-test/suite/galera_ee/t/GCF-421.test | 46 +
mysql-test/suite/galera_ee/t/GCF-546.test | 47 +
mysql-test/suite/galera_ee/t/GCF-563.test | 63 +
mysql-test/suite/galera_ee/t/GCF-849.test | 39 +
mysql-test/suite/galera_ee/t/GCF-854.test | 42 +
.../suite/galera_ee/t/galera-features#117.cnf | 4 +
.../suite/galera_ee/t/galera-features#117.test | 37 +
.../galera_ee/t/galera_nbo_alter_conflicting.test | 57 +
.../suite/galera_ee/t/galera_nbo_alter_copy.test | 67 +
.../suite/galera_ee/t/galera_nbo_alter_engine.test | 31 +
.../t/galera_nbo_alter_error_duplicate.test | 34 +
.../galera_ee/t/galera_nbo_alter_exclusive.test | 64 +
.../galera_ee/t/galera_nbo_alter_inplace.test | 67 +
.../suite/galera_ee/t/galera_nbo_alter_multi.test | 15 +
.../t/galera_nbo_alter_nonconflicting.test | 57 +
.../galera_ee/t/galera_nbo_alter_parallel.test | 65 +
.../galera_ee/t/galera_nbo_alter_partition.test | 29 +
.../suite/galera_ee/t/galera_nbo_alter_rename.test | 31 +
.../suite/galera_ee/t/galera_nbo_alter_toi.test | 53 +
.../suite/galera_ee/t/galera_nbo_create_index.test | 34 +
.../suite/galera_ee/t/galera_nbo_ddl_error.test | 38 +
.../suite/galera_ee/t/galera_nbo_error_on_all.test | 21 +
.../suite/galera_ee/t/galera_nbo_local_mdl.test | 55 +
.../suite/galera_ee/t/galera_nbo_processlist.test | 81 +
.../suite/galera_ee/t/galera_nbo_sst_slave.test | 89 +
.../t/galera_nbo_temporary_table-master.opt | 2 +
.../galera_ee/t/galera_nbo_temporary_table.test | 37 +
.../suite/galera_ee/t/galera_nbo_unsupported.test | 42 +
.../suite/galera_ee/t/galera_vote_rejoin_ddl.cnf | 5 +
.../suite/galera_ee/t/galera_vote_rejoin_ddl.test | 87 +
.../suite/galera_ee/t/galera_vote_rejoin_dml.cnf | 4 +
.../suite/galera_ee/t/galera_vote_rejoin_dml.test | 91 +
.../galera_ee/t/mysql-wsrep-features#127.test | 16 +
.../t/mysql-wsrep-features#128-master.opt | 1 +
.../galera_ee/t/mysql-wsrep-features#128.test | 11 +
.../galera_ee/t/mysql-wsrep-features#131.test | 38 +
.../galera_ee/t/mysql-wsrep-features#132.test | 39 +
mysql-test/suite/galera_sr/galera_2nodes.cnf | 1 +
mysql-test/suite/galera_sr/my.cnf | 1 +
mysql-test/suite/galera_sr/r/GCF-1008.result | 70 +
mysql-test/suite/galera_sr/r/GCF-1018.result | 15 +
mysql-test/suite/galera_sr/r/GCF-1018B.result | 8 +
mysql-test/suite/galera_sr/r/GCF-1043A.result | 21 +
mysql-test/suite/galera_sr/r/GCF-1043B.result | 15 +
mysql-test/suite/galera_sr/r/GCF-1051.result | 46 +
mysql-test/suite/galera_sr/r/GCF-1060.result | 15 +
mysql-test/suite/galera_sr/r/GCF-437.result | 12 +
mysql-test/suite/galera_sr/r/GCF-561.result | 42 +
mysql-test/suite/galera_sr/r/GCF-571.result | 67 +
mysql-test/suite/galera_sr/r/GCF-572.result | 37 +
mysql-test/suite/galera_sr/r/GCF-574.result | 11 +
mysql-test/suite/galera_sr/r/GCF-580.result | 13 +
mysql-test/suite/galera_sr/r/GCF-585.result | 25 +
mysql-test/suite/galera_sr/r/GCF-597.result | 15 +
mysql-test/suite/galera_sr/r/GCF-620.result | 14 +
mysql-test/suite/galera_sr/r/GCF-623.result | 22 +
mysql-test/suite/galera_sr/r/GCF-627.result | 18 +
mysql-test/suite/galera_sr/r/GCF-845.result | 14 +
mysql-test/suite/galera_sr/r/GCF-851.result | 24 +
mysql-test/suite/galera_sr/r/GCF-867.result | 2 +
mysql-test/suite/galera_sr/r/GCF-889.result | 18 +
mysql-test/suite/galera_sr/r/GCF-900.result | 13 +
.../suite/galera_sr/r/galera-features#56.result | 32 +
.../suite/galera_sr/r/galera_sr_bf_abort.result | 448 ++++
mysql-test/suite/galera_sr/r/galera_sr_blob.result | 15 +
.../suite/galera_sr/r/galera_sr_cc_master.result | 45 +
.../suite/galera_sr/r/galera_sr_cc_slave.result | 46 +
.../suite/galera_sr/r/galera_sr_concurrent.result | 28 +
.../suite/galera_sr/r/galera_sr_conflict.result | 14 +
.../r/galera_sr_conflict_on_commit.result | 22 +
.../r/galera_sr_conflict_on_commit2.result | 19 +
.../galera_sr_conflict_with_rollback_master.result | 22 +
.../suite/galera_sr/r/galera_sr_ddl_master.result | 41 +
.../suite/galera_sr/r/galera_sr_ddl_schema.result | 18 +
.../suite/galera_sr/r/galera_sr_ddl_slave.result | 42 +
.../galera_sr/r/galera_sr_ddl_unrelated.result | 34 +
.../galera_sr/r/galera_sr_dupkey_error.result | 36 +
.../suite/galera_sr/r/galera_sr_fk_conflict.result | 34 +
mysql-test/suite/galera_sr/r/galera_sr_gtid.result | 57 +
.../galera_sr/r/galera_sr_insert_select.result | 11 +
.../r/galera_sr_kill_all_nobootstrap.result | 21 +
.../r/galera_sr_kill_all_norecovery.result | 22 +
.../r/galera_sr_kill_all_pcrecovery.result | 22 +
.../galera_sr/r/galera_sr_kill_connection.result | 25 +
.../suite/galera_sr/r/galera_sr_kill_query.result | 17 +
.../suite/galera_sr/r/galera_sr_kill_slave.result | 39 +
.../galera_sr/r/galera_sr_large_fragment.result | 28 +
.../suite/galera_sr/r/galera_sr_load_data.result | 8 +
.../r/galera_sr_load_data_splitting.result | 9 +
.../suite/galera_sr/r/galera_sr_log_bin.result | 124 +
.../galera_sr/r/galera_sr_many_fragments.result | 28 +
.../suite/galera_sr/r/galera_sr_myisam.result | 11 +
.../galera_sr/r/galera_sr_mysqldump_sst.result | 40 +
.../galera_sr/r/galera_sr_parallel_apply.result | 26 +
.../suite/galera_sr/r/galera_sr_rollback.result | 29 +
.../galera_sr/r/galera_sr_rollback_retry.result | 26 +
.../r/galera_sr_rollback_savepoint.result | 33 +
.../r/galera_sr_rollback_statement.result | 22 +
mysql-test/suite/galera_sr/r/galera_sr_sbr.result | 16 +
.../galera_sr/r/galera_sr_shutdown_master.result | 20 +
.../galera_sr/r/galera_sr_shutdown_slave.result | 29 +
.../galera_sr/r/galera_sr_small_gcache.result | 10 +
.../galera_sr/r/galera_sr_table_contents.result | 198 ++
.../r/galera_sr_transaction_replay.result | 101 +
.../galera_sr/r/galera_sr_unit_statements.result | 18 +
.../galera_sr/r/galera_sr_v1_row_events.result | 20 +
.../suite/galera_sr/r/galera_sr_ws_size.result | 29 +
.../suite/galera_sr/r/galera_sr_ws_size2.result | 28 +
.../r/galera_var_ignore_apply_errors_sr.result | 22 +
.../suite/galera_sr/r/mysql-wsrep#215.result | 88 +
.../galera_sr/r/mysql-wsrep-features#136.result | 65 +
.../galera_sr/r/mysql-wsrep-features#138.result | 17 +
.../galera_sr/r/mysql-wsrep-features#14.result | 8 +
.../galera_sr/r/mysql-wsrep-features#148.result | 27 +
.../galera_sr/r/mysql-wsrep-features#15.result | 8 +
.../galera_sr/r/mysql-wsrep-features#165.result | 752 ++++++
.../galera_sr/r/mysql-wsrep-features#213.result | 26 +
.../galera_sr/r/mysql-wsrep-features#214.result | 46 +
.../galera_sr/r/mysql-wsrep-features#22.result | 26 +
.../galera_sr/r/mysql-wsrep-features#27.result | 17 +
.../galera_sr/r/mysql-wsrep-features#29.result | 14 +
.../galera_sr/r/mysql-wsrep-features#32.result | 27 +
.../galera_sr/r/mysql-wsrep-features#35.result | 26 +
.../galera_sr/r/mysql-wsrep-features#8.result | 27 +
.../galera_sr/r/mysql-wsrep-features#9.result | 12 +
.../galera_sr/r/mysql-wsrep-features#93.result | 15 +
.../galera_sr/r/mysql-wsrep-features#96.result | 26 +
mysql-test/suite/galera_sr/t/GCF-1008.inc | 36 +
mysql-test/suite/galera_sr/t/GCF-1008.test | 18 +
mysql-test/suite/galera_sr/t/GCF-1018.test | 38 +
mysql-test/suite/galera_sr/t/GCF-1018B.test | 40 +
mysql-test/suite/galera_sr/t/GCF-1043A.test | 13 +
mysql-test/suite/galera_sr/t/GCF-1043B.test | 13 +
mysql-test/suite/galera_sr/t/GCF-1051.test | 52 +
mysql-test/suite/galera_sr/t/GCF-1060.test | 9 +
mysql-test/suite/galera_sr/t/GCF-437.test | 21 +
mysql-test/suite/galera_sr/t/GCF-561.test | 65 +
mysql-test/suite/galera_sr/t/GCF-571.test | 54 +
mysql-test/suite/galera_sr/t/GCF-572.test | 54 +
mysql-test/suite/galera_sr/t/GCF-574.test | 27 +
mysql-test/suite/galera_sr/t/GCF-580.test | 27 +
mysql-test/suite/galera_sr/t/GCF-585.test | 44 +
mysql-test/suite/galera_sr/t/GCF-597.test | 29 +
mysql-test/suite/galera_sr/t/GCF-620.test | 22 +
mysql-test/suite/galera_sr/t/GCF-623.test | 31 +
mysql-test/suite/galera_sr/t/GCF-627.test | 30 +
mysql-test/suite/galera_sr/t/GCF-845.test | 30 +
mysql-test/suite/galera_sr/t/GCF-851.test | 24 +
mysql-test/suite/galera_sr/t/GCF-867.test | 42 +
mysql-test/suite/galera_sr/t/GCF-889.test | 28 +
mysql-test/suite/galera_sr/t/GCF-900.test | 28 +
mysql-test/suite/galera_sr/t/disabled.def | 4 +
.../suite/galera_sr/t/galera-features#56.test | 55 +
.../suite/galera_sr/t/galera_sr_bf_abort.inc | 145 ++
.../suite/galera_sr/t/galera_sr_bf_abort.test | 48 +
mysql-test/suite/galera_sr/t/galera_sr_blob.test | 38 +
.../suite/galera_sr/t/galera_sr_cc_master.test | 87 +
.../suite/galera_sr/t/galera_sr_cc_slave.test | 86 +
.../suite/galera_sr/t/galera_sr_concurrent.test | 45 +
.../suite/galera_sr/t/galera_sr_conflict.test | 45 +
.../galera_sr/t/galera_sr_conflict_on_commit.test | 45 +
.../galera_sr/t/galera_sr_conflict_on_commit2.test | 46 +
.../t/galera_sr_conflict_with_rollback_master.test | 44 +
.../suite/galera_sr/t/galera_sr_ddl_master.test | 63 +
.../suite/galera_sr/t/galera_sr_ddl_schema.test | 43 +
.../suite/galera_sr/t/galera_sr_ddl_slave.test | 65 +
.../suite/galera_sr/t/galera_sr_ddl_unrelated.test | 53 +
.../suite/galera_sr/t/galera_sr_dupkey_error.test | 59 +
.../suite/galera_sr/t/galera_sr_fk_conflict.test | 62 +
.../suite/galera_sr/t/galera_sr_gtid-master.opt | 1 +
mysql-test/suite/galera_sr/t/galera_sr_gtid.test | 46 +
.../suite/galera_sr/t/galera_sr_insert_select.test | 33 +
.../t/galera_sr_kill_all_nobootstrap.test | 52 +
.../galera_sr/t/galera_sr_kill_all_norecovery.cnf | 4 +
.../galera_sr/t/galera_sr_kill_all_norecovery.test | 53 +
.../galera_sr/t/galera_sr_kill_all_pcrecovery.test | 54 +
.../galera_sr/t/galera_sr_kill_connection.test | 59 +
.../suite/galera_sr/t/galera_sr_kill_query.test | 53 +
.../suite/galera_sr/t/galera_sr_kill_slave.cnf | 4 +
.../suite/galera_sr/t/galera_sr_kill_slave.test | 80 +
.../t/galera_sr_large_fragment-master.opt | 1 +
.../galera_sr/t/galera_sr_large_fragment.test | 58 +
.../suite/galera_sr/t/galera_sr_load_data.test | 39 +
.../galera_sr/t/galera_sr_load_data_splitting.test | 50 +
.../suite/galera_sr/t/galera_sr_log_bin-master.opt | 1 +
.../suite/galera_sr/t/galera_sr_log_bin.test | 70 +
.../galera_sr/t/galera_sr_many_fragments.test | 53 +
mysql-test/suite/galera_sr/t/galera_sr_myisam.test | 29 +
.../suite/galera_sr/t/galera_sr_mysqldump_sst.cnf | 11 +
.../suite/galera_sr/t/galera_sr_mysqldump_sst.test | 79 +
.../galera_sr/t/galera_sr_parallel_apply.test | 59 +
.../suite/galera_sr/t/galera_sr_rollback.test | 76 +
.../galera_sr/t/galera_sr_rollback_retry.test | 55 +
.../galera_sr/t/galera_sr_rollback_savepoint.test | 51 +
.../galera_sr/t/galera_sr_rollback_statement.test | 61 +
mysql-test/suite/galera_sr/t/galera_sr_sbr.test | 31 +
.../galera_sr/t/galera_sr_shutdown_master.test | 45 +
.../galera_sr/t/galera_sr_shutdown_slave.test | 63 +
.../suite/galera_sr/t/galera_sr_small_gcache.cnf | 6 +
.../suite/galera_sr/t/galera_sr_small_gcache.test | 21 +
.../galera_sr/t/galera_sr_table_contents.test | 49 +
.../galera_sr/t/galera_sr_transaction_replay.test | 260 ++
.../galera_sr/t/galera_sr_unit_statements.test | 47 +
.../galera_sr/t/galera_sr_v1_row_events-master.opt | 1 +
.../suite/galera_sr/t/galera_sr_v1_row_events.test | 27 +
.../suite/galera_sr/t/galera_sr_ws_size.test | 70 +
.../suite/galera_sr/t/galera_sr_ws_size2.test | 62 +
.../t/galera_var_ignore_apply_errors_sr.test | 37 +
mysql-test/suite/galera_sr/t/mysql-wsrep#215.test | 161 ++
.../t/mysql-wsrep-features#136-master.opt | 1 +
.../galera_sr/t/mysql-wsrep-features#136.test | 41 +
.../galera_sr/t/mysql-wsrep-features#138.test | 25 +
.../suite/galera_sr/t/mysql-wsrep-features#14.test | 21 +
.../galera_sr/t/mysql-wsrep-features#148.test | 60 +
.../suite/galera_sr/t/mysql-wsrep-features#15.test | 17 +
.../suite/galera_sr/t/mysql-wsrep-features#165.inc | 104 +
.../galera_sr/t/mysql-wsrep-features#165.test | 41 +
.../galera_sr/t/mysql-wsrep-features#213.test | 63 +
.../galera_sr/t/mysql-wsrep-features#214.test | 86 +
.../suite/galera_sr/t/mysql-wsrep-features#22.test | 47 +
.../suite/galera_sr/t/mysql-wsrep-features#27.test | 29 +
.../suite/galera_sr/t/mysql-wsrep-features#29.test | 23 +
.../galera_sr/t/mysql-wsrep-features#32-master.opt | 1 +
.../suite/galera_sr/t/mysql-wsrep-features#32.test | 44 +
.../suite/galera_sr/t/mysql-wsrep-features#35.test | 46 +
.../suite/galera_sr/t/mysql-wsrep-features#8.test | 63 +
.../suite/galera_sr/t/mysql-wsrep-features#9.test | 44 +
.../suite/galera_sr/t/mysql-wsrep-features#93.test | 29 +
.../suite/galera_sr/t/mysql-wsrep-features#96.test | 45 +
.../suite/innodb/r/innodb-index-online-fk.result | 10 +-
mysql-test/suite/innodb/t/galera.skip | 53 +
.../suite/innodb/t/innodb-index-online-fk.test | 10 +-
packaging/deb-in/CMakeLists.txt | 357 +++
plugin/wsrep_info/plugin.cc | 2 +
scripts/mysqld_safe.sh | 11 +-
scripts/wsrep_sst_mysqldump.sh | 1 +
scripts/wsrep_sst_xtrabackup-v2.sh | 2 +-
sql/CMakeLists.txt | 20 +-
sql/event_data_objects.cc | 13 +-
sql/events.cc | 1 -
sql/ha_partition.cc | 7 +
sql/ha_partition.h | 3 +
sql/handler.cc | 282 ++-
sql/handler.h | 4 +
sql/item_create.cc | 101 +
sql/item_func.cc | 5 +-
sql/item_strfunc.cc | 99 +
sql/item_strfunc.h | 51 +
sql/lock.cc | 82 +-
sql/log.cc | 258 +-
sql/log.h | 19 +
sql/log_event.cc | 38 +-
sql/mdl.cc | 79 +-
sql/mysqld.cc | 83 +-
sql/protocol.cc | 20 +-
sql/service_wsrep.cc | 335 +++
sql/slave.cc | 122 +-
sql/sp_head.cc | 29 +-
sql/sql_acl.cc | 5 +-
sql/sql_base.cc | 26 +-
sql/sql_class.cc | 158 +-
sql/sql_class.h | 148 +-
sql/sql_connect.cc | 31 +-
sql/sql_insert.cc | 98 +-
sql/sql_lex.cc | 5 +-
sql/sql_load.cc | 9 +-
sql/sql_parse.cc | 680 ++---
sql/sql_parse.h | 6 +
sql/sql_plugin.cc | 6 +-
sql/sql_plugin_services.ic | 30 +-
sql/sql_prepare.cc | 48 -
sql/sql_repl.cc | 11 +
sql/sql_table.cc | 32 +-
sql/sql_trigger.cc | 2 +-
sql/sql_truncate.cc | 15 +-
sql/sys_vars.cc | 40 +-
sql/table.cc | 7 +
sql/table_cache.cc | 32 +-
sql/transaction.cc | 55 +-
sql/wsrep_applier.cc | 314 +--
sql/wsrep_applier.h | 66 +-
sql/wsrep_binlog.cc | 349 ++-
sql/wsrep_binlog.h | 64 +-
sql/wsrep_client_service.cc | 300 +++
sql/wsrep_client_service.h | 64 +
sql/wsrep_client_state.h | 47 +
sql/wsrep_condition_variable.h | 54 +
sql/wsrep_dummy.cc | 9 +-
sql/wsrep_high_priority_service.cc | 681 +++++
sql/wsrep_high_priority_service.h | 118 +
sql/wsrep_hton.cc | 1 +
sql/wsrep_mutex.h | 50 +
sql/wsrep_mysqld.cc | 2612 +++++++++++---------
sql/wsrep_mysqld.h | 448 +++-
sql/wsrep_notify.cc | 1 +
sql/wsrep_plugin.cc | 53 +
sql/wsrep_priv.h | 13 +-
sql/wsrep_schema.cc | 1319 ++++++++++
sql/wsrep_schema.h | 167 ++
sql/wsrep_server_service.cc | 277 +++
sql/wsrep_server_service.h | 75 +
sql/wsrep_server_state.cc | 78 +
sql/wsrep_server_state.h | 68 +
sql/wsrep_sst.cc | 421 ++--
sql/wsrep_sst.h | 28 +-
sql/wsrep_storage_service.cc | 244 ++
sql/wsrep_storage_service.h | 48 +
sql/wsrep_tc.h | 0
sql/wsrep_thd.cc | 708 ++----
sql/wsrep_thd.h | 217 +-
sql/wsrep_thd_pool.cc | 125 +
sql/wsrep_thd_pool.h | 37 +
sql/wsrep_trans_observer.h | 369 +++
sql/wsrep_types.h | 29 +
sql/wsrep_utils.cc | 2 +
sql/wsrep_utils.h | 32 +
sql/wsrep_var.cc | 253 +-
sql/wsrep_var.h | 6 +-
sql/wsrep_xid.cc | 112 +-
sql/wsrep_xid.h | 18 +-
storage/innobase/buf/buf0dump.cc | 5 +-
storage/innobase/handler/ha_innodb.cc | 409 ++-
storage/innobase/handler/ha_innodb.h | 33 +-
storage/innobase/include/ha_prototypes.h | 10 +-
storage/innobase/include/trx0trx.h | 17 +
storage/innobase/lock/lock0lock.cc | 47 +-
storage/innobase/lock/lock0wait.cc | 12 +-
storage/innobase/row/row0ins.cc | 50 +-
storage/innobase/row/row0sel.cc | 14 +
storage/innobase/row/row0upd.cc | 20 +-
storage/innobase/srv/srv0conc.cc | 7 +-
storage/innobase/srv/srv0srv.cc | 4 +-
storage/innobase/trx/trx0roll.cc | 5 +
storage/innobase/trx/trx0rseg.cc | 17 +-
storage/innobase/trx/trx0trx.cc | 3 +
wsrep-lib | 1 +
wsrep/CMakeLists.txt | 26 -
wsrep/wsrep_api.h | 539 ++--
wsrep/wsrep_dummy.c | 114 +-
wsrep/wsrep_gtid.c | 2 +-
wsrep/wsrep_listener.c | 261 ++
wsrep/wsrep_loader.c | 28 +-
wsrep/wsrep_uuid.c | 11 +
878 files changed, 34996 insertions(+), 4897 deletions(-)
diff --git a/.gitmodules b/.gitmodules
index 6419657e501..61d4c06dd4e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,7 @@
[submodule "storage/rocksdb/rocksdb"]
path = storage/rocksdb/rocksdb
url = https://github.com/facebook/rocksdb.git
+[submodule "wsrep-lib"]
+ path = wsrep-lib
+ url = https://github.com/codership/wsrep-lib.git
+ branch = master
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 93146fa94e9..73aa8638ce8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -382,6 +382,16 @@ INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb)
# Add storage engines and plugins.
CONFIGURE_PLUGINS()
+IF(WITH_WSREP)
+# ADD_SUBDIRECTORY(wsrep)
+# INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep)
+ADD_SUBDIRECTORY(wsrep-lib)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26)
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/wsrep-lib/src)
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/wsrep-lib/wsrep-API)
+ENDIF()
+
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(dbug)
ADD_SUBDIRECTORY(strings)
@@ -403,10 +413,6 @@ IF(NOT WITHOUT_SERVER)
ADD_SUBDIRECTORY(unittest/embedded)
ENDIF(WITH_EMBEDDED_SERVER)
- IF(WITH_WSREP)
- ADD_SUBDIRECTORY(wsrep)
- ENDIF()
-
ADD_SUBDIRECTORY(mysql-test)
ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess)
ADD_SUBDIRECTORY(sql-bench)
@@ -426,7 +432,7 @@ INCLUDE(cmake/tags.cmake)
-INCLUDE(for_clients)
+#INCLUDE(for_clients)
ADD_SUBDIRECTORY(scripts)
ADD_SUBDIRECTORY(support-files)
diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake
index 5a5fcd616fc..61fe26da9ef 100644
--- a/cmake/plugin.cmake
+++ b/cmake/plugin.cmake
@@ -42,6 +42,10 @@ MACRO(MYSQL_ADD_PLUGIN)
${PCRE_INCLUDES}
${SSL_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIR})
+IF(WITH_WSREP)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/include)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26)
+ENDIF()
LIST(GET ARG_UNPARSED_ARGUMENTS 0 plugin)
SET(SOURCES ${ARG_UNPARSED_ARGUMENTS})
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake
index 9fa127380a4..3d77ef754ae 100644
--- a/cmake/wsrep.cmake
+++ b/cmake/wsrep.cmake
@@ -26,7 +26,7 @@ ENDIF()
OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default})
# Set the patch version
-SET(WSREP_PATCH_VERSION "23")
+SET(WSREP_PATCH_VERSION "22")
# Obtain wsrep API version
FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION
diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt
index 7df5fa17903..08745ea1e61 100644
--- a/extra/mariabackup/CMakeLists.txt
+++ b/extra/mariabackup/CMakeLists.txt
@@ -41,7 +41,7 @@ IF(NOT HAVE_SYSTEM_REGEX)
ENDIF()
IF(WITH_WSREP)
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib)
ENDIF()
ADD_DEFINITIONS(-UMYSQL_SERVER)
diff --git a/extra/mariabackup/wsrep.cc b/extra/mariabackup/wsrep.cc
index c3ad1b53a21..793a2a0eb21 100644
--- a/extra/mariabackup/wsrep.cc
+++ b/extra/mariabackup/wsrep.cc
@@ -83,7 +83,7 @@ xb_write_galera_info(bool incremental_prepare)
}
wsrep_uuid_t uuid;
- memcpy(uuid.data, wsrep_xid_uuid(&xid), sizeof(uuid.data));
+ memcpy(uuid.data, get_wsrep_xid_uuid(&xid), sizeof(uuid.data));
if (wsrep_uuid_print(&uuid, uuid_str,
sizeof(uuid_str)) < 0) {
return;
@@ -99,7 +99,7 @@ xb_write_galera_info(bool incremental_prepare)
exit(EXIT_FAILURE);
}
- seqno = wsrep_xid_seqno(&xid);
+ seqno = get_wsrep_xid_seqno(&xid);
msg("mariabackup: Recovered WSREP position: %s:%lld\n",
uuid_str, (long long) seqno);
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h
index cefba6303fe..82fecdb3d2e 100644
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@ -1,19 +1,13 @@
#ifndef MYSQL_SERVICE_WSREP_INCLUDED
-/* Copyright (c) 2015 MariaDB Corporation Ab
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
+#define MYSQL_SERVICE_WSREP_INCLUDED
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED))
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#else
+/* Copyright (c) 2015 MariaDB Corporation Ab
+ 2018 Codership Oy <info(a)codership.com>
+*/
/**
@file
wsrep service
@@ -21,11 +15,9 @@
Interface to WSREP functionality in the server.
For engines that want to support galera.
*/
-
+#include <my_pthread.h>
#ifdef __cplusplus
-extern "C" {
#endif
-
enum wsrep_conflict_state {
NO_CONFLICT,
MUST_ABORT,
@@ -48,7 +40,8 @@ enum wsrep_exec_mode {
Transaction procession after it has been replicated in prepare stage and
has passed certification.
*/
- LOCAL_COMMIT
+ LOCAL_COMMIT,
+ LOCAL_ROLLBACK,
};
enum wsrep_query_state {
@@ -56,7 +49,6 @@ enum wsrep_query_state {
QUERY_EXEC,
QUERY_COMMITTING,
QUERY_EXITING,
- QUERY_ROLLINGBACK,
};
enum wsrep_trx_status {
@@ -65,14 +57,11 @@ enum wsrep_trx_status {
WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */
WSREP_TRX_ERROR, /* native mysql error */
};
-
struct xid_t;
-struct wsrep;
struct wsrep_ws_handle;
struct wsrep_buf;
extern struct wsrep_service_st {
- struct wsrep * (*get_wsrep_func)();
my_bool (*get_wsrep_certify_nonPK_func)();
my_bool (*get_wsrep_debug_func)();
my_bool (*get_wsrep_drupal_282555_workaround_func)();
@@ -80,43 +69,32 @@ extern struct wsrep_service_st {
my_bool (*get_wsrep_load_data_splitting_func)();
my_bool (*get_wsrep_log_conflicts_func)();
long (*get_wsrep_protocol_version_func)();
- my_bool (*wsrep_aborting_thd_contains_func)(THD *thd);
- void (*wsrep_aborting_thd_enqueue_func)(THD *thd);
bool (*wsrep_consistency_check_func)(THD *thd);
- int (*wsrep_is_wsrep_xid_func)(const struct xid_t *xid);
+ int (*wsrep_is_wsrep_xid_func)(const void *xid);
long long (*wsrep_xid_seqno_func)(const struct xid_t *xid);
const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid);
- void (*wsrep_lock_rollback_func)();
- int (*wsrep_on_func)(MYSQL_THD);
- void (*wsrep_post_commit_func)(THD* thd, bool all);
- bool (*wsrep_prepare_key_func)(const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*);
- enum wsrep_trx_status (*wsrep_run_wsrep_commit_func)(THD *thd, bool all);
- void (*wsrep_thd_LOCK_func)(THD *thd);
- void (*wsrep_thd_UNLOCK_func)(THD *thd);
- void (*wsrep_thd_awake_func)(THD *thd, my_bool signal);
- enum wsrep_conflict_state (*wsrep_thd_conflict_state_func)(MYSQL_THD, my_bool);
- const char * (*wsrep_thd_conflict_state_str_func)(THD *thd);
- enum wsrep_exec_mode (*wsrep_thd_exec_mode_func)(THD *thd);
- const char * (*wsrep_thd_exec_mode_str_func)(THD *thd);
- enum wsrep_conflict_state (*wsrep_thd_get_conflict_state_func)(MYSQL_THD);
- my_bool (*wsrep_thd_is_BF_func)(MYSQL_THD , my_bool);
- my_bool (*wsrep_thd_is_wsrep_func)(MYSQL_THD thd);
- char * (*wsrep_thd_query_func)(THD *thd);
- enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd);
- const char * (*wsrep_thd_query_state_str_func)(THD *thd);
- int (*wsrep_thd_retry_counter_func)(THD *thd);
- void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state);
+ my_bool (*wsrep_on_func)(const void *);
+ bool (*wsrep_prepare_key_for_innodb_func)(THD* thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*);
+ void (*wsrep_thd_LOCK_func)(const void* thd_ptr);
+ void (*wsrep_thd_UNLOCK_func)(const void* thd_ptr);
+ void (*wsrep_thd_awake_func)(const void* thd, my_bool signal);
+ my_thread_id (*wsrep_thd_thread_id_func)(const void* thd);
+ my_bool (*wsrep_thd_is_wsrep_on_func)(const void* thd);
+ const char * (*wsrep_thd_query_func)(const void* thd);
bool (*wsrep_thd_ignore_table_func)(THD *thd);
- long long (*wsrep_thd_trx_seqno_func)(THD *thd);
- struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd);
- int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd);
- int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD);
- void (*wsrep_unlock_rollback_func)();
+ long long (*wsrep_thd_trx_seqno_func)(const void* thd);
+ my_bool (*wsrep_thd_is_aborting_func)(const void* thd);
+ my_bool (*wsrep_trx_order_before_func)(const void* left_ptr, const void* right_ptr);
+ void (*wsrep_thd_xid_func)(const void *thd_ptr, void *xid, size_t xid_size);
void (*wsrep_set_data_home_dir_func)(const char *data_dir);
} *wsrep_service;
+#define MYSQL_SERVICE_WSREP_INCLUDED
+#endif
+
#ifdef MYSQL_DYNAMIC_PLUGIN
-#define get_wsrep() wsrep_service->get_wsrep_func()
+
+#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED
#define get_wsrep_certify_nonPK() wsrep_service->get_wsrep_certify_nonPK_func()
#define get_wsrep_debug() wsrep_service->get_wsrep_debug_func()
#define get_wsrep_drupal_282555_workaround() wsrep_service->get_wsrep_drupal_282555_workaround_func()
@@ -124,50 +102,31 @@ extern struct wsrep_service_st {
#define get_wsrep_load_data_splitting() wsrep_service->get_wsrep_load_data_splitting_func()
#define get_wsrep_log_conflicts() wsrep_service->get_wsrep_log_conflicts_func()
#define get_wsrep_protocol_version() wsrep_service->get_wsrep_protocol_version_func()
-#define wsrep_aborting_thd_contains(T) wsrep_service->wsrep_aborting_thd_contains_func(T)
-#define wsrep_aborting_thd_enqueue(T) wsrep_service->wsrep_aborting_thd_enqueue_func(T)
#define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T)
#define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X)
-#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X)
-#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X)
-#define wsrep_lock_rollback() wsrep_service->wsrep_lock_rollback_func()
+#define get_wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X)
+#define get_wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X)
#define wsrep_on(X) wsrep_service->wsrep_on_func(X)
-#define wsrep_post_commit(T,A) wsrep_service->wsrep_post_commit_func(T,A)
-#define wsrep_prepare_key(A,B,C,D,E,F) wsrep_service->wsrep_prepare_key_func(A,B,C,D,E,F)
-#define wsrep_run_wsrep_commit(T,A) wsrep_service->wsrep_run_wsrep_commit_func(T,A)
+#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F.G)
#define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T)
#define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T)
#define wsrep_thd_awake(T,S) wsrep_service->wsrep_thd_awake_func(T,S)
-#define wsrep_thd_conflict_state(T,S) wsrep_service->wsrep_thd_conflict_state_func(T,S)
-#define wsrep_thd_conflict_state_str(T) wsrep_service->wsrep_thd_conflict_state_str_func(T)
-#define wsrep_thd_exec_mode(T) wsrep_service->wsrep_thd_exec_mode_func(T)
-#define wsrep_thd_exec_mode_str(T) wsrep_service->wsrep_thd_exec_mode_str_func(T)
-#define wsrep_thd_get_conflict_state(T) wsrep_service->wsrep_thd_get_conflict_state_func(T)
-#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S)
-#define wsrep_thd_is_wsrep(T) wsrep_service->wsrep_thd_is_wsrep_func(T)
+#define wsrep_thd_thread_id(T) wsrep_service->wsrep_thd_thread_id_func(T)
+#define wsrep_thd_is_wsrep_on(T) wsrep_service->wsrep_thd_is_wsrep_on_func(T)
#define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T)
-#define wsrep_thd_query_state(T) wsrep_service->wsrep_thd_query_state_func(T)
-#define wsrep_thd_query_state_str(T) wsrep_service->wsrep_thd_query_state_str_func(T)
#define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T)
-#define wsrep_thd_set_conflict_state(T,S) wsrep_service->wsrep_thd_set_conflict_state_func(T,S)
#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T)
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
-#define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T)
#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T)
#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2)
-#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func()
+#define wsrep_thd_xid(T,X,S) wsrep_service->wsrep_thd_xid_func(T,X,S)
#define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A)
-#define wsrep_debug get_wsrep_debug()
-#define wsrep_log_conflicts get_wsrep_log_conflicts()
-#define wsrep_certify_nonPK get_wsrep_certify_nonPK()
-#define wsrep_load_data_splitting get_wsrep_load_data_splitting()
-#define wsrep_drupal_282555_workaround get_wsrep_drupal_282555_workaround()
-#define wsrep_recovery get_wsrep_recovery()
-#define wsrep_protocol_version get_wsrep_protocol_version()
+#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S)
#else
+#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED
extern my_bool wsrep_debug;
extern my_bool wsrep_log_conflicts;
extern my_bool wsrep_certify_nonPK;
@@ -175,27 +134,19 @@ extern my_bool wsrep_load_data_splitting;
extern my_bool wsrep_drupal_282555_workaround;
extern my_bool wsrep_recovery;
extern long wsrep_protocol_version;
-
+extern my_thread_id wsrep_thd_thread_id(THD *thd);
+
bool wsrep_consistency_check(THD *thd);
-bool wsrep_prepare_key(const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len);
-char *wsrep_thd_query(THD *thd);
-const char *wsrep_thd_conflict_state_str(THD *thd);
-const char *wsrep_thd_exec_mode_str(THD *thd);
-const char *wsrep_thd_query_state_str(THD *thd);
-enum wsrep_conflict_state wsrep_thd_conflict_state(MYSQL_THD thd, my_bool sync);
-enum wsrep_conflict_state wsrep_thd_get_conflict_state(MYSQL_THD thd);
-enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
-enum wsrep_query_state wsrep_thd_query_state(THD *thd);
-enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, bool all);
-int wsrep_is_wsrep_xid(const struct xid_t* xid);
-long long wsrep_xid_seqno(const struct xid_t* xid);
-const unsigned char* wsrep_xid_uuid(const struct xid_t* xid);
-int wsrep_on(MYSQL_THD thd);
+bool wsrep_prepare_key_for_innodb(THD* thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len);
+extern "C" const char *wsrep_thd_query(const void* thd);
+int wsrep_is_wsrep_xid(const void* xid);
+extern "C" long long get_wsrep_xid_seqno(const struct xid_t* xid);
+const unsigned char* get_wsrep_xid_uuid(const struct xid_t* xid);
int wsrep_thd_retry_counter(THD *thd);
-int wsrep_trx_is_aborting(MYSQL_THD thd);
-int wsrep_trx_order_before(MYSQL_THD thd1, MYSQL_THD thd2);
+my_bool wsrep_trx_is_aborting(const void* thd);
+my_bool wsrep_trx_order_before(const void* thd1, const void* thd2);
long get_wsrep_protocol_version();
-long long wsrep_thd_trx_seqno(THD *thd);
+extern "C" long long wsrep_thd_trx_seqno(const void* thd);
my_bool get_wsrep_certify_nonPK();
my_bool get_wsrep_debug();
my_bool get_wsrep_drupal_282555_workaround();
@@ -203,27 +154,99 @@ my_bool get_wsrep_recovery();
my_bool get_wsrep_load_data_splitting();
my_bool get_wsrep_log_conflicts();
my_bool wsrep_aborting_thd_contains(THD *thd);
-my_bool wsrep_thd_is_BF(MYSQL_THD thd, my_bool sync);
-my_bool wsrep_thd_is_wsrep(MYSQL_THD thd);
-struct wsrep *get_wsrep();
+my_bool wsrep_thd_is_wsrep(const void* thd);
struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd);
void wsrep_aborting_thd_enqueue(THD *thd);
-void wsrep_lock_rollback();
void wsrep_post_commit(THD* thd, bool all);
-void wsrep_thd_LOCK(THD *thd);
-void wsrep_thd_UNLOCK(THD *thd);
-void wsrep_thd_awake(THD *thd, my_bool signal);
-void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state);
bool wsrep_thd_ignore_table(THD *thd);
-void wsrep_unlock_rollback();
void wsrep_set_data_home_dir(const char *data_dir);
-#endif
+/* from mysql wsrep-lib */
+#include "my_global.h"
+#include "my_pthread.h"
+/* Must match to definition in sql/mysqld.h */
+typedef int64 query_id_t;
+
+extern "C" my_bool wsrep_global_on();
+
+/* Return true if wsrep is enabled for a thd. This means that
+ wsrep is enabled globally and the thd has wsrep on */
+extern "C" my_bool wsrep_on(const void* thd);
+/* Lock thd wsrep lock */
+extern "C" void wsrep_thd_LOCK(const void* thd);
+/* Unlock thd wsrep lock */
+extern "C" void wsrep_thd_UNLOCK(const void* thd);
+
+/* Return true if thd has wsrep_on */
+extern "C" my_bool wsrep_thd_is_wsrep_on(const void* thd);
+/* Return thd id */
+extern "C" my_thread_id wsrep_thd_thread_id(const void* thd);
+
+/* Return thd client state string */
+extern "C" const char* wsrep_thd_client_state_str(const void* thd);
+/* Return thd client mode string */
+extern "C" const char* wsrep_thd_client_mode_str(const void* thd);
+/* Return thd transaction state string */
+extern "C" const char* wsrep_thd_transaction_state_str(const void* thd);
+
+/* Return current query id */
+extern "C" query_id_t wsrep_thd_query_id(const void* thd);
+/* Return current transaction id */
+extern "C" query_id_t wsrep_thd_transaction_id(const void* thd);
+/* Mark thd own transaction as aborted */
+extern "C" void wsrep_thd_self_abort(void *thd);
+/* Return true if thd is in replicating mode */
+extern "C" my_bool wsrep_thd_is_local(const void *thd);
+/* Return true if thd is in high priority mode */
+/* todo: rename to is_high_priority() */
+extern "C" my_bool wsrep_thd_is_applying(const void *thd);
+/* Return true if thd is in TOI mode */
+extern "C" my_bool wsrep_thd_is_toi(const void* thd);
+/* Return true if thd is in replicating TOI mode */
+extern "C" my_bool wsrep_thd_is_local_toi(const void* thd);
+/* Return true if thd is in RSU mode */
+extern "C" my_bool wsrep_thd_is_in_rsu(const void* thd);
+/* Return true if thd is in BF mode, either high_priority or TOI */
+extern "C" my_bool wsrep_thd_is_BF(const void* thd, my_bool sync);
+/* Return true if thd is streaming */
+extern "C" my_bool wsrep_thd_is_SR(const void* thd);
+extern "C" void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr);
+/* Return XID associated to thd */
+extern "C" void wsrep_thd_xid(const void* thd, void* xid, size_t size);
+/* Return thd retry counter */
+extern "C" int wsrep_thd_retry_counter(const void*);
+/* Signal thd to awake from wait */
+extern "C" void wsrep_thd_awake(const void* thd, my_bool signal);
+/* BF abort victim_thd */
+extern "C" my_bool wsrep_thd_bf_abort(const void* bf_thd, void* victim_thd,
+ my_bool signal);
+/* Return true if left thd is ordered before right thd */
+extern "C" my_bool wsrep_thd_order_before(const void* left, const void* right);
+/* Return true if thd should skip locking. This means that the thd
+ is operating on shared resource inside commit order critical section. */
+extern "C" my_bool wsrep_thd_skip_locking(const void*);
+/* Return true if thd is aborting */
+extern "C" my_bool wsrep_thd_is_aborting(const void*);
+
+
+enum Wsrep_key_type
+{
+ wsrep_key_shared,
+ wsrep_key_semi_shared,
+ wsrep_key_semi_exclusive,
+ wsrep_key_exclusive
+};
+struct wsrep_key;
+struct wsrep_key_array;
+extern "C" int wsrep_thd_append_key(void*,
+ const struct wsrep_key* key,
+ int n_keys,
+ enum Wsrep_key_type);
#ifdef __cplusplus
-}
-#endif
+#include <string>
+extern const std::string sr_table_name_full_str;
+#endif /* __cplusplus */
-#define MYSQL_SERVICE_WSREP_INCLUDED
#endif
-
+#endif /* MYSQL_SERVICE_WSREP_INCLUDED */
diff --git a/include/thr_lock.h b/include/thr_lock.h
index e6451bf21c4..b775e846681 100644
--- a/include/thr_lock.h
+++ b/include/thr_lock.h
@@ -168,9 +168,9 @@ void thr_set_lock_wait_callback(void (*before_wait)(void),
void (*after_wait)(void));
#ifdef WITH_WSREP
- typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
- typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
- typedef int (* wsrep_on_fun)(void *);
+ typedef my_bool (* wsrep_thd_is_brute_force_fun)(const void *, my_bool);
+ typedef my_bool(* wsrep_abort_thd_fun)(const void *, void *, my_bool);
+ typedef my_bool (* wsrep_on_fun)(const void *);
void wsrep_thr_lock_init(
wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun,
my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun);
diff --git a/include/wsrep.h b/include/wsrep.h
index c7f598906bb..77d50fc7678 100644
--- a/include/wsrep.h
+++ b/include/wsrep.h
@@ -28,12 +28,14 @@
goto error;
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \
- if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, \
- table_list_, alter_info_)) \
+ if (WSREP_ON && WSREP(thd) && wsrep_thd_is_local(thd) && \
+ wsrep_to_isolation_begin(thd, db_, table_, \
+ table_list_, alter_info_)) \
goto error;
-#define WSREP_TO_ISOLATION_END \
- if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \
+#define WSREP_TO_ISOLATION_END \
+ if ((WSREP(thd) && thd && wsrep_thd_is_local_toi(thd)) || \
+ wsrep_thd_is_in_rsu(thd)) \
wsrep_to_isolation_end(thd);
/*
@@ -44,6 +46,11 @@
if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error;
+#define WSREP_SYNC_WAIT(thd_, before_) \
+ { if (WSREP_CLIENT(thd_) && \
+ wsrep_sync_wait(thd_, before_)) goto error; }
+
+
#define WSREP_DEBUG(...) \
if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
@@ -55,18 +62,17 @@
wsrep_sync_wait(thd_, before_)) goto error; }
#else
-#define IF_WSREP(A,B) B
-#define DBUG_ASSERT_IF_WSREP(A)
-#define WSREP_DEBUG(...)
-#define WSREP_INFO(...)
-#define WSREP_WARN(...)
-#define WSREP_ERROR(...)
-#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_)
-#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_)
-#define WSREP_TO_ISOLATION_END
-#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)
-#define WSREP_SYNC_WAIT(thd_, before_)
-
+//#define IF_WSREP(A,B) B
+//#define DBUG_ASSERT_IF_WSREP(A)
+//#define WSREP_DEBUG(...)
+//#define WSREP_INFO(...)
+//#define WSREP_WARN(...)
+//#define WSREP_ERROR(...)
+//#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_)
+//#define WSREP_TO_ISOLATION_END
+//#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_)
+//#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)
+//#define WSREP_SYNC_WAIT(thd_, before_)
#endif /* WITH_WSREP */
#endif /* WSREP_INCLUDED */
diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test
index a9c8e13fa7c..ac4a40e8b05 100644
--- a/mysql-test/include/check-testcase.test
+++ b/mysql-test/include/check-testcase.test
@@ -103,5 +103,51 @@ cat_file $datadir.tempfiles.txt;
remove_file $datadir.tempfiles.txt;
list_files $datadir/mysql #sql*;
+#
+# Check that SHOW ENGINE INNODB STATUS does not show any active transactions
+# We do this only if wsrep provider is loaded, to avoid disturbing any non-Galera MTR tests
+#
+
+if (`SELECT @@wsrep_on`) {
+ if (`SELECT COUNT(*) FROM information_schema.innodb_trx WHERE trx_mysql_thread_id != 0`) {
+ if ($before) {
+ --echo Before test start.
+ }
+ if (!$before) {
+ --echo After test end.
+ }
+ --echo There is one or more active InnoDB transaction(s) when there should be none. Dumping some diagnostics.
+
+ --enable_query_log
+
+ SET GLOBAL innodb_status_output_locks=ON;
+ SHOW ENGINE INNODB STATUS;
+ SET GLOBAL innodb_status_output_locks=default;
+
+ --vertical_results
+ if ($before) {
+ --replace_regex /$/ /
+ }
+ SELECT * FROM information_schema.processlist;
+
+ if ($before) {
+ --replace_regex /$/ /
+ }
+ SELECT * FROM information_schema.innodb_trx;
+
+ if ($before) {
+ --replace_regex /$/ /
+ }
+ SELECT * FROM information_schema.innodb_locks;
+
+ if ($before) {
+ --replace_regex /$/ /
+ }
+ SELECT * FROM information_schema.innodb_lock_waits;
+ --horizontal_results
+ --disable_query_log
+ }
+}
+
--enable_query_log
diff --git a/mysql-test/include/galera_cluster.inc b/mysql-test/include/galera_cluster.inc
index c1834c3c26f..7f76ea59c7f 100644
--- a/mysql-test/include/galera_cluster.inc
+++ b/mysql-test/include/galera_cluster.inc
@@ -8,5 +8,11 @@
--let $galera_cluster_size = 2
--source include/galera_init.inc
+--source include/have_innodb.inc
+--source include/galera_wait_ready.inc
+--connection node_2
+--source include/galera_wait_ready.inc
--source include/have_innodb.inc
+
+--connection node_1
diff --git a/mysql-test/suite/galera/include/galera_have_debug_sync.inc b/mysql-test/include/galera_have_debug_sync.inc
similarity index 100%
rename from mysql-test/suite/galera/include/galera_have_debug_sync.inc
rename to mysql-test/include/galera_have_debug_sync.inc
diff --git a/mysql-test/include/galera_wait_sync_point.inc b/mysql-test/include/galera_wait_sync_point.inc
index cf3a4980186..c0951b220b4 100644
--- a/mysql-test/include/galera_wait_sync_point.inc
+++ b/mysql-test/include/galera_wait_sync_point.inc
@@ -1,6 +1,17 @@
--let $wait_timeout = 10
--let $wsrep_on_orig = `SELECT @@wsrep_on`
SET SESSION wsrep_on = 0;
+
+#
+# following is only for debugging purposes
+# should be commented out when test wporks as planned
+#
+#--sleep 1
+# SHOW PROCESSLIST;
+#SHOW STATUS LIKE 'wsrep_%';
+#--echo $galera_sync_point
+
--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = '$galera_sync_point'
--source include/wait_condition.inc
--eval SET SESSION wsrep_on = $wsrep_on_orig
+
diff --git a/mysql-test/include/have_ipv6.inc b/mysql-test/include/have_ipv6.inc
new file mode 100644
index 00000000000..752dd0db53e
--- /dev/null
+++ b/mysql-test/include/have_ipv6.inc
@@ -0,0 +1,20 @@
+# Check if ipv6 is available.
+#
+--disable_query_log
+--disable_result_log
+--disable_abort_on_error
+connect (checkcon123456789,::1,root,,test);
+if($mysql_errno)
+{
+ skip No IPv6 support;
+}
+connection default;
+if(!$mysql_errno)
+{
+ disconnect checkcon123456789;
+}
+--enable_abort_on_error
+--enable_result_log
+--enable_query_log
+# end check
+
diff --git a/mysql-test/include/kill_galera.inc b/mysql-test/include/kill_galera.inc
new file mode 100644
index 00000000000..d7f665df6c7
--- /dev/null
+++ b/mysql-test/include/kill_galera.inc
@@ -0,0 +1,20 @@
+--echo Killing server ...
+
+# Write file to make mysql-test-run.pl expect the crash, but don't start it
+--let $_server_id= `SELECT @@server_id`
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
+--exec echo "wait" > $_expect_file_name
+
+# Kill the connected server
+--disable_reconnect
+--let KILL_NODE_PIDFILE = `SELECT @@pid_file`
+
+--perl
+ my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
+ my $mysqld_pid = `cat $pid_filename`;
+ chomp($mysqld_pid);
+ system("kill -9 $mysqld_pid");
+ exit(0);
+EOF
+
+--source include/wait_until_disconnected.inc
diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql
index b7b2a316dfb..28974cff315 100644
--- a/mysql-test/include/mtr_warnings.sql
+++ b/mysql-test/include/mtr_warnings.sql
@@ -229,6 +229,52 @@ INSERT INTO global_suppressions VALUES
MDEV-12501 -- set --maturity-level by default
*/
("Plugin .* is of maturity level .* while the server is .*"),
+ ("WSREP:*down context*"),
+ ("WSREP: Failed to send state UUID:*"),
+ ("WSREP: wsrep_sst_receive_address is set to '127.0.0.1"),
+ ("WSREP: option --wsrep-causal-reads is deprecated"),
+ ("WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0"),
+ ("WSREP: Could not open saved state file for reading: "),
+ ("WSREP: Could not open state file for reading: "),
+ ("WSREP: access file\\(.*gvwstate\\.dat\\) failed\\(No such file or directory\\)"),
+ ("WSREP: Gap in state sequence\\. Need state transfer\\."),
+ ("WSREP: Failed to prepare for incremental state transfer: Local state UUID \\(00000000-0000-0000-0000-000000000000\\) does not match group state UUID"),
+ ("WSREP: No existing UUID has been found, so we assume that this is the first time that this server has been started\\. Generating a new UUID: "),
+ ("WSREP: last inactive check more than"),
+ ("WSREP: binlog cache not empty \\(0 bytes\\) at connection close"),
+ ("WSREP: SQL statement was ineffective"),
+ ("WSREP: Refusing exit for the last slave thread"),
+ ("WSREP: Quorum: No node with complete state"),
+ ("WSREP: Failed to report last committed"),
+ ("Slave SQL: Error 'Duplicate entry"),
+ ("Query apply warning:"),
+ ("WSREP: Ignoring error"),
+ ("WSREP: Initial position was provided by configuration or SST, avoiding override"),
+ ("Warning: Using a password on the command line interface can be insecure"),
+ ("InnoDB: Error: Table \"mysql\"\\.\"innodb_table_stats\" not found"),
+ ("but it is impossible to select State Transfer donor: Resource temporarily unavailable"),
+ ("WSREP: Could not find peer"),
+ ("WSREP: discarding established \\(time wait\\)"),
+ ("sending install message failed: Resource temporarily unavailable"),
+ ("WSREP: Ignoring possible split-brain \\(allowed by configuration\\) from view"),
+ ("WSREP: no nodes coming from prim view, prim not possible"),
+ ("WSREP: Failed to prepare for incremental state transfer: Local state seqno is undefined:"),
+ ("WSREP: gcs_caused\\(\\) returned -107 \\(Transport endpoint is not connected\\)"),
+ ("WSREP: gcs_caused\\(\\) returned -57 \\(Socket is not connected\\)"),
+ ("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"),
+ ("Action message in non-primary configuration from member"),
+ ("SYNC message from member"),
+ ("InnoDB: Resizing redo log from"),
+ ("InnoDB: Starting to delete and rewrite log files"),
+ ("InnoDB: New log files created, LSN="),
+-- WSREP: Send action {0x7f86280147f0, 73, STATE_REQUEST} returned -107 (Transport endpoint is not connected)
+ ("Transport endpoint is not connected"),
+ ("Socket is not connected"),
+-- "WSREP: Protocol violation. JOIN message sender 1.0 (host-91-221-67-96) is not in state transfer (SYNCED). Message ignored.
+ ("is not in state transfer"),
+ ("JOIN message from member .* in non-primary configuration"),
+ ("install timer expired"),
+ ("Last Applied Action message in non-primary configuration from member"),
("THE_LAST_SUPPRESSION")||
diff --git a/mysql-test/include/restart_mysqld.inc b/mysql-test/include/restart_mysqld.inc
index 3d3e55db4ac..8cf2798b592 100644
--- a/mysql-test/include/restart_mysqld.inc
+++ b/mysql-test/include/restart_mysqld.inc
@@ -5,6 +5,5 @@
# --source include/restart_mysqld.inc
--source include/not_embedded.inc
-
--source include/shutdown_mysqld.inc
--source include/start_mysqld.inc
diff --git a/mysql-test/include/wait_until_connected_again.inc b/mysql-test/include/wait_until_connected_again.inc
index 26168d10558..e0594c37190 100644
--- a/mysql-test/include/wait_until_connected_again.inc
+++ b/mysql-test/include/wait_until_connected_again.inc
@@ -11,7 +11,7 @@ let $counter= 5000;
let $mysql_errno= 9999;
while ($mysql_errno)
{
- --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013
+ --error 0,1205,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013
show status;
dec $counter;
diff --git a/mysql-test/include/wait_wsrep_ready.inc b/mysql-test/include/wait_wsrep_ready.inc
index 2dd1ef7f1ab..7ff65136c92 100644
--- a/mysql-test/include/wait_wsrep_ready.inc
+++ b/mysql-test/include/wait_wsrep_ready.inc
@@ -6,13 +6,26 @@
--disable_query_log
--disable_result_log
+#
+# if node is not ready, SELECT @@GLOBAL.WSREP_ON below does not
+# succeed. However, we can force it to succeed by running the SELECT
+# with dirty reads configuration. So we prepare for that
+#
+--let $my_dirty_reads= `select @@wsrep_dirty_reads`
+SET wsrep_dirty_reads = ON;
+
if (`SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`)
{
if (`SELECT @@GLOBAL.WSREP_ON`)
{
--source include/galera_wait_ready.inc
+ --disable_query_log
+ --disable_result_log
}
}
+# ..and returning original dirty read selection here
+--eval SET wsrep_dirty_reads = $my_dirty_reads;
+
--enable_query_log
--enable_result_log
diff --git a/mysql-test/include/wsrep_wait_disconnect.inc b/mysql-test/include/wsrep_wait_disconnect.inc
new file mode 100644
index 00000000000..740fc0d9426
--- /dev/null
+++ b/mysql-test/include/wsrep_wait_disconnect.inc
@@ -0,0 +1,20 @@
+let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' AND VARIABLE_VALUE = 'OFF';
+# since this is called until AFTER provider disconnects,we need to allow
+# queries in non-prim
+#
+# We are also forced to use a hard-coded value for wsrep_sync_wait here because
+# we can not issue a SELECT query to obtain the original value and then restore
+# it
+disable_query_log;
+SET SESSION wsrep_sync_wait = 7;
+--let $restore_wsrep_on = `SHOW VARIABLES WHERE Variable_name = 'wsrep_on' AND Value = 'ON'`
+SET SESSION wsrep_on = OFF;
+
+--source include/wait_condition.inc
+
+if ($restore_wsrep_on != "")
+{
+ --eval SET SESSION wsrep_on = ON
+}
+SET SESSION wsrep_sync_wait = 15;
+enable_query_log;
diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm
index d481058902f..29271a97387 100644
--- a/mysql-test/lib/My/ConfigFactory.pm
+++ b/mysql-test/lib/My/ConfigFactory.pm
@@ -206,7 +206,11 @@ my @mysqld_rules=
{ '#user' => sub { return shift->{ARGS}->{user} || ""; } },
{ '#password' => sub { return shift->{ARGS}->{password} || ""; } },
{ 'server-id' => \&fix_server_id, },
- { 'bind-address' => \&fix_bind_address },
+ #
+ # bind-address is commented out here, because this would bind bind
+ # only 127.0.0.1 for mysqld, and in galera mtr testing we will need
+ # also 127.0.0.2 for sst address
+# { 'bind-address' => \&fix_bind_address },
);
#
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 28792d2ad01..426821270c3 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -414,6 +414,7 @@ sub main {
}
check_ssl_support();
check_debug_support();
+ check_wsrep_support();
if (!$opt_suites) {
$opt_suites= join ',', collect_default_suites(@DEFAULT_SUITES);
@@ -2902,6 +2903,55 @@ sub mysql_server_wait {
$warn_seconds);
}
+sub have_wsrep() {
+ my $wsrep_on= $mysqld_variables{'wsrep-on'};
+ return defined $wsrep_on
+}
+
+sub wsrep_is_bootstrap_server($) {
+ my $mysqld= shift;
+ return $mysqld->if_exist('wsrep_cluster_address') &&
+ ($mysqld->value('wsrep_cluster_address') eq "gcomm://" ||
+ $mysqld->value('wsrep_cluster_address') eq "'gcomm://'");
+}
+
+sub check_wsrep_support() {
+ if (have_wsrep())
+ {
+ mtr_report(" - binaries built with wsrep patch");
+
+ # ADD scripts to $PATH to that wsrep_sst_* can be found
+ my ($path) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir;
+ mtr_error("No SST scripts") unless $path;
+ $ENV{PATH}="$path:$ENV{PATH}";
+
+ # Check whether WSREP_PROVIDER environment variable is set.
+ if (defined $ENV{'WSREP_PROVIDER'}) {
+ if ((mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") &&
+ ($ENV{'WSREP_PROVIDER'} ne "none")) {
+ mtr_error("WSREP_PROVIDER env set to an invalid path");
+ }
+ # WSREP_PROVIDER is valid; set to a valid path or "none").
+ mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}");
+ } else {
+ # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider
+ # library.
+ my $file_wsrep_provider=
+ mtr_file_exists("/usr/lib/galera/libgalera_smm.so",
+ "/usr/lib64/galera/libgalera_smm.so");
+
+ if ($file_wsrep_provider ne "") {
+ # wsrep provider library found !
+ mtr_verbose("wsrep provider library found : $file_wsrep_provider");
+ $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider;
+ } else {
+ mtr_verbose("Could not find wsrep provider library, setting it to 'none'");
+ $ENV{'WSREP_PROVIDER'}= "none";
+ }
+ }
+ }
+}
+
sub create_config_file_for_extern {
my %opts=
(
@@ -3365,6 +3415,60 @@ sub run_query {
}
+sub run_query_output {
+ my ($mysqld, $query, $outfile)= @_;
+
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
+ mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
+
+ mtr_add_arg($args, "--silent");
+ mtr_add_arg($args, "--execute=%s", $query);
+
+ my $res= My::SafeProcess->run
+ (
+ name => "run_query_output -> ".$mysqld->name(),
+ path => $exe_mysql,
+ args => \$args,
+ output => $outfile,
+ error => $outfile
+ );
+
+ return $res
+}
+
+
+sub wait_wsrep_ready($$) {
+ my ($tinfo, $mysqld)= @_;
+
+ my $sleeptime= 100; # Milliseconds
+ my $loops= ($opt_start_timeout * 1000) / $sleeptime;
+
+ my $name= $mysqld->name();
+ my $outfile= "$opt_vardir/tmp/$name.wsrep_ready";
+ my $query= "SET SESSION wsrep_sync_wait = 0;
+ SELECT VARIABLE_VALUE
+ FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+ WHERE VARIABLE_NAME = 'wsrep_ready'";
+
+ for (my $loop= 1; $loop <= $loops; $loop++)
+ {
+ if (run_query_output($mysqld, $query, $outfile) == 0 &&
+ mtr_grab_file($outfile) =~ /^ON/)
+ {
+ unlink($outfile);
+ return 1;
+ }
+
+ mtr_milli_sleep($sleeptime);
+ }
+
+ $tinfo->{logfile}= "WSREP did not transition to state READY";
+ return 0;
+}
+
+
sub do_before_run_mysqltest($)
{
my $tinfo= shift;
@@ -5413,6 +5517,21 @@ sub start_servers($) {
for (all_servers()) {
$_->{START}->($_, $tinfo) if $_->{START};
+ # If wsrep is on, we need to wait until the first
+ # server starts and bootstraps the cluster before
+ # starting other servers. The bootsrap server in the
+ # configuration should always be the first which has
+ # wsrep_on=ON and should be tagged with "#wsrep-new-cluster".
+ # option
+ if (have_wsrep() && (defined $_->option("#wsrep-new-cluster") ||
+ wsrep_is_bootstrap_server($_)))
+ {
+ mtr_debug("Waiting the first wsrep server to start");
+ if ($_->{WAIT}->($_) && !wait_wsrep_ready($tinfo, $_))
+ {
+ return 1;
+ }
+ }
}
for (all_servers()) {
@@ -5421,7 +5540,13 @@ sub start_servers($) {
$tinfo->{comment}= "Failed to start ".$_->name() . "\n";
return 1;
}
+
+ if (have_wsrep() && !wait_wsrep_ready($tinfo, $_))
+ {
+ return 1;
+ }
}
+
return 0;
}
diff --git a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result
new file mode 100644
index 00000000000..b7db372a704
--- /dev/null
+++ b/mysql-test/r/mysqld--help-notwin.result
@@ -0,0 +1,1472 @@
+The following options may be given as the first argument:
+--print-defaults Print the program argument list and exit.
+--no-defaults Don't read default options from any option file,
+ except for login file.
+--defaults-file=# Only read default options from the given file #.
+--defaults-extra-file=# Read this file after the global files are read.
+--defaults-group-suffix=#
+ Also read groups with concat(group, suffix)
+--login-path=# Read this path from the login file.
+
+ --abort-slave-event-count=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --allow-suspicious-udfs
+ Allows use of UDFs consisting of only one symbol xxx()
+ without corresponding xxx_init() or xxx_deinit(). That
+ also means that one can load any function from any
+ library, for example exit() from libc.so
+ -a, --ansi Use ANSI SQL syntax instead of MySQL syntax. This mode
+ will also set transaction isolation level 'serializable'.
+ --auto-increment-increment[=#]
+ Auto-increment columns are incremented by this
+ --auto-increment-offset[=#]
+ Offset added to Auto-increment columns. Used when
+ auto-increment-increment != 1
+ --autocommit Set default value for autocommit (0 or 1)
+ (Defaults to on; use --skip-autocommit to disable.)
+ --automatic-sp-privileges
+ Creating and dropping stored procedures alters ACLs
+ (Defaults to on; use --skip-automatic-sp-privileges to disable.)
+ --avoid-temporal-upgrade
+ When this option is enabled, the pre-5.6.4 temporal types
+ are not upgraded to the new format for ALTER TABLE
+ requests ADD/CHANGE/MODIFY COLUMN, ADD INDEX or FORCE
+ operation. This variable is deprecated and will be
+ removed in a future release.
+ --back-log=# The number of outstanding connection requests MySQL can
+ have. This comes into play when the main MySQL thread
+ gets very many connection requests in a very short time
+ -b, --basedir=name Path to installation directory. All paths are usually
+ resolved relative to this
+ --big-tables Allow big result sets by saving all temporary sets on
+ file (Solves most 'table full' errors)
+ --bind-address=name IP address to bind to.
+ --binlog-cache-size=#
+ The size of the transactional cache for updates to
+ transactional engines for the binary log. If you often
+ use transactions containing many statements, you can
+ increase this to get more performance
+ --binlog-checksum=name
+ Type of BINLOG_CHECKSUM_ALG. Include checksum for log
+ events in the binary log. Possible values are NONE and
+ CRC32; default is CRC32.
+ --binlog-direct-non-transactional-updates
+ Causes updates to non-transactional engines using
+ statement format to be written directly to binary log.
+ Before using this option make sure that there are no
+ dependencies between transactional and non-transactional
+ tables such as in the statement INSERT INTO t_myisam
+ SELECT * FROM t_innodb; otherwise, slaves may diverge
+ from the master.
+ --binlog-do-db=name Tells the master it should log updates for the specified
+ database, and exclude all others not explicitly
+ mentioned.
+ --binlog-error-action=name
+ When statements cannot be written to the binary log due
+ to a fatal error, the server can either ignore the error
+ and let the master continue, or abort.
+ --binlog-format=name
+ What form of binary logging the master will use: either
+ ROW for row-based binary logging, STATEMENT for
+ statement-based binary logging, or MIXED. MIXED is
+ statement-based binary logging except for those
+ statements where only row-based is correct: those which
+ involve user-defined functions (i.e. UDFs) or the UUID()
+ function; for those, row-based binary logging is
+ automatically used. If NDBCLUSTER is enabled and
+ binlog-format is MIXED, the format switches to row-based
+ and back implicitly per each query accessing an
+ NDBCLUSTER table
+ --binlog-gtid-simple-recovery
+ If this option is enabled, the server does not open more
+ than two binary logs when initializing GTID_PURGED and
+ GTID_EXECUTED, either during server restart or when
+ binary logs are being purged. Enabling this option is
+ useful when the server has already generated many binary
+ logs without GTID events (e.g., having GTID_MODE = OFF).
+ Note: If this option is enabled, GLOBAL.GTID_EXECUTED and
+ GLOBAL.GTID_PURGED may be initialized wrongly in two
+ cases: (1) GTID_MODE was ON for some binary logs but OFF
+ for the newest binary log. (2) SET GTID_PURGED was issued
+ after the oldest existing binary log was generated. If a
+ wrong set is computed in one of case (1) or case (2), it
+ will remain wrong even if the server is later restarted
+ with this option disabled.
+ --binlog-ignore-db=name
+ Tells the master that updates to the given database
+ should not be logged to the binary log.
+ --binlog-max-flush-queue-time=#
+ The maximum time that the binary log group commit will
+ keep reading transactions before it flush the
+ transactions to the binary log (and optionally sync,
+ depending on the value of sync_binlog).
+ --binlog-order-commits
+ Issue internal commit calls in the same order as
+ transactions are written to the binary log. Default is to
+ order commits.
+ (Defaults to on; use --skip-binlog-order-commits to disable.)
+ --binlog-row-event-max-size=#
+ The maximum size of a row-based binary log event in
+ bytes. Rows will be grouped into events smaller than this
+ size if possible. The value has to be a multiple of 256.
+ --binlog-row-image=name
+ Controls whether rows should be logged in 'FULL',
+ 'NOBLOB' or 'MINIMAL' formats. 'FULL', means that all
+ columns in the before and after image are logged.
+ 'NOBLOB', means that mysqld avoids logging blob columns
+ whenever possible (eg, blob column was not changed or is
+ not part of primary key). 'MINIMAL', means that a PK
+ equivalent (PK columns or full row if there is no PK in
+ the table) is logged in the before image, and only
+ changed columns are logged in the after image. (Default:
+ FULL).
+ --binlog-rows-query-log-events
+ Allow writing of Rows_query_log events into binary log.
+ --binlog-stmt-cache-size=#
+ The size of the statement cache for updates to
+ non-transactional engines for the binary log. If you
+ often use statements updating a great number of rows, you
+ can increase this to get more performance
+ --binlogging-impossible-mode=name
+ On a fatal error when statements cannot be binlogged the
+ behaviour can be ignore the error and let the master
+ continue or abort the server. This variable is deprecated
+ and will be removed in a future release. Please use
+ binlog_error_action instead.
+ --block-encryption-mode=name
+ mode for AES_ENCRYPT/AES_DECRYPT
+ --bootstrap Used by mysql installation scripts.
+ --bulk-insert-buffer-size=#
+ Size of tree cache used in bulk insert optimisation. Note
+ that this is a limit per thread!
+ --character-set-client-handshake
+ Don't ignore client side character set value sent during
+ handshake.
+ (Defaults to on; use --skip-character-set-client-handshake to disable.)
+ --character-set-filesystem=name
+ Set the filesystem character set.
+ -C, --character-set-server=name
+ Set the default character set.
+ --character-sets-dir=name
+ Directory where character sets are
+ -r, --chroot=name Chroot mysqld daemon during startup.
+ --collation-server=name
+ Set the default collation.
+ --completion-type=name
+ The transaction completion type, one of NO_CHAIN, CHAIN,
+ RELEASE
+ --concurrent-insert[=name]
+ Use concurrent insert with MyISAM. Possible values are
+ NEVER, AUTO, ALWAYS
+ --connect-timeout=# The number of seconds the mysqld server is waiting for a
+ connect packet before responding with 'Bad handshake'
+ --console Write error output on screen; don't remove the console
+ window on windows.
+ --core-file Write core on errors.
+ -h, --datadir=name Path to the database root directory
+ --date-format=name The DATE format (ignored)
+ --datetime-format=name
+ The DATETIME format (ignored)
+ --default-authentication-plugin=name
+ Defines what password- and authentication algorithm to
+ use per default
+ --default-storage-engine=name
+ The default storage engine for new tables
+ --default-time-zone=name
+ Set the default time zone.
+ --default-tmp-storage-engine=name
+ The default storage engine for new explict temporary
+ tables
+ --default-week-format=#
+ The default week format used by WEEK() functions
+ --delay-key-write[=name]
+ Type of DELAY_KEY_WRITE
+ --delayed-insert-limit=#
+ After inserting delayed_insert_limit rows, the INSERT
+ DELAYED handler will check if there are any SELECT
+ statements pending. If so, it allows these to execute
+ before continuing. This variable is deprecated along with
+ INSERT DELAYED.
+ --delayed-insert-timeout=#
+ How long a INSERT DELAYED thread should wait for INSERT
+ statements before terminating.This variable is deprecated
+ along with INSERT DELAYED.
+ --delayed-queue-size=#
+ What size queue (in rows) should be allocated for
+ handling INSERT DELAYED. If the queue becomes full, any
+ client that does INSERT DELAYED will wait until there is
+ room in the queue again.This variable is deprecated along
+ with INSERT DELAYED.
+ --disconnect-on-expired-password
+ Give clients that don't signal password expiration
+ support execution time error(s) instead of connection
+ error
+ (Defaults to on; use --skip-disconnect-on-expired-password to disable.)
+ --disconnect-slave-event-count=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --div-precision-increment=#
+ Precision of the result of '/' operator will be increased
+ on that value
+ --end-markers-in-json
+ In JSON output ("EXPLAIN FORMAT=JSON" and optimizer
+ trace), if variable is set to 1, repeats the structure's
+ key (if it has one) near the closing bracket
+ --enforce-gtid-consistency
+ Prevents execution of statements that would be impossible
+ to log in a transactionally safe manner. Currently, the
+ disallowed statements include CREATE TEMPORARY TABLE
+ inside transactions, all updates to non-transactional
+ tables, and CREATE TABLE ... SELECT.
+ --eq-range-index-dive-limit=#
+ The optimizer will use existing index statistics instead
+ of doing index dives for equality ranges if the number of
+ equality ranges for the index is larger than or equal to
+ this number. If set to 0, index dives are always used.
+ --event-scheduler[=name]
+ Enable the event scheduler. Possible values are ON, OFF,
+ and DISABLED (keep the event scheduler completely
+ deactivated, it cannot be activated run-time)
+ -T, --exit-info[=#] Used for debugging. Use at your own risk.
+ --expire-logs-days=#
+ If non-zero, binary logs will be purged after
+ expire_logs_days days; possible purges happen at startup
+ and at binary log rotation
+ --explicit-defaults-for-timestamp
+ This option causes CREATE TABLE to create all TIMESTAMP
+ columns as NULL with DEFAULT NULL attribute, Without this
+ option, TIMESTAMP columns are NOT NULL and have implicit
+ DEFAULT clauses. The old behavior is deprecated.
+ --external-locking Use system (external) locking (disabled by default).
+ With this option enabled you can run myisamchk to test
+ (not repair) tables while the MySQL server is running.
+ Disable with --skip-external-locking.
+ --flush Flush MyISAM tables to disk between SQL commands
+ --flush-time=# A dedicated thread is created to flush all tables at the
+ given interval
+ --ft-boolean-syntax=name
+ List of operators for MATCH ... AGAINST ( ... IN BOOLEAN
+ MODE)
+ --ft-max-word-len=# The maximum length of the word to be included in a
+ FULLTEXT index. Note: FULLTEXT indexes must be rebuilt
+ after changing this variable
+ --ft-min-word-len=# The minimum length of the word to be included in a
+ FULLTEXT index. Note: FULLTEXT indexes must be rebuilt
+ after changing this variable
+ --ft-query-expansion-limit=#
+ Number of best matches to use for query expansion
+ --ft-stopword-file=name
+ Use stopwords from this file instead of built-in list
+ --gdb Set up signals usable for debugging.
+ --general-log Log connections and queries to a table or log file.
+ Defaults logging to a file hostname.log or a table
+ mysql.general_logif --log-output=TABLE is used
+ --general-log-file=name
+ Log connections and queries to given file
+ --group-concat-max-len=#
+ The maximum length of the result of function
+ GROUP_CONCAT()
+ --gtid-mode=name Whether Global Transaction Identifiers (GTIDs) are
+ enabled. Can be ON or OFF.
+ -?, --help Display this help and exit.
+ --host-cache-size=# How many host names should be cached to avoid resolving.
+ --ignore-builtin-innodb
+ IGNORED. This option will be removed in future releases.
+ Disable initialization of builtin InnoDB plugin
+ --ignore-db-dir=name
+ Specifies a directory to add to the ignore list when
+ collecting database names from the datadir. Put a blank
+ argument to reset the list accumulated so far.
+ --init-connect=name Command(s) that are executed for each new connection
+ --init-file=name Read SQL commands from this file at startup
+ --init-slave=name Command(s) that are executed by a slave server each time
+ the SQL thread starts
+ --interactive-timeout=#
+ The number of seconds the server waits for activity on an
+ interactive connection before closing it
+ --join-buffer-size=#
+ The size of the buffer that is used for full joins
+ --keep-files-on-create
+ Don't overwrite stale .MYD and .MYI even if no directory
+ is specified
+ --key-buffer-size=# The size of the buffer used for index blocks for MyISAM
+ tables. Increase this to get better index handling (for
+ all reads and multiple writes) to as much as you can
+ afford
+ --key-cache-age-threshold=#
+ This characterizes the number of hits a hot block has to
+ be untouched until it is considered aged enough to be
+ downgraded to a warm block. This specifies the percentage
+ ratio of that number of hits to the total number of
+ blocks in key cache
+ --key-cache-block-size=#
+ The default size of key cache blocks
+ --key-cache-division-limit=#
+ The minimum percentage of warm blocks in key cache
+ -L, --language=name Client error messages in given language. May be given as
+ a full path. Deprecated. Use --lc-messages-dir instead.
+ --large-pages Enable support for large pages
+ --lc-messages=name Set the language used for the error messages.
+ --lc-messages-dir=name
+ Directory where error messages are
+ --lc-time-names=name
+ Set the language used for the month names and the days of
+ the week.
+ --local-infile Enable LOAD DATA LOCAL INFILE
+ (Defaults to on; use --skip-local-infile to disable.)
+ --lock-wait-timeout=#
+ Timeout in seconds to wait for a lock before returning an
+ error.
+ --log-bin[=name] Log update queries in binary format. Optional (but
+ strongly recommended to avoid replication problems if
+ server's hostname changes) argument should be the chosen
+ location for the binary log files.
+ --log-bin-index=name
+ File that holds the names for binary log files.
+ --log-bin-trust-function-creators
+ If set to FALSE (the default), then when --log-bin is
+ used, creation of a stored function (or trigger) is
+ allowed only to users having the SUPER privilege and only
+ if this stored function (trigger) may not break binary
+ logging. Note that if ALL connections to this server
+ ALWAYS use row-based binary logging, the security issues
+ do not exist and the binary logging cannot break, so you
+ can safely set this to TRUE
+ --log-bin-use-v1-row-events
+ If equal to 1 then version 1 row events are written to a
+ row based binary log. If equal to 0, then the latest
+ version of events are written. This option is useful
+ during some upgrades.
+ --log-error[=name] Error log file
+ --log-isam[=name] Log all MyISAM changes to file.
+ --log-output=name Syntax: log-output=value[,value...], where "value" could
+ be TABLE, FILE or NONE
+ --log-queries-not-using-indexes
+ Log queries that are executed without benefit of any
+ index to the slow log if it is open
+ --log-raw Log to general log before any rewriting of the query. For
+ use in debugging, not production as sensitive information
+ may be logged.
+ --log-short-format Don't log extra information to update and slow-query
+ logs.
+ --log-slave-updates Tells the slave to log the updates from the slave thread
+ to the binary log. You will need to turn it on if you
+ plan to daisy-chain the slaves
+ --log-slow-admin-statements
+ Log slow OPTIMIZE, ANALYZE, ALTER and other
+ administrative statements to the slow log if it is open.
+ --log-slow-slave-statements
+ Log slow statements executed by slave thread to the slow
+ log if it is open.
+ --log-tc=name Path to transaction coordinator log (used for
+ transactions that affect more than one storage engine,
+ when binary log is disabled).
+ --log-tc-size=# Size of transaction coordinator log.
+ --log-throttle-queries-not-using-indexes[=#]
+ Log at most this many 'not using index' warnings per
+ minute to the slow log. Any further warnings will be
+ condensed into a single summary line. A value of 0
+ disables throttling. Option has no effect unless
+ --log_queries_not_using_indexes is set.
+ -W, --log-warnings[=#]
+ Log some not critical warnings to the log file
+ --long-query-time=# Log all queries that have taken more than long_query_time
+ seconds to execute to file. The argument will be treated
+ as a decimal value with microsecond precision
+ --low-priority-updates
+ INSERT/DELETE/UPDATE has lower priority than selects
+ --lower-case-table-names[=#]
+ If set to 1 table names are stored in lowercase on disk
+ and table names will be case-insensitive. Should be set
+ to 2 if you are using a case insensitive file system
+ --master-info-file=name
+ The location and name of the file that remembers the
+ master and where the I/O replication thread is in the
+ master's binlogs.
+ --master-info-repository=name
+ Defines the type of the repository for the master
+ information.
+ --master-retry-count=#
+ The number of tries the slave will make to connect to the
+ master before giving up. Deprecated option, use 'CHANGE
+ MASTER TO master_retry_count = <num>' instead.
+ --master-verify-checksum
+ Force checksum verification of logged events in binary
+ log before sending them to slaves or printing them in
+ output of SHOW BINLOG EVENTS. Disabled by default.
+ --max-allowed-packet=#
+ Max packet length to send to or receive from the server
+ --max-binlog-cache-size=#
+ Sets the total size of the transactional cache
+ --max-binlog-dump-events=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --max-binlog-size=# Binary log will be rotated automatically when the size
+ exceeds this value. Will also apply to relay logs if
+ max_relay_log_size is 0
+ --max-binlog-stmt-cache-size=#
+ Sets the total size of the statement cache
+ --max-connect-errors=#
+ If there is more than this number of interrupted
+ connections from a host this host will be blocked from
+ further connections
+ --max-connections=# The number of simultaneous clients allowed
+ --max-delayed-threads=#
+ Don't start more than this number of threads to handle
+ INSERT DELAYED statements. If set to zero INSERT DELAYED
+ will be not used.This variable is deprecated along with
+ INSERT DELAYED.
+ --max-digest-length=#
+ Maximum length considered for digest text.
+ --max-error-count=# Max number of errors/warnings to store for a statement
+ --max-heap-table-size=#
+ Don't allow creation of heap tables bigger than this
+ --max-join-size=# Joins that are probably going to read more than
+ max_join_size records return an error
+ --max-length-for-sort-data=#
+ Max number of bytes in sorted records
+ --max-prepared-stmt-count=#
+ Maximum number of prepared statements in the server
+ --max-relay-log-size=#
+ If non-zero: relay log will be rotated automatically when
+ the size exceeds this value; if zero: when the size
+ exceeds max_binlog_size
+ --max-seeks-for-key=#
+ Limit assumed max number of seeks when looking up rows
+ based on a key
+ --max-sort-length=# The number of bytes to use when sorting BLOB or TEXT
+ values (only the first max_sort_length bytes of each
+ value are used; the rest are ignored)
+ --max-sp-recursion-depth[=#]
+ Maximum stored procedure recursion depth
+ --max-tmp-tables=# Maximum number of temporary tables a client can keep open
+ at a time
+ --max-user-connections=#
+ The maximum number of active connections for a single
+ user (0 = no limit)
+ --max-write-lock-count=#
+ After this many write locks, allow some read locks to run
+ in between
+ --memlock Lock mysqld in memory.
+ --metadata-locks-cache-size=#
+ Size of unused metadata locks cache
+ --metadata-locks-hash-instances=#
+ Number of metadata locks hash instances
+ --min-examined-row-limit=#
+ Don't write queries to slow log that examine fewer rows
+ than that
+ --multi-range-count=#
+ Number of key ranges to request at once. This variable
+ has no effect, and is deprecated. It will be removed in a
+ future release.
+ --myisam-block-size=#
+ Block size to be used for MyISAM index pages
+ --myisam-data-pointer-size=#
+ Default pointer size to be used for MyISAM tables
+ --myisam-max-sort-file-size=#
+ Don't use the fast sort index method to created index if
+ the temporary file would get bigger than this
+ --myisam-mmap-size=#
+ Restricts the total memory used for memory mapping of
+ MySQL tables
+ --myisam-recover-options[=name]
+ Syntax: myisam-recover-options[=option[,option...]],
+ where option can be DEFAULT, BACKUP, FORCE, QUICK, or OFF
+ --myisam-repair-threads=#
+ If larger than 1, when repairing a MyISAM table all
+ indexes will be created in parallel, with one thread per
+ index. The value of 1 disables parallel repair
+ --myisam-sort-buffer-size=#
+ The buffer that is allocated when sorting the index when
+ doing a REPAIR or when creating indexes with CREATE INDEX
+ or ALTER TABLE
+ --myisam-stats-method=name
+ Specifies how MyISAM index statistics collection code
+ should treat NULLs. Possible values of name are
+ NULLS_UNEQUAL (default behavior for 4.1 and later),
+ NULLS_EQUAL (emulate 4.0 behavior), and NULLS_IGNORED
+ --myisam-use-mmap Use memory mapping for reading and writing MyISAM tables
+ --net-buffer-length=#
+ Buffer length for TCP/IP and socket communication
+ --net-read-timeout=#
+ Number of seconds to wait for more data from a connection
+ before aborting the read
+ --net-retry-count=# If a read on a communication port is interrupted, retry
+ this many times before giving up
+ --net-write-timeout=#
+ Number of seconds to wait for a block to be written to a
+ connection before aborting the write
+ -n, --new Use very new possible "unsafe" functions
+ --old Use compatible behavior
+ --old-alter-table Use old, non-optimized alter table
+ --old-passwords=# Determine which hash algorithm to use when generating
+ passwords using the PASSWORD() function
+ --old-style-user-limits
+ Enable old-style user limits (before 5.0.3, user
+ resources were counted per each user+host vs. per
+ account).
+ --open-files-limit=#
+ If this is not 0, then mysqld will use this value to
+ reserve file descriptors to use with setrlimit(). If this
+ value is 0 then mysqld will reserve max_connections*5 or
+ max_connections + table_open_cache*2 (whichever is
+ larger) number of file descriptors
+ --optimizer-prune-level=#
+ Controls the heuristic(s) applied during query
+ optimization to prune less-promising partial plans from
+ the optimizer search space. Meaning: 0 - do not apply any
+ heuristic, thus perform exhaustive search; 1 - prune
+ plans based on number of retrieved rows
+ --optimizer-search-depth=#
+ Maximum depth of search performed by the query optimizer.
+ Values larger than the number of relations in a query
+ result in better query plans, but take longer to compile
+ a query. Values smaller than the number of tables in a
+ relation result in faster optimization, but may produce
+ very bad query plans. If set to 0, the system will
+ automatically pick a reasonable value
+ --optimizer-switch=name
+ optimizer_switch=option=val[,option=val...], where option
+ is one of {index_merge, index_merge_union,
+ index_merge_sort_union, index_merge_intersection,
+ engine_condition_pushdown, index_condition_pushdown, mrr,
+ mrr_cost_based, materialization, semijoin, loosescan,
+ firstmatch, subquery_materialization_cost_based,
+ block_nested_loop, batched_key_access,
+ use_index_extensions} and val is one of {on, off,
+ default}
+ --optimizer-trace=name
+ Controls tracing of the Optimizer:
+ optimizer_trace=option=val[,option=val...], where option
+ is one of {enabled, one_line} and val is one of {on,
+ default}
+ --optimizer-trace-features=name
+ Enables/disables tracing of selected features of the
+ Optimizer:
+ optimizer_trace_features=option=val[,option=val...],
+ where option is one of {greedy_search, range_optimizer,
+ dynamic_range, repeated_subselect} and val is one of {on,
+ off, default}
+ --optimizer-trace-limit=#
+ Maximum number of shown optimizer traces
+ --optimizer-trace-max-mem-size=#
+ Maximum allowed cumulated size of stored optimizer traces
+ --optimizer-trace-offset=#
+ Offset of first optimizer trace to show; see manual
+ --performance-schema
+ Enable the performance schema.
+ (Defaults to on; use --skip-performance-schema to disable.)
+ --performance-schema-accounts-size=#
+ Maximum number of instrumented user@host accounts. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-consumer-events-stages-current
+ Default startup value for the events_stages_current
+ consumer.
+ --performance-schema-consumer-events-stages-history
+ Default startup value for the events_stages_history
+ consumer.
+ --performance-schema-consumer-events-stages-history-long
+ Default startup value for the events_stages_history_long
+ consumer.
+ --performance-schema-consumer-events-statements-current
+ Default startup value for the events_statements_current
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-events-statements-current to disable.)
+ --performance-schema-consumer-events-statements-history
+ Default startup value for the events_statements_history
+ consumer.
+ --performance-schema-consumer-events-statements-history-long
+ Default startup value for the
+ events_statements_history_long consumer.
+ --performance-schema-consumer-events-waits-current
+ Default startup value for the events_waits_current
+ consumer.
+ --performance-schema-consumer-events-waits-history
+ Default startup value for the events_waits_history
+ consumer.
+ --performance-schema-consumer-events-waits-history-long
+ Default startup value for the events_waits_history_long
+ consumer.
+ --performance-schema-consumer-global-instrumentation
+ Default startup value for the global_instrumentation
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-global-instrumentation to disable.)
+ --performance-schema-consumer-statements-digest
+ Default startup value for the statements_digest consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-statements-digest to disable.)
+ --performance-schema-consumer-thread-instrumentation
+ Default startup value for the thread_instrumentation
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-thread-instrumentation to disable.)
+ --performance-schema-digests-size=#
+ Size of the statement digest. Use 0 to disable, -1 for
+ automated sizing.
+ --performance-schema-events-stages-history-long-size=#
+ Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-events-stages-history-size=#
+ Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-events-statements-history-long-size=#
+ Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-events-statements-history-size=#
+ Number of rows per thread in EVENTS_STATEMENTS_HISTORY.
+ Use 0 to disable, -1 for automated sizing.
+ --performance-schema-events-waits-history-long-size=#
+ Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-events-waits-history-size=#
+ Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-hosts-size=#
+ Maximum number of instrumented hosts. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-instrument[=name]
+ Default startup value for a performance schema
+ instrument.
+ --performance-schema-max-cond-classes=#
+ Maximum number of condition instruments.
+ --performance-schema-max-cond-instances=#
+ Maximum number of instrumented condition objects. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-max-digest-length=#
+ Maximum length considered for digest text, when stored in
+ performance_schema tables.
+ --performance-schema-max-file-classes=#
+ Maximum number of file instruments.
+ --performance-schema-max-file-handles=#
+ Maximum number of opened instrumented files.
+ --performance-schema-max-file-instances=#
+ Maximum number of instrumented files. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-max-mutex-classes=#
+ Maximum number of mutex instruments.
+ --performance-schema-max-mutex-instances=#
+ Maximum number of instrumented MUTEX objects. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-rwlock-classes=#
+ Maximum number of rwlock instruments.
+ --performance-schema-max-rwlock-instances=#
+ Maximum number of instrumented RWLOCK objects. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-socket-classes=#
+ Maximum number of socket instruments.
+ --performance-schema-max-socket-instances=#
+ Maximum number of opened instrumented sockets. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-stage-classes=#
+ Maximum number of stage instruments.
+ --performance-schema-max-statement-classes=#
+ Maximum number of statement instruments.
+ --performance-schema-max-table-handles=#
+ Maximum number of opened instrumented tables. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-table-instances=#
+ Maximum number of instrumented tables. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-max-thread-classes=#
+ Maximum number of thread instruments.
+ --performance-schema-max-thread-instances=#
+ Maximum number of instrumented threads. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-session-connect-attrs-size=#
+ Size of session attribute string buffer per thread. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-setup-actors-size=#
+ Maximum number of rows in SETUP_ACTORS.
+ --performance-schema-setup-objects-size=#
+ Maximum number of rows in SETUP_OBJECTS.
+ --performance-schema-users-size=#
+ Maximum number of instrumented users. Use 0 to disable,
+ -1 for automated sizing.
+ --pid-file=name Pid file used by safe_mysqld
+ --plugin-dir=name Directory for plugins
+ --plugin-load=name Optional semicolon-separated list of plugins to load,
+ where each plugin is identified as name=library, where
+ name is the plugin name and library is the plugin library
+ in plugin_dir.
+ --plugin-load-add=name
+ Optional semicolon-separated list of plugins to load,
+ where each plugin is identified as name=library, where
+ name is the plugin name and library is the plugin library
+ in plugin_dir. This option adds to the list speficied by
+ --plugin-load in an incremental way. Multiple
+ --plugin-load-add are supported.
+ -P, --port=# Port number to use for connection or 0 to default to,
+ my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default
+ (3306), whatever comes first
+ --port-open-timeout=#
+ Maximum time in seconds to wait for the port to become
+ free. (Default: No wait).
+ --preload-buffer-size=#
+ The size of the buffer that is allocated when preloading
+ indexes
+ --profiling-history-size=#
+ Limit of query profiling memory
+ --query-alloc-block-size=#
+ Allocation block size for query parsing and execution
+ --query-cache-limit=#
+ Don't cache results that are bigger than this
+ --query-cache-min-res-unit=#
+ The minimum size for blocks allocated by the query cache
+ --query-cache-size=#
+ The memory allocated to store results from old queries
+ --query-cache-type=name
+ OFF = Don't cache or retrieve results. ON = Cache all
+ results except SELECT SQL_NO_CACHE ... queries. DEMAND =
+ Cache only SELECT SQL_CACHE ... queries
+ --query-cache-wlock-invalidate
+ Invalidate queries in query cache on LOCK for write
+ --query-prealloc-size=#
+ Persistent buffer for query parsing and execution
+ --range-alloc-block-size=#
+ Allocation block size for storing ranges during
+ optimization
+ --read-buffer-size=#
+ Each thread that does a sequential scan allocates a
+ buffer of this size for each table it scans. If you do
+ many sequential scans, you may want to increase this
+ value
+ --read-only Make all non-temporary tables read-only, with the
+ exception for replication (slave) threads and users with
+ the SUPER privilege
+ --read-rnd-buffer-size=#
+ When reading rows in sorted order after a sort, the rows
+ are read through this buffer to avoid a disk seeks
+ --relay-log=name The location and name to use for relay logs
+ --relay-log-index=name
+ File that holds the names for relay log files.
+ --relay-log-info-file=name
+ The location and name of the file that remembers where
+ the SQL replication thread is in the relay logs
+ --relay-log-info-repository=name
+ Defines the type of the repository for the relay log
+ information and associated workers.
+ --relay-log-purge if disabled - do not purge relay logs. if enabled - purge
+ them as soon as they are no more needed
+ (Defaults to on; use --skip-relay-log-purge to disable.)
+ --relay-log-recovery
+ Enables automatic relay log recovery right after the
+ database startup, which means that the IO Thread starts
+ re-fetching from the master right after the last
+ transaction processed
+ --relay-log-space-limit=#
+ Maximum space to use for all relay logs
+ --replicate-do-db=name
+ Tells the slave thread to restrict replication to the
+ specified database. To specify more than one database,
+ use the directive multiple times, once for each database.
+ Note that this will only work if you do not use
+ cross-database queries such as UPDATE some_db.some_table
+ SET foo='bar' while having selected a different or no
+ database. If you need cross database updates to work,
+ make sure you have 3.23.28 or later, and use
+ replicate-wild-do-table=db_name.%.
+ --replicate-do-table=name
+ Tells the slave thread to restrict replication to the
+ specified table. To specify more than one table, use the
+ directive multiple times, once for each table. This will
+ work for cross-database updates, in contrast to
+ replicate-do-db.
+ --replicate-ignore-db=name
+ Tells the slave thread to not replicate to the specified
+ database. To specify more than one database to ignore,
+ use the directive multiple times, once for each database.
+ This option will not work if you use cross database
+ updates. If you need cross database updates to work, make
+ sure you have 3.23.28 or later, and use
+ replicate-wild-ignore-table=db_name.%.
+ --replicate-ignore-table=name
+ Tells the slave thread to not replicate to the specified
+ table. To specify more than one table to ignore, use the
+ directive multiple times, once for each table. This will
+ work for cross-database updates, in contrast to
+ replicate-ignore-db.
+ --replicate-rewrite-db=name
+ Updates to a database with a different name than the
+ original. Example:
+ replicate-rewrite-db=master_db_name->slave_db_name.
+ --replicate-same-server-id
+ In replication, if set to 1, do not skip events having
+ our server id. Default value is 0 (to break infinite
+ loops in circular replication). Can't be set to 1 if
+ --log-slave-updates is used.
+ --replicate-wild-do-table=name
+ Tells the slave thread to restrict replication to the
+ tables that match the specified wildcard pattern. To
+ specify more than one table, use the directive multiple
+ times, once for each table. This will work for
+ cross-database updates. Example:
+ replicate-wild-do-table=foo%.bar% will replicate only
+ updates to tables in all databases that start with foo
+ and whose table names start with bar.
+ --replicate-wild-ignore-table=name
+ Tells the slave thread to not replicate to the tables
+ that match the given wildcard pattern. To specify more
+ than one table to ignore, use the directive multiple
+ times, once for each table. This will work for
+ cross-database updates. Example:
+ replicate-wild-ignore-table=foo%.bar% will not do updates
+ to tables in databases that start with foo and whose
+ table names start with bar.
+ --report-host=name Hostname or IP of the slave to be reported to the master
+ during slave registration. Will appear in the output of
+ SHOW SLAVE HOSTS. Leave unset if you do not want the
+ slave to register itself with the master. Note that it is
+ not sufficient for the master to simply read the IP of
+ the slave off the socket once the slave connects. Due to
+ NAT and other routing issues, that IP may not be valid
+ for connecting to the slave from the master or other
+ hosts
+ --report-password=name
+ The account password of the slave to be reported to the
+ master during slave registration
+ --report-port=# Port for connecting to slave reported to the master
+ during slave registration. Set it only if the slave is
+ listening on a non-default port or if you have a special
+ tunnel from the master or other clients to the slave. If
+ not sure, leave this option unset
+ --report-user=name The account user name of the slave to be reported to the
+ master during slave registration
+ --rpl-stop-slave-timeout=#
+ Timeout in seconds to wait for slave to stop before
+ returning a warning.
+ --safe-user-create Don't allow new user creation by the user who has no
+ write privileges to the mysql.user table.
+ --secure-auth Disallow authentication for accounts that have old
+ (pre-4.1) passwords
+ (Defaults to on; use --skip-secure-auth to disable.)
+ --secure-file-priv=name
+ Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to
+ files within specified directory
+ --server-id=# Uniquely identifies the server instance in the community
+ of replication partners
+ --server-id-bits=# Set number of significant bits in server-id
+ --show-old-temporals
+ When this option is enabled, the pre-5.6.4 temporal types
+ will be marked in the 'SHOW CREATE TABLE' and
+ 'INFORMATION_SCHEMA.COLUMNS' table as a comment in
+ COLUMN_TYPE field. This variable is deprecated and will
+ be removed in a future release.
+ --show-slave-auth-info
+ Show user and password in SHOW SLAVE HOSTS on this
+ master.
+ --simplified-binlog-gtid-recovery
+ Alias for @@binlog_gtid_simple_recovery. Deprecated
+ --skip-grant-tables Start without grant tables. This gives all users FULL
+ ACCESS to all tables.
+ --skip-host-cache Don't cache host names.
+ --skip-name-resolve Don't resolve hostnames. All hostnames are IP's or
+ 'localhost'.
+ --skip-networking Don't allow connection with TCP/IP
+ --skip-new Don't use new, possibly wrong routines.
+ --skip-show-database
+ Don't allow 'SHOW DATABASE' commands
+ --skip-slave-start If set, slave is not autostarted.
+ --skip-stack-trace Don't print a stack trace on failure.
+ --slave-allow-batching
+ Allow slave to batch requests
+ --slave-checkpoint-group=#
+ Maximum number of processed transactions by
+ Multi-threaded slave before a checkpoint operation is
+ called to update progress status.
+ --slave-checkpoint-period=#
+ Gather workers' activities to Update progress status of
+ Multi-threaded slave and flush the relay log info to disk
+ after every #th milli-seconds.
+ --slave-compressed-protocol
+ Use compression on master/slave protocol
+ --slave-exec-mode=name
+ Modes for how replication events should be executed.
+ Legal values are STRICT (default) and IDEMPOTENT. In
+ IDEMPOTENT mode, replication will not stop for operations
+ that are idempotent. In STRICT mode, replication will
+ stop on any unexpected difference between the master and
+ the slave
+ --slave-load-tmpdir=name
+ The location where the slave should put its temporary
+ files when replicating a LOAD DATA INFILE command
+ --slave-max-allowed-packet=#
+ The maximum packet length to sent successfully from the
+ master to slave.
+ --slave-net-timeout=#
+ Number of seconds to wait for more data from a
+ master/slave connection before aborting the read
+ --slave-parallel-workers=#
+ Number of worker threads for executing events in parallel
+ --slave-pending-jobs-size-max=#
+ Max size of Slave Worker queues holding yet not applied
+ events.The least possible value must be not less than the
+ master side max_allowed_packet.
+ --slave-rows-search-algorithms=name
+ Set of searching algorithms that the slave will use while
+ searching for records from the storage engine to either
+ updated or deleted them. Possible values are: INDEX_SCAN,
+ TABLE_SCAN and HASH_SCAN. Any combination is allowed, and
+ the slave will always pick the most suitable algorithm
+ for any given scenario. (Default: INDEX_SCAN,
+ TABLE_SCAN).
+ --slave-skip-errors=name
+ Tells the slave thread to continue replication when a
+ query event returns an error from the provided list
+ --slave-sql-verify-checksum
+ Force checksum verification of replication events after
+ reading them from relay log. Note: Events are always
+ checksum-verified by slave on receiving them from the
+ network before writing them to the relay log. Enabled by
+ default.
+ (Defaults to on; use --skip-slave-sql-verify-checksum to disable.)
+ --slave-transaction-retries=#
+ Number of times the slave SQL thread will retry a
+ transaction in case it failed with a deadlock or elapsed
+ lock wait timeout, before giving up and stopping
+ --slave-type-conversions=name
+ Set of slave type conversions that are enabled. Legal
+ values are: ALL_LOSSY to enable lossy conversions,
+ ALL_NON_LOSSY to enable non-lossy conversions,
+ ALL_UNSIGNED to treat all integer column type data to be
+ unsigned values, and ALL_SIGNED to treat all integer
+ column type data to be signed values. Default treatment
+ is ALL_SIGNED. If ALL_SIGNED and ALL_UNSIGNED both are
+ specifed, ALL_SIGNED will take high priority than
+ ALL_UNSIGNED. If the variable is assigned the empty set,
+ no conversions are allowed and it is expected that the
+ types match exactly.
+ --slow-launch-time=#
+ If creating the thread takes longer than this value (in
+ seconds), the Slow_launch_threads counter will be
+ incremented
+ --slow-query-log Log slow queries to a table or log file. Defaults logging
+ to a file hostname-slow.log or a table mysql.slow_log if
+ --log-output=TABLE is used. Must be enabled to activate
+ other slow log options
+ --slow-query-log-file=name
+ Log slow queries to given log file. Defaults logging to
+ hostname-slow.log. Must be enabled to activate other slow
+ log options
+ --socket=name Socket file to use for connection
+ --sort-buffer-size=#
+ Each thread that needs to do a sort allocates a buffer of
+ this size
+ --sporadic-binlog-dump-fail
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --sql-mode=name Syntax: sql-mode=mode[,mode[,mode...]]. See the manual
+ for the complete list of valid sql modes
+ --stored-program-cache=#
+ The soft upper limit for number of cached stored routines
+ for one connection.
+ -s, --symbolic-links
+ Enable symbolic link support.
+ --sync-binlog=# Synchronously flush binary log to disk after every #th
+ write to the file. Use 0 (default) to disable synchronous
+ flushing
+ --sync-frm Sync .frm files to disk on creation
+ (Defaults to on; use --skip-sync-frm to disable.)
+ --sync-master-info=#
+ Synchronously flush master info to disk after every #th
+ event. Use 0 to disable synchronous flushing
+ --sync-relay-log=# Synchronously flush relay log to disk after every #th
+ event. Use 0 to disable synchronous flushing
+ --sync-relay-log-info=#
+ Synchronously flush relay log info to disk after every
+ #th transaction. Use 0 to disable synchronous flushing
+ --sysdate-is-now Non-default option to alias SYSDATE() to NOW() to make it
+ safe-replicable. Since 5.0, SYSDATE() returns a `dynamic'
+ value different for different invocations, even within
+ the same statement.
+ --table-definition-cache=#
+ The number of cached table definitions
+ --table-open-cache=#
+ The number of cached open tables (total for all table
+ cache instances)
+ --table-open-cache-instances=#
+ The number of table cache instances
+ --tc-heuristic-recover=name
+ Decision to use in heuristic recover process. Possible
+ values are COMMIT or ROLLBACK.
+ --thread-cache-size=#
+ How many threads we should keep in a cache for reuse
+ --thread-handling=name
+ Define threads usage for handling queries, one of
+ one-thread-per-connection, no-threads, loaded-dynamically
+ --thread-stack=# The stack size for each thread
+ --time-format=name The TIME format (ignored)
+ --timed-mutexes Specify whether to time mutexes. Deprecated, has no
+ effect.
+ --tmp-table-size=# If an internal in-memory temporary table exceeds this
+ size, MySQL will automatically convert it to an on-disk
+ MyISAM table
+ -t, --tmpdir=name Path for temporary files. Several paths may be specified,
+ separated by a colon (:), in this case they are used in a
+ round-robin fashion
+ --transaction-alloc-block-size=#
+ Allocation block size for transactions to be stored in
+ binary log
+ --transaction-isolation=name
+ Default transaction isolation level.
+ --transaction-prealloc-size=#
+ Persistent buffer for transactions to be stored in binary
+ log
+ --transaction-read-only
+ Default transaction access mode. True if transactions are
+ read-only.
+ --updatable-views-with-limit=name
+ YES = Don't issue an error message (warning only) if a
+ VIEW without presence of a key of the underlying table is
+ used in queries with a LIMIT clause for updating. NO =
+ Prohibit update of a VIEW, which does not contain a key
+ of the underlying table and the query uses a LIMIT clause
+ (usually get from GUI tools)
+ -u, --user=name Run mysqld daemon as user.
+ --validate-user-plugins
+ Turns on additional validation of authentication plugins
+ assigned to user accounts.
+ (Defaults to on; use --skip-validate-user-plugins to disable.)
+ -v, --verbose Used with --help option for detailed help.
+ -V, --version Output version information and exit.
+ --wait-timeout=# The number of seconds the server waits for activity on a
+ connection before closing it
+ --wsrep-OSU-method[=name]
+ Method for Online Schema Upgrade
+ --wsrep-SR-store=name
+ Storage for streaming replication fragments
+ --wsrep-auto-increment-control
+ To automatically control the assignment of autoincrement
+ variables
+ (Defaults to on; use --skip-wsrep-auto-increment-control to disable.)
+ --wsrep-causal-reads
+ (DEPRECATED) setting this variable is equivalent to
+ setting wsrep_sync_wait READ flag
+ --wsrep-certify-nonPK
+ Certify tables with no primary key
+ (Defaults to on; use --skip-wsrep-certify-nonPK to disable.)
+ --wsrep-cluster-address=name
+ Address to initially connect to cluster
+ --wsrep-cluster-name=name
+ Name for the cluster
+ --wsrep-convert-LOCK-to-trx
+ To convert locking sessions into transactions
+ --wsrep-data-home-dir=name
+ home directory for wsrep provider
+ --wsrep-dbug-option=name
+ DBUG options to provider library
+ --wsrep-debug To enable debug level logging
+ --wsrep-desync To desynchronize the node from the cluster
+ --wsrep-dirty-reads Allow reads from a node is not in primary component
+ --wsrep-drupal-282555-workaround
+ To use a workaround forbad autoincrement value
+ --wsrep-forced-binlog-format=name
+ binlog format to take effect over user's choice
+ --wsrep-ignore-apply-errors=#
+ Ignore replication errors
+ --wsrep-load-data-splitting
+ To commit LOAD DATA transaction after every 10K rows
+ inserted (deprecating)
+ (Defaults to on; use --skip-wsrep-load-data-splitting to disable.)
+ --wsrep-log-conflicts
+ To log multi-master conflicts
+ --wsrep-max-ws-rows=#
+ Max number of rows in write set
+ --wsrep-max-ws-size=#
+ Max write set size (bytes)
+ --wsrep-mysql-replication-bundle=#
+ mysql replication group commit
+ --wsrep-node-address=name
+ Node address
+ --wsrep-node-incoming-address=name
+ Client connection address
+ --wsrep-node-name=name
+ Node name
+ --wsrep-notify-cmd=name
+ --wsrep-on To enable wsrep replication
+ (Defaults to on; use --skip-wsrep-on to disable.)
+ --wsrep-preordered To enable preordered write set processing
+ --wsrep-provider=name
+ Path to replication provider library
+ --wsrep-provider-options=name
+ provider specific options
+ --wsrep-recover Recover database state after crash and exit
+ --wsrep-reject-queries[=name]
+ Variable to set to reject queries
+ --wsrep-replicate-myisam
+ To enable myisam replication
+ --wsrep-restart-slave
+ Should MySQL slave be restarted automatically, when node
+ joins back to cluster
+ --wsrep-retry-autocommit=#
+ Max number of times to retry a failed autocommit
+ statement
+ --wsrep-slave-FK-checks
+ Should slave thread do foreign key constraint checks
+ (Defaults to on; use --skip-wsrep-slave-FK-checks to disable.)
+ --wsrep-slave-UK-checks
+ Should slave thread do secondary index uniqueness checks
+ --wsrep-slave-threads=#
+ Number of slave appliers to launch
+ --wsrep-sst-auth=name
+ Authentication for SST connection
+ --wsrep-sst-donor=name
+ preferred donor node for the SST
+ --wsrep-sst-donor-rejects-queries
+ Reject client queries when donating state snapshot
+ transfer
+ --wsrep-sst-method=name
+ State snapshot transfer method
+ --wsrep-sst-receive-address=name
+ Address where node is waiting for SST contact
+ --wsrep-start-position=name
+ global transaction position to start from
+ --wsrep-sync-wait[=#]
+ Ensure "synchronous" read view before executing an
+ operation of the type specified by bitmask: 1 -
+ READ(includes SELECT, SHOW and BEGIN/START TRANSACTION);
+ 2 - UPDATE and DELETE; 4 - INSERT and REPLACE
+ --wsrep-trx-fragment-size=#
+ Size of transaction fragments for streaming replication
+ (measured in units of 'wsrep_trx_fragment_unit')
+ --wsrep-trx-fragment-unit=name
+ Unit for streaming replication transaction fragments'
+ size: bytes, events, rows, statements
+
+Variables (--variable-name=value)
+abort-slave-event-count 0
+allow-suspicious-udfs FALSE
+auto-increment-increment 1
+auto-increment-offset 1
+autocommit TRUE
+automatic-sp-privileges TRUE
+avoid-temporal-upgrade FALSE
+back-log 80
+big-tables FALSE
+bind-address *
+binlog-cache-size 32768
+binlog-checksum CRC32
+binlog-direct-non-transactional-updates FALSE
+binlog-error-action IGNORE_ERROR
+binlog-format STATEMENT
+binlog-gtid-simple-recovery FALSE
+binlog-max-flush-queue-time 0
+binlog-order-commits TRUE
+binlog-row-event-max-size 8192
+binlog-row-image FULL
+binlog-rows-query-log-events FALSE
+binlog-stmt-cache-size 32768
+binlogging-impossible-mode IGNORE_ERROR
+block-encryption-mode aes-128-ecb
+bulk-insert-buffer-size 8388608
+character-set-client-handshake TRUE
+character-set-filesystem binary
+character-set-server latin1
+character-sets-dir MYSQL_CHARSETSDIR/
+chroot (No default value)
+collation-server latin1_swedish_ci
+completion-type NO_CHAIN
+concurrent-insert AUTO
+connect-timeout 10
+console FALSE
+date-format %Y-%m-%d
+datetime-format %Y-%m-%d %H:%i:%s
+default-storage-engine InnoDB
+default-time-zone (No default value)
+default-tmp-storage-engine InnoDB
+default-week-format 0
+delay-key-write ON
+delayed-insert-limit 100
+delayed-insert-timeout 300
+delayed-queue-size 1000
+disconnect-on-expired-password TRUE
+disconnect-slave-event-count 0
+div-precision-increment 4
+end-markers-in-json FALSE
+enforce-gtid-consistency FALSE
+eq-range-index-dive-limit 10
+event-scheduler OFF
+expire-logs-days 0
+explicit-defaults-for-timestamp FALSE
+external-locking FALSE
+flush FALSE
+flush-time 0
+ft-boolean-syntax + -><()~*:""&|
+ft-max-word-len 84
+ft-min-word-len 4
+ft-query-expansion-limit 20
+ft-stopword-file (No default value)
+gdb FALSE
+general-log FALSE
+group-concat-max-len 1024
+gtid-mode OFF
+help TRUE
+host-cache-size 279
+ignore-builtin-innodb FALSE
+init-connect
+init-file (No default value)
+init-slave
+interactive-timeout 28800
+join-buffer-size 262144
+keep-files-on-create FALSE
+key-buffer-size 8388608
+key-cache-age-threshold 300
+key-cache-block-size 1024
+key-cache-division-limit 100
+language MYSQL_SHAREDIR/
+large-pages FALSE
+lc-messages en_US
+lc-messages-dir MYSQL_SHAREDIR/
+lc-time-names en_US
+local-infile TRUE
+lock-wait-timeout 31536000
+log-bin (No default value)
+log-bin-index (No default value)
+log-bin-trust-function-creators FALSE
+log-bin-use-v1-row-events FALSE
+log-error
+log-isam myisam.log
+log-output FILE
+log-queries-not-using-indexes FALSE
+log-raw FALSE
+log-short-format FALSE
+log-slave-updates FALSE
+log-slow-admin-statements FALSE
+log-slow-slave-statements FALSE
+log-tc tc.log
+log-tc-size 24576
+log-throttle-queries-not-using-indexes 0
+log-warnings 1
+long-query-time 10
+low-priority-updates FALSE
+lower-case-table-names 1
+master-info-file master.info
+master-info-repository FILE
+master-retry-count 86400
+master-verify-checksum FALSE
+max-allowed-packet 4194304
+max-binlog-cache-size 18446744073709547520
+max-binlog-dump-events 0
+max-binlog-size 1073741824
+max-binlog-stmt-cache-size 18446744073709547520
+max-connect-errors 100
+max-connections 151
+max-delayed-threads 20
+max-digest-length 1024
+max-error-count 64
+max-heap-table-size 16777216
+max-join-size 18446744073709551615
+max-length-for-sort-data 1024
+max-prepared-stmt-count 16382
+max-relay-log-size 0
+max-seeks-for-key 18446744073709551615
+max-sort-length 1024
+max-sp-recursion-depth 0
+max-tmp-tables 32
+max-user-connections 0
+max-write-lock-count 18446744073709551615
+memlock FALSE
+metadata-locks-cache-size 1024
+metadata-locks-hash-instances 8
+min-examined-row-limit 0
+multi-range-count 256
+myisam-block-size 1024
+myisam-data-pointer-size 6
+myisam-max-sort-file-size 9223372036853727232
+myisam-mmap-size 18446744073709551615
+myisam-recover-options OFF
+myisam-repair-threads 1
+myisam-sort-buffer-size 8388608
+myisam-stats-method nulls_unequal
+myisam-use-mmap FALSE
+net-buffer-length 16384
+net-read-timeout 30
+net-retry-count 10
+net-write-timeout 60
+new FALSE
+old FALSE
+old-alter-table FALSE
+old-passwords 0
+old-style-user-limits FALSE
+optimizer-prune-level 1
+optimizer-search-depth 62
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,subquery_materialization_cost_based=on,use_index_extensions=on
+optimizer-trace
+optimizer-trace-features greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on
+optimizer-trace-limit 1
+optimizer-trace-max-mem-size 16384
+optimizer-trace-offset -1
+performance-schema TRUE
+performance-schema-accounts-size -1
+performance-schema-consumer-events-stages-current FALSE
+performance-schema-consumer-events-stages-history FALSE
+performance-schema-consumer-events-stages-history-long FALSE
+performance-schema-consumer-events-statements-current TRUE
+performance-schema-consumer-events-statements-history FALSE
+performance-schema-consumer-events-statements-history-long FALSE
+performance-schema-consumer-events-waits-current FALSE
+performance-schema-consumer-events-waits-history FALSE
+performance-schema-consumer-events-waits-history-long FALSE
+performance-schema-consumer-global-instrumentation TRUE
+performance-schema-consumer-statements-digest TRUE
+performance-schema-consumer-thread-instrumentation TRUE
+performance-schema-digests-size -1
+performance-schema-events-stages-history-long-size -1
+performance-schema-events-stages-history-size -1
+performance-schema-events-statements-history-long-size -1
+performance-schema-events-statements-history-size -1
+performance-schema-events-waits-history-long-size -1
+performance-schema-events-waits-history-size -1
+performance-schema-hosts-size -1
+performance-schema-instrument
+performance-schema-max-cond-classes 80
+performance-schema-max-cond-instances -1
+performance-schema-max-digest-length 1024
+performance-schema-max-file-classes 50
+performance-schema-max-file-handles 32768
+performance-schema-max-file-instances -1
+performance-schema-max-mutex-classes 200
+performance-schema-max-mutex-instances -1
+performance-schema-max-rwlock-classes 40
+performance-schema-max-rwlock-instances -1
+performance-schema-max-socket-classes 10
+performance-schema-max-socket-instances -1
+performance-schema-max-stage-classes 150
+performance-schema-max-statement-classes 168
+performance-schema-max-table-handles -1
+performance-schema-max-table-instances -1
+performance-schema-max-thread-classes 50
+performance-schema-max-thread-instances -1
+performance-schema-session-connect-attrs-size -1
+performance-schema-setup-actors-size 100
+performance-schema-setup-objects-size 100
+performance-schema-users-size -1
+port ####
+port-open-timeout 0
+preload-buffer-size 32768
+profiling-history-size 15
+query-alloc-block-size 8192
+query-cache-limit 1048576
+query-cache-min-res-unit 4096
+query-cache-size 1048576
+query-cache-type OFF
+query-cache-wlock-invalidate FALSE
+query-prealloc-size 8192
+range-alloc-block-size 4096
+read-buffer-size 131072
+read-only FALSE
+read-rnd-buffer-size 262144
+relay-log (No default value)
+relay-log-index (No default value)
+relay-log-info-file relay-log.info
+relay-log-info-repository FILE
+relay-log-purge TRUE
+relay-log-recovery FALSE
+relay-log-space-limit 0
+replicate-same-server-id FALSE
+report-host (No default value)
+report-password (No default value)
+report-port 0
+report-user (No default value)
+rpl-stop-slave-timeout 31536000
+safe-user-create FALSE
+secure-auth TRUE
+server-id 0
+server-id-bits 32
+show-old-temporals FALSE
+show-slave-auth-info FALSE
+simplified-binlog-gtid-recovery FALSE
+skip-grant-tables TRUE
+skip-name-resolve FALSE
+skip-networking FALSE
+skip-show-database FALSE
+skip-slave-start FALSE
+slave-allow-batching FALSE
+slave-checkpoint-group 512
+slave-checkpoint-period 300
+slave-compressed-protocol FALSE
+slave-exec-mode STRICT
+slave-max-allowed-packet 1073741824
+slave-net-timeout 3600
+slave-parallel-workers 0
+slave-pending-jobs-size-max 16777216
+slave-rows-search-algorithms TABLE_SCAN,INDEX_SCAN
+slave-skip-errors (No default value)
+slave-sql-verify-checksum TRUE
+slave-transaction-retries 10
+slave-type-conversions
+slow-launch-time 2
+slow-query-log FALSE
+sort-buffer-size 262144
+sporadic-binlog-dump-fail FALSE
+sql-mode NO_ENGINE_SUBSTITUTION
+stored-program-cache 256
+symbolic-links FALSE
+sync-binlog 0
+sync-frm TRUE
+sync-master-info 10000
+sync-relay-log 10000
+sync-relay-log-info 10000
+sysdate-is-now FALSE
+table-open-cache-instances 1
+tc-heuristic-recover COMMIT
+thread-cache-size 9
+thread-handling one-thread-per-connection
+thread-stack 262144
+time-format %H:%i:%s
+timed-mutexes FALSE
+tmp-table-size 16777216
+transaction-alloc-block-size 8192
+transaction-isolation REPEATABLE-READ
+transaction-prealloc-size 4096
+transaction-read-only FALSE
+updatable-views-with-limit YES
+validate-user-plugins TRUE
+verbose TRUE
+wait-timeout 28800
+wsrep-OSU-method TOI
+wsrep-SR-store table
+wsrep-auto-increment-control TRUE
+wsrep-causal-reads FALSE
+wsrep-certify-nonPK TRUE
+wsrep-cluster-address
+wsrep-cluster-name my_wsrep_cluster
+wsrep-convert-LOCK-to-trx FALSE
+wsrep-data-home-dir
+wsrep-dbug-option
+wsrep-debug FALSE
+wsrep-desync FALSE
+wsrep-dirty-reads FALSE
+wsrep-drupal-282555-workaround FALSE
+wsrep-forced-binlog-format NONE
+wsrep-ignore-apply-errors 7
+wsrep-load-data-splitting TRUE
+wsrep-log-conflicts FALSE
+wsrep-max-ws-rows 0
+wsrep-max-ws-size 2147483647
+wsrep-mysql-replication-bundle 0
+wsrep-node-address
+wsrep-node-incoming-address AUTO
+wsrep-notify-cmd
+wsrep-on FALSE
+wsrep-preordered FALSE
+wsrep-provider none
+wsrep-provider-options
+wsrep-recover FALSE
+wsrep-reject-queries NONE
+wsrep-replicate-myisam FALSE
+wsrep-restart-slave FALSE
+wsrep-retry-autocommit 1
+wsrep-slave-FK-checks TRUE
+wsrep-slave-UK-checks FALSE
+wsrep-slave-threads 1
+wsrep-sst-auth (No default value)
+wsrep-sst-donor
+wsrep-sst-donor-rejects-queries FALSE
+wsrep-sst-method rsync
+wsrep-sst-receive-address AUTO
+wsrep-start-position 00000000-0000-0000-0000-000000000000:-1
+wsrep-sync-wait 0
+wsrep-trx-fragment-size 0
+wsrep-trx-fragment-unit bytes
+
+To see what values a running MySQL server is using, type
+'mysqladmin variables' instead of 'mysqld --verbose --help'.
diff --git a/mysql-test/r/query_cache_size_functionality.result b/mysql-test/r/query_cache_size_functionality.result
new file mode 100644
index 00000000000..7563b3e61eb
--- /dev/null
+++ b/mysql-test/r/query_cache_size_functionality.result
@@ -0,0 +1,226 @@
+'#________________________VAR_02_query_cache_size__________________#'
+echo '##'
+--echo '#---------------------WL6372_VAR_2_01----------------------#'
+####################################################################
+# Checking default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.query_cache_size)
+1 Expected
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_02----------------------#'
+# Restart server with query_cache_size 51200;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+51200
+51200 Expected
+SET @@GLOBAL.query_cache_size=DEFAULT;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_03----------------------#'
+SET @@local.query_cache_size=1;
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
+Expected error 'Global variable'
+SET @@session.query_cache_size=1;
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
+Expected error 'Global variable'
+SET @@GLOBAL.query_cache_size=1;
+SET @@GLOBAL.query_cache_size=DEFAULT;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_04----------------------#'
+SELECT @@GLOBAL.query_cache_size = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_size';
+@@GLOBAL.query_cache_size = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_size);
+COUNT(@@GLOBAL.query_cache_size)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_size';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------WL6372_VAR_2_05----------------------#'
+SELECT @@query_cache_size = @@GLOBAL.query_cache_size;
+@@query_cache_size = @@GLOBAL.query_cache_size
+1
+1 Expected
+SELECT COUNT(@@local.query_cache_size);
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@SESSION.query_cache_size);
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@GLOBAL.query_cache_size);
+COUNT(@@GLOBAL.query_cache_size)
+1
+1 Expected
+SELECT query_cache_size = @@SESSION.query_cache_size;
+ERROR 42S22: Unknown column 'query_cache_size' in 'field list'
+Expected error 'Unknown column query_cache_size in field list'
+'#---------------------WL6372_VAR_2_06----------------------#'
+Check the size of the vardir
+The output size is in unit blocks
+TRUE
+TRUE Expected
+'#---------------------WL6372_VAR_2_07----------------------#'
+# create 1 table and insert 3 rows each
+DROP TABLE IF EXISTS tab1;
+===============
+create table & Index
+===============
+CREATE TABLE tab1 (col_1 text(10))
+ENGINE=INNODB ;
+===============
+Load the data
+===============
+SET @col_1 = repeat('a', 10);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+commit;
+set @@GLOBAL.query_cache_size=DEFAULT;
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+24
+22 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+29
+27 Expected
+# Restart server with query_cache_type ON
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+10
+8 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+14
+12 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+18
+16 Expected
+# opening another client session
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+#cleanup
+DROP TABLE IF EXISTS tab1;
diff --git a/mysql-test/r/query_cache_type_functionality.result b/mysql-test/r/query_cache_type_functionality.result
new file mode 100644
index 00000000000..134d8c3a066
--- /dev/null
+++ b/mysql-test/r/query_cache_type_functionality.result
@@ -0,0 +1,250 @@
+'#________________________VAR_03_query_cache_type__________________#'
+echo '##'
+--echo '#---------------------WL6372_VAR_3_01----------------------#'
+####################################################################
+# Checking default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.query_cache_type)
+1 Expected
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_02----------------------#'
+# Restart server with query_cache_type 1;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=DEFAULT;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_03----------------------#'
+SET @@local.query_cache_type=1;
+SELECT @@Local.query_cache_type;
+@@Local.query_cache_type
+ON
+ON Expected
+SET @@session.query_cache_type=1;
+SELECT @@Session.query_cache_type;
+@@Session.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=1;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=DEFAULT;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+SET @@Session.query_cache_type=DEFAULT;
+SELECT @@Session.query_cache_type;
+@@Session.query_cache_type
+OFF
+OFF Expected
+SET @@Local.query_cache_type=DEFAULT;
+SELECT @@Local.query_cache_type;
+@@Local.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_04----------------------#'
+SELECT @@GLOBAL.query_cache_type = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_type';
+@@GLOBAL.query_cache_type = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_type);
+COUNT(@@GLOBAL.query_cache_type)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_type';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------WL6372_VAR_3_05----------------------#'
+SELECT @@query_cache_type = @@GLOBAL.query_cache_type;
+@@query_cache_type = @@GLOBAL.query_cache_type
+1
+1 Expected
+SELECT @@query_cache_type = @@Session.query_cache_type;
+@@query_cache_type = @@Session.query_cache_type
+1
+1 Expected
+SELECT COUNT(@@local.query_cache_type);
+COUNT(@@local.query_cache_type)
+1
+1 Expected
+SELECT COUNT(@@SESSION.query_cache_type);
+COUNT(@@SESSION.query_cache_type)
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_type);
+COUNT(@@GLOBAL.query_cache_type)
+1
+1 Expected
+SELECT query_cache_type = @@SESSION.query_cache_type;
+ERROR 42S22: Unknown column 'query_cache_type' in 'field list'
+Expected error 'Unknown column query_cache_type in field list'
+'#---------------------WL6372_VAR_3_06----------------------#'
+Check the size of the vardir
+The output size is in unit blocks
+TRUE
+TRUE Expected
+'#---------------------WL6372_VAR_3_07----------------------#'
+# create 1 table and insert 3 rows each
+DROP TABLE IF EXISTS tab1;
+===============
+create table & Index
+===============
+CREATE TABLE tab1 (col_1 text(10))
+ENGINE=INNODB ;
+===============
+Load the data
+===============
+SET @col_1 = repeat('a', 10);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+commit;
+set @@GLOBAL.query_cache_type=DEFAULT;
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+27
+25 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+32
+30 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+37
+35 Expected
+# Restart server with query_cache_type ON
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+10
+8 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+14
+12 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+18
+16 Expected
+# opening another client session
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+#cleanup
+DROP TABLE IF EXISTS tab1;
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 840e69db71f..1e0ffd120da 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -9,7 +9,7 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-
+MW-360 : needs rewrite to be MariaDB gtid compatible
galera_flush : MariaDB does not have global.thread_statistics
galera_account_management : MariaDB 10.0 does not support ALTER USER
galera_binlog_rows_query_log_events: MariaDB does not support binlog_rows_query_log_events
diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf
index b24f3603894..68e4759ee9b 100644
--- a/mysql-test/suite/galera/galera_2nodes.cnf
+++ b/mysql-test/suite/galera/galera_2nodes.cnf
@@ -2,6 +2,7 @@
!include include/default_mysqld.cnf
[mysqld]
+loose-innodb
wsrep-on=1
binlog-format=row
innodb-autoinc-lock-mode=2
@@ -10,20 +11,34 @@ wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
# enforce read-committed characteristics across the cluster
wsrep-sync-wait=15
-
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
+loose-innodb
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+#wsrep-new-cluster
wsrep-cluster-address=gcomm://
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
+# enforce read-committed characteristics across the cluster
+wsrep_causal_reads=ON
+wsrep_sync_wait = 15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
[mysqld.2]
+loose-innodb
+# debug=d:t:i:o,/tmp/mysqld.2.trace
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S'
@@ -34,8 +49,14 @@ wsrep_sync_wait = 15
wsrep_node_address=127.0.0.1
wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_sst_receive_address='127.0.0.2:@mysqld.2.#sst_port'
+# enforce read-committed characteristics across the cluster
+wsrep_causal_reads=ON
+wsrep_sync_wait = 15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf
index 33bfc475721..f856b58ab14 100644
--- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf
+++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf
@@ -11,6 +11,9 @@ log-bin=mysqld-bin
binlog-format=row
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
#galera_port=(a)OPT.port
@@ -30,6 +33,9 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.2]
#galera_port=(a)OPT.port
@@ -49,9 +55,15 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.3]
server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
index 4d9e39d2aae..b432c9db7d3 100644
--- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
+++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
@@ -9,17 +9,14 @@
binlog-format=row
[mysqld.1]
-log-bin
-server-id=1
-
-[mysqld.2]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
wsrep-on=1
-log-bin
+log-bin=master-bin
+log-bin-index=master-bin
log-slave-updates
innodb-autoinc-lock-mode=2
@@ -27,38 +24,54 @@ default-storage-engine=innodb
wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
wsrep-cluster-address=gcomm://
-wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=2
+server-id=1
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.3]
+[mysqld.2]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
wsrep-on=1
-log-bin
+log-bin=master-bin
+log-bin-index=master-bin
log-slave-updates
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=(a)mysqld.3.#galera_port;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+server-id=2
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
+[mysqld.1]
+log-bin=master-bin
+log-bin-index=master-bin
server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
[ENV]
NODE_MYPORT_1= @mysqld.1.port
@@ -70,8 +83,8 @@ NODE_MYSOCK_2= @mysqld.2.socket
NODE_MYPORT_3= @mysqld.3.port
NODE_MYSOCK_3= @mysqld.3.socket
+NODE_GALERAPORT_1= @mysqld.1.#galera_port
NODE_GALERAPORT_2= @mysqld.2.#galera_port
-NODE_GALERAPORT_3= @mysqld.3.#galera_port
+NODE_SSTPORT_1= @mysqld.1.#sst_port
NODE_SSTPORT_2= @mysqld.2.#sst_port
-NODE_SSTPORT_3= @mysqld.3.#sst_port
diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
index ac1ca34e242..26640374be9 100644
--- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
+++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
@@ -8,15 +8,15 @@
[mysqld]
log-bin
binlog-format=row
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
-server-id=1
-
-[mysqld.2]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
-
+wsrep-on=1
log-slave-updates
innodb-autoinc-lock-mode=2
@@ -24,19 +24,23 @@ default-storage-engine=innodb
wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
wsrep-cluster-address=gcomm://
-wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=2
+server-id=1
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.3]
+[mysqld.2]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+wsrep-on=1
log-slave-updates
@@ -44,20 +48,24 @@ innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=3
+server-id=2
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.4]
+[mysqld.3]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+wsrep-on=1
log-slave-updates
@@ -65,15 +73,24 @@ innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=(a)ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
+[mysqld.4]
server-id=4
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
@@ -88,10 +105,10 @@ NODE_MYSOCK_3= @mysqld.3.socket
NODE_MYPORT_4= @mysqld.4.port
NODE_MYSOCK_4= @mysqld.4.socket
+NODE_GALERAPORT_1= @mysqld.1.#galera_port
NODE_GALERAPORT_2= @mysqld.2.#galera_port
NODE_GALERAPORT_3= @mysqld.3.#galera_port
-NODE_GALERAPORT_4= @mysqld.4.#galera_port
+NODE_SSTPORT_1= @mysqld.1.#sst_port
NODE_SSTPORT_2= @mysqld.2.#sst_port
NODE_SSTPORT_3= @mysqld.3.#sst_port
-NODE_SSTPORT_4= @mysqld.4.#sst_port
diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf
index 1c195afd54b..2d348c0c2ed 100644
--- a/mysql-test/suite/galera/galera_4nodes.cnf
+++ b/mysql-test/suite/galera/galera_4nodes.cnf
@@ -11,6 +11,9 @@ wsrep_node_address=127.0.0.1
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
#galera_port=(a)OPT.port
@@ -20,6 +23,9 @@ wsrep-cluster-address=gcomm://
wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.2]
#galera_port=(a)OPT.port
@@ -29,6 +35,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.3]
@@ -39,6 +48,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=(a)mysqld.3.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.4]
@@ -49,6 +61,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=(a)mysqld.4.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/include/galera_load_provider.inc b/mysql-test/suite/galera/include/galera_load_provider.inc
index aeab7e6ea19..0f843597d9c 100644
--- a/mysql-test/suite/galera/include/galera_load_provider.inc
+++ b/mysql-test/suite/galera/include/galera_load_provider.inc
@@ -2,7 +2,75 @@
--disable_query_log
--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig';
+
+#
+# count occurences of successful node starts in error log
+#
+perl;
+ use strict;
+ my $test_log=$ENV{'LOG_FILE'} or die "LOG_FILE not set";
+ my $test_log_copy=$test_log . '.copy';
+ if (-e $test_log_copy) {
+ unlink $test_log_copy;
+ }
+
+EOF
+--copy_file $LOG_FILE $LOG_FILE.copy
+
+#
+# now join to the cluster
+#
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig';
+
+--enable_query_log
+
+#
+# Cluster address change above, will launch SST/IST
+# if mysqldump ST has been configured, mysqld will close all
+# client connections, and it will be hard for us to poll for
+# cluster status during SST process, therefore wait_until_connected_again.inc
+# and wait_until_ready.inc may fail in this phase
+# To workaround this, we do first lazy polling here just to see when
+# client connections will be possible, and after that check for node readyness
+#
+--disable_result_log
+--disable_query_log
+
+--error 0,1
+perl;
+ use strict;
+ my $logfile = $ENV{'LOG_FILE'} or die ("no error log file set");
+
+ my $counter = 1000;
+ #my $found = false
+
+ while ($counter > 0) {
+
+ open(FILE, "$logfile") or die("Unable to open $logfile : $!\n");
+ my $new_sync_count = () = grep(/Synchronized with group/g,<FILE>);
+ close(FILE);
+
+ open(FILEN, "$logfile.copy") or die("Unable to open $logfile.copy : $!\n");
+ my $old_sync_count = () = grep(/Synchronized with group/g,<FILEN>);
+ close(FILEN);
+
+ if ($new_sync_count > $old_sync_count ) {
+ exit(0);
+ }
+ $counter--;
+ sleep(5);
+ }
+ exit(1);
+EOF
+if ($errno)
+{
+--echo "SST failed $errno"
+}
+
+--remove_file $LOG_FILE.copy
+
--enable_query_log
+--enable_result_log
+#--eval SET GLOBAL log_error = $log_error_;
--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera/include/galera_resume.inc b/mysql-test/suite/galera/include/galera_resume.inc
index 232cb46479e..af8f2b956fd 100644
--- a/mysql-test/suite/galera/include/galera_resume.inc
+++ b/mysql-test/suite/galera/include/galera_resume.inc
@@ -3,7 +3,7 @@
my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
- system("kill -18 $mysqld_pid");
+ system("kill -SIGCONT $mysqld_pid");
exit(0);
EOF
diff --git a/mysql-test/suite/galera/include/galera_sst_restore.inc b/mysql-test/suite/galera/include/galera_sst_restore.inc
index 7c9a08090ad..83d07f086d1 100644
--- a/mysql-test/suite/galera/include/galera_sst_restore.inc
+++ b/mysql-test/suite/galera/include/galera_sst_restore.inc
@@ -20,7 +20,7 @@ CALL mtr.add_suppression("Can't open and lock time zone table");
CALL mtr.add_suppression("Can't open and lock privilege tables");
CALL mtr.add_suppression("Info table is not ready to be used");
CALL mtr.add_suppression("Native table .* has the wrong structure");
-
+CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist");
--disable_query_log
--eval SET GLOBAL wsrep_sst_method = '$wsrep_sst_method_orig';
--eval SET GLOBAL wsrep_sst_receive_address = '$wsrep_sst_receive_address_orig';
diff --git a/mysql-test/suite/galera/include/galera_st_clean_slave.inc b/mysql-test/suite/galera/include/galera_st_clean_slave.inc
index 3a49f4f6ad2..52044775186 100644
--- a/mysql-test/suite/galera/include/galera_st_clean_slave.inc
+++ b/mysql-test/suite/galera/include/galera_st_clean_slave.inc
@@ -34,6 +34,7 @@ COMMIT;
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql
+--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/wsrep_schema
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
index c8869746bd1..d6d7552f7b6 100644
--- a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
+++ b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
@@ -55,6 +55,14 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
--connection node_2
--source suite/galera/include/galera_load_provider.inc
+#
+# client connections were killed by provider load, so have to re-open here
+#
+--disconnect node_2
+--connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2
+--enable_reconnect
+
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
diff --git a/mysql-test/suite/galera/include/galera_unload_provider.inc b/mysql-test/suite/galera/include/galera_unload_provider.inc
index edc7eb31e0e..cd841f51fbc 100644
--- a/mysql-test/suite/galera/include/galera_unload_provider.inc
+++ b/mysql-test/suite/galera/include/galera_unload_provider.inc
@@ -3,5 +3,13 @@
--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
--let $wsrep_provider_orig = `SELECT @@wsrep_provider`
--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+--let $wsrep_error_log_orig = `SELECT @@log_error`
+if(!$wsrep_log_error_orig)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $wsrep_log_error_orig = $MYSQLTEST_VARDIR/log/mysqld.2.err;
+}
+--let LOG_FILE= $wsrep_log_error_orig
SET GLOBAL wsrep_provider = 'none';
diff --git a/mysql-test/suite/galera/r/GAL-382.result b/mysql-test/suite/galera/r/GAL-382.result
index fb7c229bd56..137efe4efba 100644
--- a/mysql-test/suite/galera/r/GAL-382.result
+++ b/mysql-test/suite/galera/r/GAL-382.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
create table t1 (i int, j int, k int, primary key pk(i)) engine=innodb;
insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3);
diff --git a/mysql-test/suite/galera/r/GAL-401.result b/mysql-test/suite/galera/r/GAL-401.result
index 3b55b7589b7..3dfc32ffb8c 100644
--- a/mysql-test/suite/galera/r/GAL-401.result
+++ b/mysql-test/suite/galera/r/GAL-401.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
connection node_2;
SET @@global.wsrep_desync = 1;
diff --git a/mysql-test/suite/galera/r/GAL-480.result b/mysql-test/suite/galera/r/GAL-480.result
index 143f48a69e3..8a4f8edcdd6 100644
--- a/mysql-test/suite/galera/r/GAL-480.result
+++ b/mysql-test/suite/galera/r/GAL-480.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 CHAR(10), f0 integer) ENGINE=InnoDB;
FLUSH TABLE t1 FOR EXPORT;
diff --git a/mysql-test/suite/galera/r/GCF-1081.result b/mysql-test/suite/galera/r/GCF-1081.result
new file mode 100644
index 00000000000..ede512ec6b1
--- /dev/null
+++ b/mysql-test/suite/galera/r/GCF-1081.result
@@ -0,0 +1,47 @@
+connection node_2;
+connection node_1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0), (3, 0);
+CREATE PROCEDURE proc_update ()
+BEGIN
+UPDATE t1 SET f2 = 1 where f1 > 0;
+END|
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+CALL proc_update ();;
+connection node_1a;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+connection node_1a;
+SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock';
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_2;
+INSERT INTO t1 VALUES (2, 2);;
+connection node_1a;
+SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached';
+SET GLOBAL DEBUG = '';
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+connection node_2;
+SELECT * FROM t1;
+f1 f2
+1 1
+2 2
+3 1
+connection node_1;
+SELECT * FROM t1;
+f1 f2
+1 1
+2 2
+3 1
+wsrep_local_replays
+1
+DROP PROCEDURE proc_update;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/GCF-939.result b/mysql-test/suite/galera/r/GCF-939.result
new file mode 100644
index 00000000000..24d4eab67e5
--- /dev/null
+++ b/mysql-test/suite/galera/r/GCF-939.result
@@ -0,0 +1,13 @@
+connection node_2;
+connection node_1;
+connection node_1;
+DROP TABLE t1;
+ERROR 42S02: Unknown table 'test.t1'
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+GRA_.log
+GRA_.log
+DROP TABLE t1;
+CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query");
+connection node_2;
+CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query");
diff --git a/mysql-test/suite/galera/r/MDEV-15443.result b/mysql-test/suite/galera/r/MDEV-15443.result
index 618e5459878..21332b372e8 100644
--- a/mysql-test/suite/galera/r/MDEV-15443.result
+++ b/mysql-test/suite/galera/r/MDEV-15443.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/MW-252.result b/mysql-test/suite/galera/r/MW-252.result
index 795d3fff670..4d458802614 100644
--- a/mysql-test/suite/galera/r/MW-252.result
+++ b/mysql-test/suite/galera/r/MW-252.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
FLUSH TABLES WITH READ LOCK;
diff --git a/mysql-test/suite/galera/r/MW-258.result b/mysql-test/suite/galera/r/MW-258.result
index 1c2a1744c98..22963557daf 100644
--- a/mysql-test/suite/galera/r/MW-258.result
+++ b/mysql-test/suite/galera/r/MW-258.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER);
LOCK TABLE t1 WRITE;
diff --git a/mysql-test/suite/galera/r/MW-259.result b/mysql-test/suite/galera/r/MW-259.result
index 5256a95c52c..9a0f2ccfa23 100644
--- a/mysql-test/suite/galera/r/MW-259.result
+++ b/mysql-test/suite/galera/r/MW-259.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
diff --git a/mysql-test/suite/galera/r/MW-284.result b/mysql-test/suite/galera/r/MW-284.result
index 0f6c0be25fe..b95639c568a 100644
--- a/mysql-test/suite/galera/r/MW-284.result
+++ b/mysql-test/suite/galera/r/MW-284.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
@@ -24,7 +26,9 @@ RESET SLAVE ALL;
CALL mtr.add_suppression('failed registering on master');
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
connection node_1;
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=OFF;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
connection node_2;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
diff --git a/mysql-test/suite/galera/r/MW-285.result b/mysql-test/suite/galera/r/MW-285.result
index 8c5a21fcbee..762f22d5d25 100644
--- a/mysql-test/suite/galera/r/MW-285.result
+++ b/mysql-test/suite/galera/r/MW-285.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent1 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB;
CREATE TABLE parent2 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB;
CREATE TABLE child (
diff --git a/mysql-test/suite/galera/r/MW-292.result b/mysql-test/suite/galera/r/MW-292.result
index 5b9214ace2a..81e5a316b63 100644
--- a/mysql-test/suite/galera/r/MW-292.result
+++ b/mysql-test/suite/galera/r/MW-292.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE rand_table (f1 FLOAT);
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
@@ -10,19 +12,28 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
f1 f2
2 a
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
-connection node_1;
-COMMIT;;
-connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
-SET SESSION wsrep_on = 0;
-SET SESSION wsrep_on = 1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
SELECT TIMEDIFF(SYSDATE(), NOW()) < 2;
TIMEDIFF(SYSDATE(), NOW()) < 2
diff --git a/mysql-test/suite/galera/r/MW-309.result b/mysql-test/suite/galera/r/MW-309.result
index 3dd49a041ee..0169b56e3e1 100644
--- a/mysql-test/suite/galera/r/MW-309.result
+++ b/mysql-test/suite/galera/r/MW-309.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 SELECT * FROM t1;
diff --git a/mysql-test/suite/galera/r/MW-313.result b/mysql-test/suite/galera/r/MW-313.result
index dc605ffc370..909caf77f1d 100644
--- a/mysql-test/suite/galera/r/MW-313.result
+++ b/mysql-test/suite/galera/r/MW-313.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 SELECT * FROM t1;
diff --git a/mysql-test/suite/galera/r/MW-328A.result b/mysql-test/suite/galera/r/MW-328A.result
index db0301b6bf2..266c5637b9b 100644
--- a/mysql-test/suite/galera/r/MW-328A.result
+++ b/mysql-test/suite/galera/r/MW-328A.result
@@ -14,10 +14,6 @@ connection node_1X;
CALL proc_update();;
connection node_2;
SET SESSION wsrep_retry_autocommit = 0;
-have_successes
-1
-have_deadlocks
-1
connection node_1;
connection node_1X;
Got one of the listed errors
@@ -25,3 +21,17 @@ connection node_1;
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
+CREATE TABLE t1 (i int primary key, j int) engine=innodb;
+INSERT INTO t1 values (1,0);
+BEGIN;
+UPDATE t1 SET j=1 WHERE i=1;
+UPDATE t1 SET j=2 WHERE i=1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+i j
+1 2
+SELECT * FROM t1;
+i j
+1 2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/MW-328B.result b/mysql-test/suite/galera/r/MW-328B.result
index e898e315ca8..d29c3a50f3d 100644
--- a/mysql-test/suite/galera/r/MW-328B.result
+++ b/mysql-test/suite/galera/r/MW-328B.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1);
CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328C.result b/mysql-test/suite/galera/r/MW-328C.result
index d8e164e7b4a..748f9420764 100644
--- a/mysql-test/suite/galera/r/MW-328C.result
+++ b/mysql-test/suite/galera/r/MW-328C.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1);
CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328D.result b/mysql-test/suite/galera/r/MW-328D.result
index 6562136ec27..43e1cefe08f 100644
--- a/mysql-test/suite/galera/r/MW-328D.result
+++ b/mysql-test/suite/galera/r/MW-328D.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (i INT) ENGINE = InnoDB;
INSERT INTO t1 (i) VALUES(1);
CREATE TABLE t2 (i INT) ENGINE = InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328E.result b/mysql-test/suite/galera/r/MW-328E.result
index 89654ec066a..729fdea1a63 100644
--- a/mysql-test/suite/galera/r/MW-328E.result
+++ b/mysql-test/suite/galera/r/MW-328E.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
create table t1 (i int primary key, j int) engine=innodb;
create table t2 (i int primary key, j int) engine=innodb;
insert into t1 values (1,0);
diff --git a/mysql-test/suite/galera/r/MW-329.result b/mysql-test/suite/galera/r/MW-329.result
index a3cb7277a9c..334ff9f80fb 100644
--- a/mysql-test/suite/galera/r/MW-329.result
+++ b/mysql-test/suite/galera/r/MW-329.result
@@ -1,10 +1,6 @@
CALL mtr.add_suppression("WSREP: .*conflict state . after post commit .*");
CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1),(65535);
-FLUSH STATUS;
-SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-VARIABLE_VALUE = 0
-1
CREATE PROCEDURE proc_insert ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
@@ -16,10 +12,7 @@ END|
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1b;
CALL proc_insert();;
-connection node_2;
-CALL mtr.add_suppression("WSREP: Failed to report last committed .*");
-SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-VARIABLE_VALUE > 0
+wsrep_local_replays
1
connection node_1;
connection node_1b;
diff --git a/mysql-test/suite/galera/r/MW-336.result b/mysql-test/suite/galera/r/MW-336.result
index e35044d872b..5961d1f3e24 100644
--- a/mysql-test/suite/galera/r/MW-336.result
+++ b/mysql-test/suite/galera/r/MW-336.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
INSERT INTO t1 values(0);
connection node_1;
diff --git a/mysql-test/suite/galera/r/MW-357.result b/mysql-test/suite/galera/r/MW-357.result
index 35855e21233..dc391be4dd3 100644
--- a/mysql-test/suite/galera/r/MW-357.result
+++ b/mysql-test/suite/galera/r/MW-357.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET GLOBAL wsrep_slave_threads = 0;
Warnings:
Warning 1292 Truncated incorrect wsrep_slave_threads value: '0'
diff --git a/mysql-test/suite/galera/r/MW-360.result b/mysql-test/suite/galera/r/MW-360.result
new file mode 100644
index 00000000000..f20d5be2135
--- /dev/null
+++ b/mysql-test/suite/galera/r/MW-360.result
@@ -0,0 +1,41 @@
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+DROP TABLE t1, t2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+DROP TABLE t1, t2;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+DROP TABLE t1;
+DROP TABLE t1;
+gtid_executed_equal
+1
diff --git a/mysql-test/suite/galera/r/MW-369.result b/mysql-test/suite/galera/r/MW-369.result
index 516904d1b2a..4f36193fd59 100644
--- a/mysql-test/suite/galera/r/MW-369.result
+++ b/mysql-test/suite/galera/r/MW-369.result
@@ -1,25 +1,36 @@
+connection node_2;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
DELETE FROM p WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
INSERT INTO c VALUES (1, 1);
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
@@ -29,6 +40,7 @@ f1 p_id
1 1
DROP TABLE c;
DROP TABLE p;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
f2 INTEGER,
@@ -36,22 +48,30 @@ CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
UPDATE c SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+connection node_2;
SELECT * FROM p;
f1 f2
1 1
@@ -61,28 +81,37 @@ f1 p_id f2
1 1 1
DROP TABLE c;
DROP TABLE p;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
DELETE FROM c WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+connection node_2;
SELECT * FROM p;
f1 f2
1 1
@@ -95,23 +124,31 @@ CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER UNIQUE KEY) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f2)) ;
INSERT INTO p VALUES (1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
INSERT INTO c VALUES (1, 0);;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
@@ -127,23 +164,31 @@ ON DELETE CASCADE) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
DELETE FROM p WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
UPDATE c SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result
index a2cf02712bb..3e532b3e12d 100644
--- a/mysql-test/suite/galera/r/MW-388.result
+++ b/mysql-test/suite/galera/r/MW-388.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
CREATE PROCEDURE insert_proc ()
@@ -18,7 +20,7 @@ connection node_1a;
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
connection node_1;
SET SESSION wsrep_sync_wait = 0;
-SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue';
+SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue';
CALL insert_proc ();;
connection node_1a;
SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached";
@@ -29,7 +31,7 @@ connection node_2;
connection node_1;
SELECT @errno = 1213;
@errno = 1213
-0
+1
SELECT * FROM t1;
f1 f2
1 node 2
diff --git a/mysql-test/suite/galera/r/MW-402.result b/mysql-test/suite/galera/r/MW-402.result
index 9be98d629fb..f692c90d611 100644
--- a/mysql-test/suite/galera/r/MW-402.result
+++ b/mysql-test/suite/galera/r/MW-402.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
@@ -20,14 +22,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -60,14 +62,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -102,14 +104,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -135,14 +137,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -159,8 +161,10 @@ DROP TABLE p;
connection node_1;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
-CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
-CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+f2 INTEGER,
+CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
@@ -179,14 +183,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
connection node_2;
@@ -197,4 +201,52 @@ f1 f2
1 2
SELECT * FROM c;
f1 p1_id p2_id f2
+DROP TABLE c;
+DROP TABLE p1;
+DROP TABLE p2;
+connection node_1;
+CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+f2 INTEGER,
+CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ON DELETE CASCADE,
+CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)
+ON DELETE CASCADE);
+INSERT INTO p1 VALUES (1, 0);
+INSERT INTO p2 VALUES (1, 0);
+INSERT INTO c VALUES (1, 1, 1, 0);
+connection node_1a;
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+DELETE FROM p2 WHERE f1=1;
+connection node_1a;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+DELETE FROM p1 WHERE f1=1;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
+SELECT * FROM p1;
+f1 f2
+SELECT * FROM p2;
+f1 f2
+1 0
+SELECT * FROM c;
+f1 p1_id p2_id f2
DROP TABLE c,p1,p2;
diff --git a/mysql-test/suite/galera/r/MW-416.result b/mysql-test/suite/galera/r/MW-416.result
index 05399b213a8..3bcd89a0cd0 100644
--- a/mysql-test/suite/galera/r/MW-416.result
+++ b/mysql-test/suite/galera/r/MW-416.result
@@ -109,6 +109,6 @@ mtr
mysql
performance_schema
test
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
-Variable_name Value
-wsrep_replicated 3
+wsrep_schema
+wsrep_replicated_after_diff
+1
diff --git a/mysql-test/suite/galera/r/MW-86-wait1.result b/mysql-test/suite/galera/r/MW-86-wait1.result
index 00010eaedcb..36cbfadf302 100644
--- a/mysql-test/suite/galera/r/MW-86-wait1.result
+++ b/mysql-test/suite/galera/r/MW-86-wait1.result
@@ -1,11 +1,13 @@
connection node_2;
+connection node_1;
+SET @orig_debug=@@debug;
+connection node_2;
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
+set debug_sync='RESET';
SET SESSION wsrep_sync_wait = 1;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
connection node_1;
CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t_wait1 VALUES (1);
@@ -36,16 +38,11 @@ SHOW TABLES;
SHOW TRIGGERS;
SHOW GLOBAL VARIABLES LIKE 'foo_bar';
SHOW WARNINGS;
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = @orig_debug;
SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
DROP TABLE t_wait1;
-SET GLOBAL debug = NULL;
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
-SET debug_sync='RESET';
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
diff --git a/mysql-test/suite/galera/r/MW-86-wait8.result b/mysql-test/suite/galera/r/MW-86-wait8.result
index 47e0ebc1342..6ac2c5f5e1f 100644
--- a/mysql-test/suite/galera/r/MW-86-wait8.result
+++ b/mysql-test/suite/galera/r/MW-86-wait8.result
@@ -1,11 +1,12 @@
connection node_2;
+connection node_1;
+SET @orig_debug=@@debug;
+connection node_2;
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
SET SESSION wsrep_sync_wait = 8;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
connection node_1;
CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t_wait8 VALUES (1);
@@ -38,16 +39,11 @@ SHOW TABLES;
SHOW TRIGGERS;
SHOW GLOBAL VARIABLES LIKE 'foo_bar';
SHOW WARNINGS;
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = @orig_debug;
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
DROP TABLE t_wait8;
-SET GLOBAL debug = NULL;
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
-SET debug_sync='RESET';
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
diff --git a/mysql-test/suite/galera/r/MW-86.result b/mysql-test/suite/galera/r/MW-86.result
new file mode 100644
index 00000000000..bca9be93191
--- /dev/null
+++ b/mysql-test/suite/galera/r/MW-86.result
@@ -0,0 +1,78 @@
+connection node_2;
+connection node_1;
+connection node_2;
+SET SESSION wsrep_sync_wait = 1;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_1;
+CREATE DATABASE db1;
+CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO bar VALUES (1);
+connection node_2;
+SHOW BINARY LOGS;
+SHOW BINLOG EVENTS;
+SHOW COLUMNS FROM t1;
+SHOW CREATE DATABASE db1;
+SHOW CREATE EVENT e1;
+SHOW CREATE FUNCTION f1;
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE TABLE t1;
+SHOW CREATE TRIGGER tr1;
+SHOW CREATE VIEW v1;
+SHOW DATABASES;
+SHOW ENGINE InnoDB STATUS;
+SHOW FUNCTION CODE f1;
+SHOW FUNCTION STATUS;
+SHOW GRANTS FOR 'root'@'localhost';
+SHOW INDEX FROM t1;
+SHOW OPEN TABLES;
+SHOW PROCEDURE CODE p1;
+SHOW PROCEDURE STATUS;
+SHOW PRIVILEGES;
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SHOW TABLE STATUS;
+SHOW TABLES;
+SHOW TRIGGERS;
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+SHOW WARNINGS;
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET SESSION wsrep_sync_wait = 8;
+DROP DATABASE db1;
+connection node_2;
+SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S";
+SET SESSION wsrep_sync_wait = 8;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+connection node_1;
+CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO q VALUES (1);
+connection node_2;
+SHOW BINARY LOGS;
+SHOW BINLOG EVENTS;
+SHOW COLUMNS FROM t1;
+SHOW CREATE DATABASE db1;
+SHOW CREATE EVENT e1;
+SHOW CREATE FUNCTION f1;
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE TABLE t1;
+SHOW CREATE TRIGGER tr1;
+SHOW CREATE VIEW v1;
+SHOW DATABASES;
+SHOW ENGINE InnoDB STATUS;
+SHOW FUNCTION CODE f1;
+SHOW FUNCTION STATUS;
+SHOW GRANTS FOR 'root'@'localhost';
+SHOW INDEX FROM t1;
+SHOW OPEN TABLES;
+SHOW PROCEDURE CODE p1;
+SHOW PROCEDURE STATUS;
+SHOW PRIVILEGES;
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SHOW TABLE STATUS;
+SHOW TABLES;
+SHOW TRIGGERS;
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+SHOW WARNINGS;
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
diff --git a/mysql-test/suite/galera/r/basic.result b/mysql-test/suite/galera/r/basic.result
index e85c805253f..10f180e7a94 100644
--- a/mysql-test/suite/galera/r/basic.result
+++ b/mysql-test/suite/galera/r/basic.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE test;
CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
diff --git a/mysql-test/suite/galera/r/binlog_checksum.result b/mysql-test/suite/galera/r/binlog_checksum.result
index e86f3892ac7..4106354eb7d 100644
--- a/mysql-test/suite/galera/r/binlog_checksum.result
+++ b/mysql-test/suite/galera/r/binlog_checksum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM;
diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result
index a445b32e8bf..6ad94dd3d43 100644
--- a/mysql-test/suite/galera/r/create.result
+++ b/mysql-test/suite/galera/r/create.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-6924 : Server crashed on CREATE TABLE ... SELECT
#
diff --git a/mysql-test/suite/galera/r/enforce_storage_engine.result b/mysql-test/suite/galera/r/enforce_storage_engine.result
index 746aa22bf20..1a453241427 100644
--- a/mysql-test/suite/galera/r/enforce_storage_engine.result
+++ b/mysql-test/suite/galera/r/enforce_storage_engine.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-8831 : enforce_storage_engine doesn't block table creation on
# other nodes (galera cluster)
diff --git a/mysql-test/suite/galera/r/enforce_storage_engine2.result b/mysql-test/suite/galera/r/enforce_storage_engine2.result
index 128994ed221..8b174139eae 100644
--- a/mysql-test/suite/galera/r/enforce_storage_engine2.result
+++ b/mysql-test/suite/galera/r/enforce_storage_engine2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-9312: storage engine not enforced during galera cluster
# replication
diff --git a/mysql-test/suite/galera/r/ev51914.result b/mysql-test/suite/galera/r/ev51914.result
index 3f3d67d01ef..b9d8a82bfa0 100644
--- a/mysql-test/suite/galera/r/ev51914.result
+++ b/mysql-test/suite/galera/r/ev51914.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SAVEPOINT in a stored function should be forbidden
CREATE FUNCTION f1 () RETURNS INT BEGIN
diff --git a/mysql-test/suite/galera/r/fk.result b/mysql-test/suite/galera/r/fk.result
index ab8e1c8f680..17fc99a904e 100644
--- a/mysql-test/suite/galera/r/fk.result
+++ b/mysql-test/suite/galera/r/fk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE test;
# On node_1
diff --git a/mysql-test/suite/galera/r/galera#414.result b/mysql-test/suite/galera/r/galera#414.result
index 34dcb6242d3..2c1dccfd131 100644
--- a/mysql-test/suite/galera/r/galera#414.result
+++ b/mysql-test/suite/galera/r/galera#414.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_admin.result b/mysql-test/suite/galera/r/galera_admin.result
index ed753247236..3db60e99409 100644
--- a/mysql-test/suite/galera/r/galera_admin.result
+++ b/mysql-test/suite/galera/r/galera_admin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS t1, t2;
DROP TABLE IF EXISTS x1, x2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
index ff6ab792c0e..dfa30441f85 100644
--- a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
+++ b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
ALTER TABLE t1 ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
index 389383858ac..b3a9bdd30df 100644
--- a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
+++ b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_replicate_myisam = TRUE;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_alter_table_force.result b/mysql-test/suite/galera/r/galera_alter_table_force.result
index d0a2f81b631..271796422cd 100644
--- a/mysql-test/suite/galera/r/galera_alter_table_force.result
+++ b/mysql-test/suite/galera/r/galera_alter_table_force.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
ALTER TABLE t1 FORCE;
diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
index a6607906661..11fda5d8aab 100644
--- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
+++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION wsrep_sync_wait = 0;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
index 9711100d155..a5aeb6eb366 100644
--- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
+++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION wsrep_sync_wait = 0;
SET SESSION lock_wait_timeout = 60;
diff --git a/mysql-test/suite/galera/r/galera_as_master.result b/mysql-test/suite/galera/r/galera_as_master.result
index 2a7262359fa..4aca328be56 100644
--- a/mysql-test/suite/galera/r/galera_as_master.result
+++ b/mysql-test/suite/galera/r/galera_as_master.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
START SLAVE;
connection node_1;
@@ -54,4 +56,6 @@ STOP SLAVE;
RESET SLAVE ALL;
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
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_master_gtid.result b/mysql-test/suite/galera/r/galera_as_master_gtid.result
index 8dfe462d495..4f5c38b607a 100644
--- a/mysql-test/suite/galera/r/galera_as_master_gtid.result
+++ b/mysql-test/suite/galera/r/galera_as_master_gtid.result
@@ -5,55 +5,19 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
uuids_do_not_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000002 120 Previous_gtids 1 151
-mysqld-bin.000002 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000002 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000002 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000002 375 Query 1 452 BEGIN
-mysqld-bin.000002 452 Table_map 1 497 table_id: # (test.t1)
-mysqld-bin.000002 497 Write_rows 1 537 table_id: # flags: STMT_END_F
-mysqld-bin.000002 537 Xid 1 568 COMMIT /* xid=# */
INSERT INTO t1 VALUES(2);
uuids_do_not_match
1
uuids_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000003 120 Previous_gtids 2 151
-mysqld-bin.000003 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000003 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000003 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000003 375 Query 1 443 BEGIN
-mysqld-bin.000003 443 Table_map 1 488 table_id: # (test.t1)
-mysqld-bin.000003 488 Write_rows 1 528 table_id: # flags: STMT_END_F
-mysqld-bin.000003 528 Xid 1 559 COMMIT /* xid=# */
-mysqld-bin.000003 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3'
-mysqld-bin.000003 607 Query 2 684 BEGIN
-mysqld-bin.000003 684 Table_map 2 729 table_id: # (test.t1)
-mysqld-bin.000003 729 Write_rows 2 769 table_id: # flags: STMT_END_F
-mysqld-bin.000003 769 Xid 2 800 COMMIT /* xid=# */
uuids_do_not_match
1
uuids_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000001 120 Previous_gtids 3 151
-mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000001 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000001 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000001 375 Query 1 443 BEGIN
-mysqld-bin.000001 443 Table_map 1 488 table_id: # (test.t1)
-mysqld-bin.000001 488 Write_rows 1 528 table_id: # flags: STMT_END_F
-mysqld-bin.000001 528 Xid 1 559 COMMIT /* xid=# */
-mysqld-bin.000001 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3'
-mysqld-bin.000001 607 Query 2 675 BEGIN
-mysqld-bin.000001 675 Table_map 2 720 table_id: # (test.t1)
-mysqld-bin.000001 720 Write_rows 2 760 table_id: # flags: STMT_END_F
-mysqld-bin.000001 760 Xid 2 791 COMMIT /* xid=# */
DROP TABLE t1;
+gtid_executed_equal
+1
+gtid_executed_equal
+1
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/r/galera_as_master_large.result b/mysql-test/suite/galera/r/galera_as_master_large.result
index dad74211af9..826d2f32057 100644
--- a/mysql-test/suite/galera/r/galera_as_master_large.result
+++ b/mysql-test/suite/galera/r/galera_as_master_large.result
@@ -2,6 +2,8 @@
# MDEV-9044 : Getting binlog corruption on my Galera cluster (10.1.8)
# making it impossible to async slave.
#
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
START SLAVE;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
index 60f3216aa9c..2da72af0d9b 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
SET SESSION binlog_format='STATEMENT';
@@ -85,4 +87,6 @@ connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
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.result b/mysql-test/suite/galera/r/galera_as_slave_gtid.result
index 0ef9d208bf4..1262879d992 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_gtid.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
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
new file mode 100644
index 00000000000..9f10efccd22
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
@@ -0,0 +1,160 @@
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
+connection node_1;
+connection node_1;
+RESET MASTER;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+connection node_2;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+START SLAVE;
+connection node_1;
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+UPDATE test2.t1 SET test2.t1.f2 = 'cde';
+UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz';
+DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO test2.t1 (f1) VALUES (999);
+INSERT INTO test2.t1 (f1) VALUES (9999);
+COMMIT;
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (111);
+INSERT INTO test1.t1 (f1) VALUES (222);
+COMMIT;
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (333);
+INSERT INTO test2.t1 (f1) VALUES (99999);
+COMMIT;
+connection node_2;
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 256 Gtid_list 2 285 []
+master-bin.000001 285 Binlog_checkpoint 2 329 master-bin.000001
+master-bin.000001 329 Gtid 1 371 GTID 0-1-1
+master-bin.000001 371 Query 1 458 CREATE SCHEMA test1
+master-bin.000001 458 Gtid 1 500 GTID 0-1-3
+master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB
+master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-5
+master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1)
+master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1)
+master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F
+master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */
+master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-7
+master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2)
+master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1)
+master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F
+master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */
+master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-9
+master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3)
+master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1)
+master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F
+master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */
+master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-12
+master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'
+master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1)
+master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F
+master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */
+master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-13
+master-bin.000001 1661 Annotate_rows 1 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 1 1844 table_id: ### (test1.t1)
+master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F
+master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */
+master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-15
+master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111)
+master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1)
+master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F
+master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222)
+master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1)
+master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F
+master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */
+master-bin.000001 2294 Gtid 1 2336 BEGIN GTID <effective_uuid>
+master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333)
+master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1)
+master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F
+master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */
+connection node_3;
+gtid_executed_equal
+0
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 256 Gtid_list 3 285 []
+master-bin.000001 285 Binlog_checkpoint 3 329 master-bin.000001
+master-bin.000001 329 Gtid 1 371 GTID 0-1-1
+master-bin.000001 371 Query 1 458 CREATE SCHEMA test1
+master-bin.000001 458 Gtid 1 500 GTID 0-1-2
+master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB
+master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-3
+master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1)
+master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1)
+master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F
+master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */
+master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-4
+master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2)
+master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1)
+master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F
+master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */
+master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-5
+master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3)
+master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1)
+master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F
+master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */
+master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-6
+master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'
+master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1)
+master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F
+master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */
+master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-7
+master-bin.000001 1661 Annotate_rows 1 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 1 1844 table_id: ### (test1.t1)
+master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F
+master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */
+master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-8
+master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111)
+master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1)
+master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F
+master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222)
+master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1)
+master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F
+master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */
+master-bin.000001 2294 Gtid 1 2336 BEGIN GTID 0-1-9
+master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333)
+master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1)
+master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F
+master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */
+include/diff_servers.inc [servers=2 3]
+connection node_3;
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2);
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333);
+COUNT(*) = 3
+1
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm';
+COUNT(*) = 2
+1
+USE test2;
+ERROR 42000: Unknown database 'test2'
+connection node_1;
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+connection node_3;
+connection node_2;
+STOP SLAVE;
+RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result
new file mode 100644
index 00000000000..fc10cc01a45
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result
@@ -0,0 +1,315 @@
+RESET MASTER;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+START SLAVE USER='root';
+Warnings:
+Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+SET SESSION wsrep_on=OFF;
+include/wait_for_slave_sql_error.inc [errno=1047]
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+INSERT INTO test1.t1 (f1) VALUES (5);
+INSERT INTO test2.t1 (f1) VALUES (5);
+SET SESSION wsrep_on=ON;
+INSERT INTO test1.t1 (f1) VALUES (6);
+INSERT INTO test2.t1 (f1) VALUES (6);
+START SLAVE;
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 120 Previous_gtids 2 151
+mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1'
+mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1
+mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2'
+mysqld-bin.000001 342 Query 1 415 BEGIN
+mysqld-bin.000001 415 Query 1 489 COMMIT
+mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3'
+mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4'
+mysqld-bin.000001 703 Query 1 776 BEGIN
+mysqld-bin.000001 776 Query 1 850 COMMIT
+mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5'
+mysqld-bin.000001 898 Query 1 961 BEGIN
+mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1)
+mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */
+mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6'
+mysqld-bin.000001 1126 Query 1 1189 BEGIN
+mysqld-bin.000001 1189 Query 1 1253 COMMIT
+mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7'
+mysqld-bin.000001 1301 Query 1 1364 BEGIN
+mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1)
+mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */
+mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8'
+mysqld-bin.000001 1529 Query 1 1592 BEGIN
+mysqld-bin.000001 1592 Query 1 1656 COMMIT
+mysqld-bin.000001 1656 Gtid 2 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12'
+mysqld-bin.000001 1704 Query 2 1772 BEGIN
+mysqld-bin.000001 1772 Ignorable 2 1795 # Unrecognized ignorable event
+mysqld-bin.000001 1795 Query 2 1864 COMMIT
+mysqld-bin.000001 1864 Gtid 2 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13'
+mysqld-bin.000001 1912 Query 2 1980 BEGIN
+mysqld-bin.000001 1980 Ignorable 2 2003 # Unrecognized ignorable event
+mysqld-bin.000001 2003 Query 2 2072 COMMIT
+mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9'
+mysqld-bin.000001 2120 Query 1 2183 BEGIN
+mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1)
+mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */
+mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10'
+mysqld-bin.000001 2348 Query 1 2411 BEGIN
+mysqld-bin.000001 2411 Query 1 2475 COMMIT
+mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11'
+mysqld-bin.000001 2523 Query 1 2586 BEGIN
+mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1)
+mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */
+mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12'
+mysqld-bin.000001 2751 Query 1 2814 BEGIN
+mysqld-bin.000001 2814 Query 1 2878 COMMIT
+mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13'
+mysqld-bin.000001 2926 Query 1 2989 BEGIN
+mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1)
+mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */
+mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14'
+mysqld-bin.000001 3154 Query 1 3217 BEGIN
+mysqld-bin.000001 3217 Query 1 3281 COMMIT
+mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15'
+mysqld-bin.000001 3329 Query 1 3392 BEGIN
+mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1)
+mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */
+mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16'
+mysqld-bin.000001 3557 Query 1 3620 BEGIN
+mysqld-bin.000001 3620 Query 1 3684 COMMIT
+mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17'
+mysqld-bin.000001 3732 Query 1 3795 BEGIN
+mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1)
+mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */
+mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18'
+mysqld-bin.000001 3960 Query 1 4023 BEGIN
+mysqld-bin.000001 4023 Query 1 4087 COMMIT
+mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19'
+mysqld-bin.000001 4135 Query 1 4198 BEGIN
+mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1)
+mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */
+mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20'
+mysqld-bin.000001 4363 Query 1 4426 BEGIN
+mysqld-bin.000001 4426 Query 1 4490 COMMIT
+mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21'
+mysqld-bin.000001 4538 Query 1 4601 BEGIN
+mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1)
+mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */
+mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22'
+mysqld-bin.000001 4766 Query 1 4829 BEGIN
+mysqld-bin.000001 4829 Query 1 4893 COMMIT
+mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23'
+mysqld-bin.000001 4941 Query 1 5004 BEGIN
+mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1)
+mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */
+mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24'
+mysqld-bin.000001 5169 Query 1 5232 BEGIN
+mysqld-bin.000001 5232 Query 1 5296 COMMIT
+mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25'
+mysqld-bin.000001 5344 Query 1 5407 BEGIN
+mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1)
+mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */
+mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26'
+mysqld-bin.000001 5572 Query 1 5635 BEGIN
+mysqld-bin.000001 5635 Query 1 5699 COMMIT
+mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27'
+mysqld-bin.000001 5747 Query 1 5810 BEGIN
+mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1)
+mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */
+mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28'
+mysqld-bin.000001 5975 Query 1 6038 BEGIN
+mysqld-bin.000001 6038 Query 1 6102 COMMIT
+mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29'
+mysqld-bin.000001 6150 Query 1 6213 BEGIN
+mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1)
+mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */
+mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30'
+mysqld-bin.000001 6378 Query 1 6441 BEGIN
+mysqld-bin.000001 6441 Query 1 6505 COMMIT
+USE test2;
+ERROR 42000: Unknown database 'test2'
+gtid_executed_equal
+1
+USE test2;
+ERROR 42000: Unknown database 'test2'
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 120 Previous_gtids 4 151
+mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1'
+mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1
+mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2'
+mysqld-bin.000001 342 Query 1 415 BEGIN
+mysqld-bin.000001 415 Query 1 489 COMMIT
+mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3'
+mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4'
+mysqld-bin.000001 703 Query 1 776 BEGIN
+mysqld-bin.000001 776 Query 1 850 COMMIT
+mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5'
+mysqld-bin.000001 898 Query 1 961 BEGIN
+mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1)
+mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */
+mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6'
+mysqld-bin.000001 1126 Query 1 1189 BEGIN
+mysqld-bin.000001 1189 Query 1 1253 COMMIT
+mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7'
+mysqld-bin.000001 1301 Query 1 1364 BEGIN
+mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1)
+mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */
+mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8'
+mysqld-bin.000001 1529 Query 1 1592 BEGIN
+mysqld-bin.000001 1592 Query 1 1656 COMMIT
+mysqld-bin.000001 1656 Gtid 4 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12'
+mysqld-bin.000001 1704 Query 4 1772 BEGIN
+mysqld-bin.000001 1772 Ignorable 4 1795 # Unrecognized ignorable event
+mysqld-bin.000001 1795 Query 4 1864 COMMIT
+mysqld-bin.000001 1864 Gtid 4 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13'
+mysqld-bin.000001 1912 Query 4 1980 BEGIN
+mysqld-bin.000001 1980 Ignorable 4 2003 # Unrecognized ignorable event
+mysqld-bin.000001 2003 Query 4 2072 COMMIT
+mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9'
+mysqld-bin.000001 2120 Query 1 2183 BEGIN
+mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1)
+mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */
+mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10'
+mysqld-bin.000001 2348 Query 1 2411 BEGIN
+mysqld-bin.000001 2411 Query 1 2475 COMMIT
+mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11'
+mysqld-bin.000001 2523 Query 1 2586 BEGIN
+mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1)
+mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */
+mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12'
+mysqld-bin.000001 2751 Query 1 2814 BEGIN
+mysqld-bin.000001 2814 Query 1 2878 COMMIT
+mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13'
+mysqld-bin.000001 2926 Query 1 2989 BEGIN
+mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1)
+mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */
+mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14'
+mysqld-bin.000001 3154 Query 1 3217 BEGIN
+mysqld-bin.000001 3217 Query 1 3281 COMMIT
+mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15'
+mysqld-bin.000001 3329 Query 1 3392 BEGIN
+mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1)
+mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */
+mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16'
+mysqld-bin.000001 3557 Query 1 3620 BEGIN
+mysqld-bin.000001 3620 Query 1 3684 COMMIT
+mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17'
+mysqld-bin.000001 3732 Query 1 3795 BEGIN
+mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1)
+mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */
+mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18'
+mysqld-bin.000001 3960 Query 1 4023 BEGIN
+mysqld-bin.000001 4023 Query 1 4087 COMMIT
+mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19'
+mysqld-bin.000001 4135 Query 1 4198 BEGIN
+mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1)
+mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */
+mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20'
+mysqld-bin.000001 4363 Query 1 4426 BEGIN
+mysqld-bin.000001 4426 Query 1 4490 COMMIT
+mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21'
+mysqld-bin.000001 4538 Query 1 4601 BEGIN
+mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1)
+mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */
+mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22'
+mysqld-bin.000001 4766 Query 1 4829 BEGIN
+mysqld-bin.000001 4829 Query 1 4893 COMMIT
+mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23'
+mysqld-bin.000001 4941 Query 1 5004 BEGIN
+mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1)
+mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */
+mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24'
+mysqld-bin.000001 5169 Query 1 5232 BEGIN
+mysqld-bin.000001 5232 Query 1 5296 COMMIT
+mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25'
+mysqld-bin.000001 5344 Query 1 5407 BEGIN
+mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1)
+mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */
+mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26'
+mysqld-bin.000001 5572 Query 1 5635 BEGIN
+mysqld-bin.000001 5635 Query 1 5699 COMMIT
+mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27'
+mysqld-bin.000001 5747 Query 1 5810 BEGIN
+mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1)
+mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */
+mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28'
+mysqld-bin.000001 5975 Query 1 6038 BEGIN
+mysqld-bin.000001 6038 Query 1 6102 COMMIT
+mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29'
+mysqld-bin.000001 6150 Query 1 6213 BEGIN
+mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1)
+mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */
+mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30'
+mysqld-bin.000001 6378 Query 1 6441 BEGIN
+mysqld-bin.000001 6441 Query 1 6505 COMMIT
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+STOP SLAVE;
+RESET SLAVE ALL;
+CALL mtr.add_suppression("GTID replication failed");
+CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed");
+CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query");
+CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query");
+CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047");
diff --git a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
index 365ea31f292..6baf930aed2 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
@@ -1,13 +1,28 @@
+connection node_2;
+connection node_1;
+connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
+connection node_2;
START SLAVE;
SET SESSION wsrep_sync_wait = 0;
+connection node_4;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connection node_1;
+connection node_4;
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+connection node_2;
+connection node_1;
expected_error
1
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
+connection node_2;
START SLAVE;
+connection node_4;
DROP TABLE t1;
+connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
CALL mtr.add_suppression("Slave SQL: Error 'Unknown command' on query");
@@ -15,4 +30,7 @@ CALL mtr.add_suppression("Slave: Unknown command Error_code: 1047");
CALL mtr.add_suppression("Transport endpoint is not connected");
CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed, 'Deadlock found when trying to get lock; try restarting transaction', Error_code: 1213");
CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+connection node_4;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
index d0fac1e3d14..0d6a6ebbbc1 100644
--- a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
+++ b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
CREATE PROCEDURE p1 ()
diff --git a/mysql-test/suite/galera/r/galera_bf_abort.result b/mysql-test/suite/galera/r/galera_bf_abort.result
index c2e89965fce..cb4a27c82fd 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(6)) ENGINE=InnoDB;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
@@ -9,7 +11,7 @@ INSERT INTO t1 VALUES (1,'node_1');
connection node_2a;
connection node_2;
INSERT INTO t1 VALUES (2, 'node_2');
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
index 7b98c807efb..1150a9fff63 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
index ec8bddb087a..7dd3053b7bb 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 10);
connection node_1;
@@ -10,7 +12,7 @@ UPDATE t1 SET f1 = 2;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_bf_aborts_diff
1
connection node_1;
@@ -23,7 +25,7 @@ UPDATE t1 SET f2 = 20;
connection node_1a;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_bf_aborts_diff
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
index ae1ca6d2157..43ca6089d78 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
index 8c6c7b7d7a4..0ef2a1a72c6 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2a;
SELECT GET_LOCK("foo", 1000);
@@ -10,7 +12,7 @@ SELECT GET_LOCK("foo", 1000);;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result
new file mode 100644
index 00000000000..52d44c3d510
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result
@@ -0,0 +1,685 @@
+SET SESSION wsrep_sync_wait = 0;
+galera_sr_bf_abort_at_commit = 0
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
index 81b5816ddbe..e7882e43b6a 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result
new file mode 100644
index 00000000000..08833cbd503
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result
@@ -0,0 +1,9 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+connection node_2;
+SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue';
+INSERT INTO t1 VALUES (1);
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
index 9cd6abad5a1..00d6600d264 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
@@ -6,7 +8,7 @@ SELECT SLEEP(1000);;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_background_statistics.result b/mysql-test/suite/galera/r/galera_bf_background_statistics.result
index c2c3fce2b14..a8c8842b8e1 100644
--- a/mysql-test/suite/galera/r/galera_bf_background_statistics.result
+++ b/mysql-test/suite/galera/r/galera_bf_background_statistics.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT @@innodb_stats_persistent;
@@innodb_stats_persistent
1
@@ -27,7 +29,7 @@ SELECT SLEEP(1000);;
connection node_1;
ALTER TABLE t1 CHANGE f2 f2 INTEGER NOT NULL DEFAULT 1;
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
index 7ec524da888..f893848a72d 100644
--- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result
+++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
ALTER TABLE t1 add primary key(a);
CREATE PROCEDURE p1()
diff --git a/mysql-test/suite/galera/r/galera_binlog_cache_size.result b/mysql-test/suite/galera/r/galera_binlog_cache_size.result
index 6aac74ab5f0..c5a09074537 100644
--- a/mysql-test/suite/galera/r/galera_binlog_cache_size.result
+++ b/mysql-test/suite/galera/r/galera_binlog_cache_size.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(767)) ENGINE=InnoDB;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_binlog_checksum.result b/mysql-test/suite/galera/r/galera_binlog_checksum.result
index 7303aa61122..3ef7cf5c41e 100644
--- a/mysql-test/suite/galera/r/galera_binlog_checksum.result
+++ b/mysql-test/suite/galera/r/galera_binlog_checksum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
index 46582ff5c4b..b513c491bb0 100644
--- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
+++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 VARCHAR(1000));
diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
index 7b88af5d5af..6c2279bece0 100644
--- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
+++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(1000));
INSERT INTO t1 VALUES (REPEAT('x', 1000));
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_binlog_row_image.result b/mysql-test/suite/galera/r/galera_binlog_row_image.result
index d54db61105e..20e6bd9fab8 100644
--- a/mysql-test/suite/galera/r/galera_binlog_row_image.result
+++ b/mysql-test/suite/galera/r/galera_binlog_row_image.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_row_image=minimal;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_commit_empty.result b/mysql-test/suite/galera/r/galera_commit_empty.result
new file mode 100644
index 00000000000..75b94c54b1e
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_commit_empty.result
@@ -0,0 +1,15 @@
+connection node_2;
+connection node_1;
+START TRANSACTION;
+COMMIT;
+START TRANSACTION;
+COMMIT;
+START TRANSACTION READ ONLY;
+COMMIT;
+START TRANSACTION;
+COMMIT;
+START TRANSACTION;
+START TRANSACTION;
+COMMIT;
+wsrep_last_committed_diff
+1
diff --git a/mysql-test/suite/galera/r/galera_create_function.result b/mysql-test/suite/galera/r/galera_create_function.result
index 9118c2864f3..85fa85d81f1 100644
--- a/mysql-test/suite/galera/r/galera_create_function.result
+++ b/mysql-test/suite/galera/r/galera_create_function.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE USER 'user1';
CREATE
diff --git a/mysql-test/suite/galera/r/galera_create_procedure.result b/mysql-test/suite/galera/r/galera_create_procedure.result
index 98dc4a856dc..24a0bd66b39 100644
--- a/mysql-test/suite/galera/r/galera_create_procedure.result
+++ b/mysql-test/suite/galera/r/galera_create_procedure.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE USER 'user1';
CREATE TABLE t1 (f1 INTEGER);
diff --git a/mysql-test/suite/galera/r/galera_create_table_as_select.result b/mysql-test/suite/galera/r/galera_create_table_as_select.result
new file mode 100644
index 00000000000..6f65ee99f0a
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_create_table_as_select.result
@@ -0,0 +1,103 @@
+connection node_2;
+connection node_1;
+connection node_1;
+SET SESSION default_storage_engine=InnoDB;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+ERROR 42S01: Table 't1' already exists
+DROP TABLE t1,t2;
+CREATE TABLE t1 AS SELECT * FROM t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1 AS SELECT 1 FROM DUAL;
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+connection node_1;
+DROP TABLE t1;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+connection node_2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_1;
+DROP TABLE t1,t2;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_1;
+DROP TABLE t1,t2;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2;
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT f1 = 5 FROM t1;
+f1 = 5
+1
+connection node_1;
+DROP TABLE t1,t2;
+connection node_1;
+CREATE PROCEDURE sp1 ()
+BEGIN
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+END|
+CALL sp1();
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_1;
+DROP TABLE t1, t2;
+DROP PROCEDURE sp1;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2';
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+LOCK TABLE t2 WRITE;
+connection node_1;
+CREATE TABLE t1 AS SELECT * FROM t2;;
+connection node_2;
+SELECT COUNT(*) = 5 FROM t2;
+COUNT(*) = 5
+1
+CREATE TABLE t1 AS SELECT * FROM t2;
+connection node_1a;
+UNLOCK TABLES;
+connection node_1;
+Got one of the listed errors
+DROP TABLE t1, t2;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2;
+connection node_2;
+SELECT * FROM t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query");
+connection node_1;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera/r/galera_create_table_like.result b/mysql-test/suite/galera/r/galera_create_table_like.result
index 131ac311bca..82543331ad5 100644
--- a/mysql-test/suite/galera/r/galera_create_table_like.result
+++ b/mysql-test/suite/galera/r/galera_create_table_like.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE SCHEMA schema1;
CREATE SCHEMA schema2;
USE schema1;
diff --git a/mysql-test/suite/galera/r/galera_create_trigger.result b/mysql-test/suite/galera/r/galera_create_trigger.result
index d07a007543e..56b35150d87 100644
--- a/mysql-test/suite/galera/r/galera_create_trigger.result
+++ b/mysql-test/suite/galera/r/galera_create_trigger.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE definer_root (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
CREATE TABLE definer_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
CREATE TABLE definer_current_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_ddl_multiline.result b/mysql-test/suite/galera/r/galera_ddl_multiline.result
index 339a91125eb..9e70731a62b 100644
--- a/mysql-test/suite/galera/r/galera_ddl_multiline.result
+++ b/mysql-test/suite/galera/r/galera_ddl_multiline.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result
index 8083784bb01..9590ed2963b 100644
--- a/mysql-test/suite/galera/r/galera_defaults.result
+++ b/mysql-test/suite/galera/r/galera_defaults.result
@@ -1,6 +1,12 @@
-SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
-COUNT(*) = 43
-0
+connection node_2;
+connection node_1;
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)'
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)'
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
+COUNT(*)
+48
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME LIKE 'wsrep_%'
@@ -31,6 +37,7 @@ WSREP_DRUPAL_282555_WORKAROUND OFF
WSREP_FORCED_BINLOG_FORMAT NONE
WSREP_GTID_DOMAIN_ID 0
WSREP_GTID_MODE OFF
+WSREP_IGNORE_APPLY_ERRORS 7
WSREP_LOAD_DATA_SPLITTING ON
WSREP_LOG_CONFLICTS OFF
WSREP_MAX_WS_ROWS 0
@@ -47,9 +54,17 @@ WSREP_RETRY_AUTOCOMMIT 1
WSREP_SLAVE_FK_CHECKS ON
WSREP_SLAVE_THREADS 1
WSREP_SLAVE_UK_CHECKS OFF
+WSREP_SR_STORE table
WSREP_SST_AUTH
WSREP_SST_DONOR
WSREP_SST_DONOR_REJECTS_QUERIES OFF
WSREP_SST_METHOD rsync
WSREP_SYNC_WAIT 15
-<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = no; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMC
AST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>;socket.checksum = 2; socket.recv_buf_size = 212992;
+WSREP_TRX_FRAGMENT_SIZE 0
+WSREP_TRX_FRAGMENT_UNIT bytes
+<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 1; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = yes; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GM
CAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>; socket.checksum = 2; socket.recv_buf_size = 212992;
+WSREP_CLUSTER_CAPABILITIES
+WSREP_CLUSTER_WEIGHT
+WSREP_OPEN_CONNECTIONS
+WSREP_OPEN_TRANSACTIONS
+WSREP_PROVIDER_CAPABILITIES
diff --git a/mysql-test/suite/galera/r/galera_delete_limit.result b/mysql-test/suite/galera/r/galera_delete_limit.result
index f6fb2e56346..9898bfcf169 100644
--- a/mysql-test/suite/galera/r/galera_delete_limit.result
+++ b/mysql-test/suite/galera/r/galera_delete_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) Engine=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_desync_overlapped.result b/mysql-test/suite/galera/r/galera_desync_overlapped.result
index f9920e7f7ad..e3f40d444ee 100644
--- a/mysql-test/suite/galera/r/galera_desync_overlapped.result
+++ b/mysql-test/suite/galera/r/galera_desync_overlapped.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_drop_multi.result b/mysql-test/suite/galera/r/galera_drop_multi.result
index 7793ef93b90..1ff8afe3219 100644
--- a/mysql-test/suite/galera/r/galera_drop_multi.result
+++ b/mysql-test/suite/galera/r/galera_drop_multi.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_enum.result b/mysql-test/suite/galera/r/galera_enum.result
index dcf31aa5948..92b72fc69c0 100644
--- a/mysql-test/suite/galera/r/galera_enum.result
+++ b/mysql-test/suite/galera/r/galera_enum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 ENUM('', 'one', 'two'), KEY (f1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES ('');
@@ -38,7 +40,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1;
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three';
COUNT(*) = 1
diff --git a/mysql-test/suite/galera/r/galera_events.result b/mysql-test/suite/galera/r/galera_events.result
index f01627aba70..791b0be729d 100644
--- a/mysql-test/suite/galera/r/galera_events.result
+++ b/mysql-test/suite/galera/r/galera_events.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE EVENT event1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO SELECT 1;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
index 73375ae55c5..291d641db88 100644
--- a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
+++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE grandparent (
id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_update.result b/mysql-test/suite/galera/r/galera_fk_cascade_update.result
index 5fe8b532473..5294826a8f9 100644
--- a/mysql-test/suite/galera/r/galera_fk_cascade_update.result
+++ b/mysql-test/suite/galera/r/galera_fk_cascade_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE grandparent (
id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_fk_conflict.result b/mysql-test/suite/galera/r/galera_fk_conflict.result
index a08aa30a82e..f9f151abce4 100644
--- a/mysql-test/suite/galera/r/galera_fk_conflict.result
+++ b/mysql-test/suite/galera/r/galera_fk_conflict.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
@@ -22,6 +24,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE child;
DROP TABLE parent;
diff --git a/mysql-test/suite/galera/r/galera_fk_mismatch.result b/mysql-test/suite/galera/r/galera_fk_mismatch.result
index bdc60c9e099..a030b1214c5 100644
--- a/mysql-test/suite/galera/r/galera_fk_mismatch.result
+++ b/mysql-test/suite/galera/r/galera_fk_mismatch.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id1 INT,
id2 INT,
diff --git a/mysql-test/suite/galera/r/galera_fk_multicolumn.result b/mysql-test/suite/galera/r/galera_fk_multicolumn.result
index f5b6aa23692..b626d963af8 100644
--- a/mysql-test/suite/galera/r/galera_fk_multicolumn.result
+++ b/mysql-test/suite/galera/r/galera_fk_multicolumn.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t0 (
f1 INT PRIMARY KEY,
f2 INT UNIQUE
diff --git a/mysql-test/suite/galera/r/galera_fk_multitable.result b/mysql-test/suite/galera/r/galera_fk_multitable.result
index 04ff7adc3e9..83e1491ab34 100644
--- a/mysql-test/suite/galera/r/galera_fk_multitable.result
+++ b/mysql-test/suite/galera/r/galera_fk_multitable.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t0 (
f0 INT PRIMARY KEY
);
diff --git a/mysql-test/suite/galera/r/galera_fk_no_pk.result b/mysql-test/suite/galera/r/galera_fk_no_pk.result
index e7b5f0b2b64..622e63dbb8f 100644
--- a/mysql-test/suite/galera/r/galera_fk_no_pk.result
+++ b/mysql-test/suite/galera/r/galera_fk_no_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT,
KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_fk_selfreferential.result b/mysql-test/suite/galera/r/galera_fk_selfreferential.result
index 3b4dbf2a8e9..9a64521e7b8 100644
--- a/mysql-test/suite/galera/r/galera_fk_selfreferential.result
+++ b/mysql-test/suite/galera/r/galera_fk_selfreferential.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 INT NOT NULL PRIMARY KEY,
f2 INT,
diff --git a/mysql-test/suite/galera/r/galera_fk_setnull.result b/mysql-test/suite/galera/r/galera_fk_setnull.result
index d4f20fe60a3..afb3fc3b9b8 100644
--- a/mysql-test/suite/galera/r/galera_fk_setnull.result
+++ b/mysql-test/suite/galera/r/galera_fk_setnull.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result
index a8e798a693d..123b8098727 100644
--- a/mysql-test/suite/galera/r/galera_flush_local.result
+++ b/mysql-test/suite/galera/r/galera_flush_local.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS t1, t2, x1, x2;
connection node_1;
CREATE TABLE t1 (f1 INTEGER);
diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format.result b/mysql-test/suite/galera/r/galera_forced_binlog_format.result
index b94e6530886..a94ac0c112d 100644
--- a/mysql-test/suite/galera/r/galera_forced_binlog_format.result
+++ b/mysql-test/suite/galera/r/galera_forced_binlog_format.result
@@ -1,5 +1,10 @@
+connection node_2;
connection node_1;
+connection node_1;
+SEt GLOBAL wsrep_on=OFF;
RESET MASTER;
+SEt GLOBAL wsrep_on=ON;
+FLUSH BINARY LOGS;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT
@@ -13,18 +18,7 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
Log_name Pos Event_type Server_id End_log_pos Info
mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> []
mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
-mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
-mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
-mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
-mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
-mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3
-mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (2)
-mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
-mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
-mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Rotate 1 <End_log_pos> mysqld-bin.000002;pos=4
DROP TABLE t1;
#
# MDEV-9401: wsrep_forced_binlog_format with binlog causes crash
@@ -43,6 +37,4 @@ GRANT ALL PRIVILEGES ON `testdb_9401`.`t1` TO 'dummy'@'localhost'
REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
DROP USER dummy@localhost;
DROP DATABASE testdb_9401;
-disconnect node_2;
-disconnect node_1;
# End of tests
diff --git a/mysql-test/suite/galera/r/galera_ftwrl.result b/mysql-test/suite/galera/r/galera_ftwrl.result
index 0565781c051..eae8028a7f4 100644
--- a/mysql-test/suite/galera/r/galera_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S";
diff --git a/mysql-test/suite/galera/r/galera_ftwrl_drain.result b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
index 751811b88fd..1e1dc65da3e 100644
--- a/mysql-test/suite/galera/r/galera_ftwrl_drain.result
+++ b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result
index 18e3bff40fc..a22296278fa 100644
--- a/mysql-test/suite/galera/r/galera_fulltext.result
+++ b/mysql-test/suite/galera/r/galera_fulltext.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
index 30ee5772411..45c426dfdf1 100644
--- a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
+++ b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
@@ -15,5 +15,5 @@ Using --wsrep-start-position when starting mysqld ...
include/diff_servers.inc [servers=1 2]
DROP TABLE t1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [IST first seqno 2 not found from cache, falling back to SST]
+include/assert_grep.inc [IST first seqno [24] not found from cache, falling back to SST]
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
diff --git a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
index 464a8b7ea97..83eaa0fb7aa 100644
--- a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
+++ b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_gcs_fragment.result b/mysql-test/suite/galera/r/galera_gcs_fragment.result
index 0c9c1819f60..d39458ecb22 100644
--- a/mysql-test/suite/galera/r/galera_gcs_fragment.result
+++ b/mysql-test/suite/galera/r/galera_gcs_fragment.result
@@ -11,7 +11,7 @@ SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
SET GLOBAL wsrep_provider_options = 'signal=gcs_core_after_frag_send';
-ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ERROR HY000: Got error 6 during COMMIT
INSERT INTO t1 VALUES (3, "cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
SELECT * FROM t1;
f1 f2
diff --git a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
index ce74f3db433..b97be5733ff 100644
--- a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
+++ b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_gra_log.result b/mysql-test/suite/galera/r/galera_gra_log.result
index 777eda42046..33853188965 100644
--- a/mysql-test/suite/galera/r/galera_gra_log.result
+++ b/mysql-test/suite/galera/r/galera_gra_log.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET SESSION wsrep_on=OFF;
CREATE TABLE t1 (f1 INTEGER);
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_gtid.result b/mysql-test/suite/galera/r/galera_gtid.result
index acc5eae9876..f27e2590898 100644
--- a/mysql-test/suite/galera/r/galera_gtid.result
+++ b/mysql-test/suite/galera/r/galera_gtid.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY);
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_gtid_slave.result b/mysql-test/suite/galera/r/galera_gtid_slave.result
index f8ca6322d22..4f207659316 100644
--- a/mysql-test/suite/galera/r/galera_gtid_slave.result
+++ b/mysql-test/suite/galera/r/galera_gtid_slave.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
@@ -25,13 +27,18 @@ SELECT @@global.gtid_binlog_state;
1-1-4,2-2-2,2-3-3
connection node_1;
DROP TABLE t1,t2;
+SET GLOBAL wsrep_on=OFF;
+reset master;
+SET GLOBAL wsrep_on=ON;
connection node_2;
connection node_3;
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
connection node_3;
+SET GLOBAL wsrep_on=OFF;
reset master;
-connection node_1;
-reset master;
+SET GLOBAL wsrep_on=ON;
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 cdf330643c2..e8b4a4665c5 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
@@ -1,38 +1,40 @@
-connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
+connection node_1;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
#Connection 2
connection node_2;
START SLAVE;
-#Connection 1
-connection node_1;
+#Connection 3
+connection node_3;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4
+2-1-4
include/save_master_gtid.inc
#Connection 2
connection node_2;
include/sync_with_master_gtid.inc
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4
+2-1-4
INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4,2-2-3
-#Connection 3
-connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+0-2-3,2-1-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-4,2-2-3,2-3-5
-#Connection 1
-connection node_1;
+1-3-2,2-1-4,2-2-7
+#Connection 3
+connection node_3;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -48,76 +50,78 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
+connection node_1;
connection node_2;
-connection node_3;
-Shutting down server ...
#Connection 2
connection node_2;
+Shutting down server ...
+#Connection 1
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
-#Connection 3
-connection node_3;
+#Connection 2
+connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES ('node3_committed_after');
-INSERT INTO t1 VALUES ('node3_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
-#Connection 2
-connection node_2;
+#Connection 1
+connection node_1;
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
+node2_committed_after
+node2_committed_after
node2_committed_before
node2_committed_before
-node3_committed_after
-node3_committed_after
-#Connection 3
-connection node_3;
+#Connection 2
+connection node_2;
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
+node2_committed_after
+node2_committed_after
node2_committed_before
node2_committed_before
-node3_committed_after
-node3_committed_after
+#Connection 1
+connection node_1;
+SELECT @@global.gtid_binlog_state;
+@@global.gtid_binlog_state
+1-3-3,2-1-6,2-2-9
#Connection 2
connection node_2;
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-6,2-2-7,2-3-8
+0-3-7,0-2-8,2-1-6
#Connection 3
connection node_3;
-SELECT @@global.gtid_binlog_state;
-@@global.gtid_binlog_state
-1-1-6,2-2-7,2-3-8
-#Connection 1
-connection node_1;
SET AUTOCOMMIT=ON;
#Connection 2
connection node_2;
SET AUTOCOMMIT=ON;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
SET AUTOCOMMIT=ON;
#Connection 2
connection node_2;
STOP slave;
INSERT INTO t1 VALUES ('node2_slave_stoped');
-#Connection 1
-connection node_1;
-INSERT INTO t1 VALUES ('node1_normal_entry');
+#Connection 3
+connection node_3;
+INSERT INTO t1 VALUES ('node3_normal_entry');
include/save_master_gtid.inc
#Connection 2
connection node_2;
@@ -130,30 +134,34 @@ count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-7,2-3-8,2-2-11
-#Connection 3
-connection node_3;
+0-3-7,0-2-11,2-1-7
+#Connection 1
+connection node_1;
SELECT count(*) from t1;
count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-7,2-3-8,2-2-11
-#Connection 1
-connection node_1;
+1-3-3,2-1-7,2-2-12
+#Connection 3
+connection node_3;
DROP TABLE t2,t1;
#Connection 2
connection node_2;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
#Connection 2
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
+set global wsrep_on=OFF;
reset master;
-#Connection 3
-connection node_3;
-reset master;
+set global wsrep_on=ON;
#Connection 1
connection node_1;
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
+#Connection 3
+connection node_3;
reset master;
diff --git a/mysql-test/suite/galera/r/galera_insert_ignore.result b/mysql-test/suite/galera/r/galera_insert_ignore.result
index 7057affaa0e..417524240e7 100644
--- a/mysql-test/suite/galera/r/galera_insert_ignore.result
+++ b/mysql-test/suite/galera/r/galera_insert_ignore.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_sync_wait = 15;
connection node_2;
SET GLOBAL wsrep_sync_wait = 15;
diff --git a/mysql-test/suite/galera/r/galera_insert_multi.result b/mysql-test/suite/galera/r/galera_insert_multi.result
index 913dd42403a..d7a4f01873e 100644
--- a/mysql-test/suite/galera/r/galera_insert_multi.result
+++ b/mysql-test/suite/galera/r/galera_insert_multi.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
@@ -51,7 +53,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
INSERT INTO t1 VALUES (1), (2);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
diff --git a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
index e3bf407ddaa..146cae1e896 100644
--- a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
+++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
@@ -1,4 +1,7 @@
+connection node_2;
+connection node_1;
Performing State Transfer on a server that has been killed and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -17,6 +21,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -31,6 +36,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -38,6 +44,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
@@ -49,6 +56,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -63,6 +71,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -77,6 +86,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -86,3 +96,15 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
+connection node_2;
+connection node_1;
+connection node_2;
+connection node_1;
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_2;
+connection node_2;
+connection node_1;
+connection node_1a_galera_st_kill_slave_ddl;
+connection node_1;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result
index ed36a217624..4795fc1224b 100644
--- a/mysql-test/suite/galera/r/galera_ist_progress.result
+++ b/mysql-test/suite/galera/r/galera_ist_progress.result
@@ -1,4 +1,9 @@
connection node_2;
+<<<<<<< HEAD
+connection node_1;
+connection node_2;
+=======
+>>>>>>> 10.3
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
connection node_1;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_ist_recv_bind.result b/mysql-test/suite/galera/r/galera_ist_recv_bind.result
index ffc751d8672..be72aa60ab0 100644
--- a/mysql-test/suite/galera/r/galera_ist_recv_bind.result
+++ b/mysql-test/suite/galera/r/galera_ist_recv_bind.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SELECT @@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%';
@@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%'
diff --git a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
index c81cecfae1c..80d2c90642b 100644
--- a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
+++ b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
@@ -13,7 +15,6 @@ Loading wsrep_provider ...
SET SESSION wsrep_on=OFF;
SET SESSION wsrep_on=ON;
connection node_1;
-connection node_1;
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_ist_rsync.result b/mysql-test/suite/galera/r/galera_ist_rsync.result
index 8a7c02ab1b6..19453af2eec 100644
--- a/mysql-test/suite/galera/r/galera_ist_rsync.result
+++ b/mysql-test/suite/galera/r/galera_ist_rsync.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been temporarily disconnected
diff --git a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
index 099d944d491..f9fdc70e9d0 100644
--- a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
+++ b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
@@ -1,4 +1,7 @@
+connection node_2;
+connection node_1;
Performing State Transfer on a server that has been temporarily disconnected
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -18,6 +22,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Unloading wsrep provider ...
SET GLOBAL wsrep_provider = 'none';
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -32,6 +37,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -39,6 +45,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Loading wsrep provider ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -48,6 +55,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -62,6 +70,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_disconnect_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -76,6 +85,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -86,6 +96,7 @@ DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been shut down cleanly and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -95,6 +106,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -104,6 +116,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Shutting down server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -118,6 +131,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -125,6 +139,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -134,6 +149,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -148,6 +164,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_shutdown_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -162,6 +179,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -172,6 +190,7 @@ DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -181,6 +200,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -190,6 +210,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -204,6 +225,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -211,6 +233,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
@@ -222,6 +245,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -236,6 +260,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -250,6 +275,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -259,3 +285,15 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
+connection node_2;
+connection node_1;
+connection node_2;
+connection node_1;
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_2;
+connection node_2;
+connection node_1;
+connection node_1a_galera_st_kill_slave_ddl;
+connection node_1;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_kill_ddl.result b/mysql-test/suite/galera/r/galera_kill_ddl.result
index b11353fcbcc..b2e49e25dd6 100644
--- a/mysql-test/suite/galera/r/galera_kill_ddl.result
+++ b/mysql-test/suite/galera/r/galera_kill_ddl.result
@@ -1,5 +1,6 @@
call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*");
connection node_1;
+connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result
index f4de101fef8..c14c28e348c 100644
--- a/mysql-test/suite/galera/r/galera_kill_largechanges.result
+++ b/mysql-test/suite/galera/r/galera_kill_largechanges.result
@@ -1,5 +1,6 @@
call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*");
connection node_1;
+connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
diff --git a/mysql-test/suite/galera/r/galera_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result
index 2ee291004b0..f327a0713cd 100644
--- a/mysql-test/suite/galera/r/galera_kill_smallchanges.result
+++ b/mysql-test/suite/galera/r/galera_kill_smallchanges.result
@@ -1,5 +1,6 @@
call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*");
connection node_1;
+connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_lock_table.result b/mysql-test/suite/galera/r/galera_lock_table.result
index ce529deb22c..c3df1749ada 100644
--- a/mysql-test/suite/galera/r/galera_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_log_bin.result b/mysql-test/suite/galera/r/galera_log_bin.result
index a6f0ef12be1..12e5e59a426 100644
--- a/mysql-test/suite/galera/r/galera_log_bin.result
+++ b/mysql-test/suite/galera/r/galera_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (id INT) ENGINE=InnoDB;
@@ -66,4 +68,6 @@ mysqld-bin.000003 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER
DROP TABLE t1;
DROP TABLE t2;
connection node_1;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_log_output_csv.result b/mysql-test/suite/galera/r/galera_log_output_csv.result
index 5cb61b36332..efe8c73c986 100644
--- a/mysql-test/suite/galera/r/galera_log_output_csv.result
+++ b/mysql-test/suite/galera/r/galera_log_output_csv.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
SELECT COUNT(*) > 0 FROM mysql.general_log;
diff --git a/mysql-test/suite/galera/r/galera_many_columns.result b/mysql-test/suite/galera/r/galera_many_columns.result
index db8a8f5ec9d..64e97f11fa7 100644
--- a/mysql-test/suite/galera/r/galera_many_columns.result
+++ b/mysql-test/suite/galera/r/galera_many_columns.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
INSERT INTO t1 (f1) VALUES (DEFAULT);
connection node_2;
SELECT f1 = 'ABC', f1017 = 'ABC' FROM t1;
@@ -19,7 +21,7 @@ UPDATE t1 SET f2 = 'CDE' WHERE f1 = 'XYZ' AND f1017 = 'XYZ';
COMMIT;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
connection node_2;
ROLLBACK;
diff --git a/mysql-test/suite/galera/r/galera_many_indexes.result b/mysql-test/suite/galera/r/galera_many_indexes.result
index 5691eef4c00..9a1ede485eb 100644
--- a/mysql-test/suite/galera/r/galera_many_indexes.result
+++ b/mysql-test/suite/galera/r/galera_many_indexes.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(767) PRIMARY KEY) ENGINE=InnoDB;
CREATE UNIQUE INDEX i63 ON t1(f1);
CREATE UNIQUE INDEX i62 ON t1(f1);
@@ -129,5 +131,5 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_many_rows.result b/mysql-test/suite/galera/r/galera_many_rows.result
index b06925fea60..28613c20779 100644
--- a/mysql-test/suite/galera/r/galera_many_rows.result
+++ b/mysql-test/suite/galera/r/galera_many_rows.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION innodb_lock_wait_timeout=600;
SET SESSION lock_wait_timeout=600;
@@ -35,6 +37,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE ten;
diff --git a/mysql-test/suite/galera/r/galera_many_tables_nopk.result b/mysql-test/suite/galera/r/galera_many_tables_nopk.result
index 573ce758a13..2a226defcc7 100644
--- a/mysql-test/suite/galera/r/galera_many_tables_nopk.result
+++ b/mysql-test/suite/galera/r/galera_many_tables_nopk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -18,6 +20,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP SCHEMA test;
CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera/r/galera_many_tables_pk.result b/mysql-test/suite/galera/r/galera_many_tables_pk.result
index 67624d5edb0..2700df8ebe4 100644
--- a/mysql-test/suite/galera/r/galera_many_tables_pk.result
+++ b/mysql-test/suite/galera/r/galera_many_tables_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
SELECT COUNT(*) = 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%';
@@ -23,7 +25,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
include/diff_servers.inc [servers=1 2]
DROP SCHEMA test;
CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera/r/galera_mdev_10812.result b/mysql-test/suite/galera/r/galera_mdev_10812.result
index de0a08a3794..16eacc6beab 100644
--- a/mysql-test/suite/galera/r/galera_mdev_10812.result
+++ b/mysql-test/suite/galera/r/galera_mdev_10812.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10812: On COM_STMT_CLOSE/COM_QUIT, when wsrep_conflict_state
# is ABORTED, it causes wrong response to be sent to the client
diff --git a/mysql-test/suite/galera/r/galera_mdev_13787.result b/mysql-test/suite/galera/r/galera_mdev_13787.result
index b1caec0283c..4d0770918c0 100644
--- a/mysql-test/suite/galera/r/galera_mdev_13787.result
+++ b/mysql-test/suite/galera/r/galera_mdev_13787.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
create table t(a int);
insert into t select 1;
diff --git a/mysql-test/suite/galera/r/galera_mdl_race.result b/mysql-test/suite/galera/r/galera_mdl_race.result
index 048b2c46a67..e05c1493322 100644
--- a/mysql-test/suite/galera/r/galera_mdl_race.result
+++ b/mysql-test/suite/galera/r/galera_mdl_race.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
@@ -28,7 +30,7 @@ SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock";
UNLOCK TABLES;
connection node_1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a';
COUNT(*) = 1
1
diff --git a/mysql-test/suite/galera/r/galera_multi_database.result b/mysql-test/suite/galera/r/galera_multi_database.result
index f6242de663b..a9d58d5d0e2 100644
--- a/mysql-test/suite/galera/r/galera_multi_database.result
+++ b/mysql-test/suite/galera/r/galera_multi_database.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE DATABASE d1;
CREATE TABLE d1.t1(f1 INTEGER) ENGINE=InnoDB;
CREATE DATABASE d2;
diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result
index e9578a261e6..6213e8f6380 100644
--- a/mysql-test/suite/galera/r/galera_myisam_autocommit.result
+++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2), (3);
diff --git a/mysql-test/suite/galera/r/galera_myisam_transactions.result b/mysql-test/suite/galera/r/galera_myisam_transactions.result
index 25796c309d1..091c5ffb6f6 100644
--- a/mysql-test/suite/galera/r/galera_myisam_transactions.result
+++ b/mysql-test/suite/galera/r/galera_myisam_transactions.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
CREATE TABLE t3 (f1 INTEGER) ENGINE=MyISAM;
diff --git a/mysql-test/suite/galera/r/galera_nopk_bit.result b/mysql-test/suite/galera/r/galera_nopk_bit.result
index 21da039df09..97ded793c08 100644
--- a/mysql-test/suite/galera/r/galera_nopk_bit.result
+++ b/mysql-test/suite/galera/r/galera_nopk_bit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(0),(b'1');
connection node_2;
@@ -28,6 +30,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_blob.result b/mysql-test/suite/galera/r/galera_nopk_blob.result
index 53e04f72d1e..6a3cee516c9 100644
--- a/mysql-test/suite/galera/r/galera_nopk_blob.result
+++ b/mysql-test/suite/galera/r/galera_nopk_blob.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),('abc');
connection node_2;
@@ -28,6 +30,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
index a83cf7f2d91..6d29306996b 100644
--- a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
+++ b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(8000)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(CONCAT(REPEAT('x', 7999), 'a'));
connection node_2;
@@ -31,6 +33,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_unicode.result b/mysql-test/suite/galera/r/galera_nopk_unicode.result
index b2a8bb63df9..587ba9285da 100644
--- a/mysql-test/suite/galera/r/galera_nopk_unicode.result
+++ b/mysql-test/suite/galera/r/galera_nopk_unicode.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255),
KEY (f1)
@@ -19,7 +21,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT f1 = 'текст2' FROM t1;
f1 = 'текст2'
1
diff --git a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
index ab56a8a2aa6..48625b3ba4a 100644
--- a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
@@ -8,10 +10,10 @@ INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
connection node_2a;
SET SESSION wsrep_sync_wait=0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%';
COUNT(*) = 1
1
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%';
COUNT(*) = 1
1
SELECT COUNT(*) = 0 FROM t1;
@@ -30,7 +32,7 @@ COUNT(*) = 1
SELECT COUNT(*) = 1 FROM t2;
COUNT(*) = 1
1
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%';
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%';
COUNT(*) = 2
1
SET GLOBAL wsrep_slave_threads = 1;;
diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
index 827b2aa9dac..f52839b5c8b 100644
--- a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
+++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -22,7 +24,7 @@ COUNT(DISTINCT f1)
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE
USER = 'system user' AND STATE NOT LIKE 'InnoDB%';
COUNT(*)
-3
+4
connection default;
DROP TABLE t1;
DROP TABLE ten;
diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
index c8c07221cb1..09a415d47eb 100644
--- a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
+++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -12,7 +14,7 @@ COUNT(*) = 20000
SELECT COUNT(DISTINCT f1) = 20000 FROM t1;
COUNT(DISTINCT f1) = 20000
1
-SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%';
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%';
COUNT(*) = 4
1
connection default;
diff --git a/mysql-test/suite/galera/r/galera_parallel_simple.result b/mysql-test/suite/galera/r/galera_parallel_simple.result
index 3f657a0479e..d95abefdc24 100644
--- a/mysql-test/suite/galera/r/galera_parallel_simple.result
+++ b/mysql-test/suite/galera/r/galera_parallel_simple.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT) ENGINE=InnoDB;
CREATE TABLE t2 (id INT) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
index 807ab62c548..0b538778204 100644
--- a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
+++ b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIGINT SIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(-9223372036854775808, 'min'),
@@ -27,6 +29,6 @@ COMMIT;
SET AUTOCOMMIT=ON;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SET AUTOCOMMIT=ON;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
index c94b7e2314a..9442f79cd14 100644
--- a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
+++ b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIGINT UNSIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(18446744073709551615, 'max')
@@ -24,6 +26,6 @@ COMMIT;
SET AUTOCOMMIT=ON;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SET AUTOCOMMIT=ON;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_prepared_statement.result b/mysql-test/suite/galera/r/galera_prepared_statement.result
index d32d412ff46..943f7d0b263 100644
--- a/mysql-test/suite/galera/r/galera_prepared_statement.result
+++ b/mysql-test/suite/galera/r/galera_prepared_statement.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 CHAR(5)) ENGINE=InnoDB;
CREATE TABLE t2 (f1 CHAR(5)) ENGINE=InnoDB;
CREATE TABLE t3 (f1 CHAR(5)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_query_cache.result b/mysql-test/suite/galera/r/galera_query_cache.result
index e64c9438646..8f5bc4b6f37 100644
--- a/mysql-test/suite/galera/r/galera_query_cache.result
+++ b/mysql-test/suite/galera/r/galera_query_cache.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
index 8c9cece9097..4ee910f9169 100644
--- a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
+++ b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_read_only.result b/mysql-test/suite/galera/r/galera_read_only.result
index 4c2523f8691..fe8b45fa596 100644
--- a/mysql-test/suite/galera/r/galera_read_only.result
+++ b/mysql-test/suite/galera/r/galera_read_only.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL read_only=TRUE;
diff --git a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
index 2470f59c497..3d421216f93 100644
--- a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
+++ b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_provider_options = 'repl.key_format=FLAT16';
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
index da24a741351..0528df7b9f6 100644
--- a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
+++ b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
@@ -1,8 +1,10 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
INSERT INTO t1 VALUES (REPEAT('a', 512));
-ERROR HY000: Got error 90 "Message too long" during COMMIT
+ERROR HY000: Got error 5 "Input/output error" during COMMIT
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
diff --git a/mysql-test/suite/galera/r/galera_restart_nochanges.result b/mysql-test/suite/galera/r/galera_restart_nochanges.result
index b35ae50e2fb..09f8d9a586b 100644
--- a/mysql-test/suite/galera/r/galera_restart_nochanges.result
+++ b/mysql-test/suite/galera/r/galera_restart_nochanges.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
index ba6f30fcf30..6e672c2d444 100644
--- a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
+++ b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CALL mtr.add_suppression("Aborting");
CALL mtr.add_suppression("unknown option '--galera-unknown-option'");
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_rsu_add_pk.result b/mysql-test/suite/galera/r/galera_rsu_add_pk.result
index 4c79da154e2..9b068ba30d1 100644
--- a/mysql-test/suite/galera/r/galera_rsu_add_pk.result
+++ b/mysql-test/suite/galera/r/galera_rsu_add_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
index f64649ef4e2..7d731955691 100644
--- a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
+++ b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_rsu_error.result b/mysql-test/suite/galera/r/galera_rsu_error.result
index 5c16e34b492..f78e8fa544c 100644
--- a/mysql-test/suite/galera/r/galera_rsu_error.result
+++ b/mysql-test/suite/galera/r/galera_rsu_error.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
INSERT INTO t1 VALUES (1), (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_rsu_simple.result b/mysql-test/suite/galera/r/galera_rsu_simple.result
index d0ddcfb4d64..d75ef094065 100644
--- a/mysql-test/suite/galera/r/galera_rsu_simple.result
+++ b/mysql-test/suite/galera/r/galera_rsu_simple.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_2;
SET SESSION wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
index a103e810588..310611a0e49 100644
--- a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
+++ b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
SET GLOBAL wsrep_desync=1;
diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result
index 0bdaeef5b8a..c5fdecece0e 100644
--- a/mysql-test/suite/galera/r/galera_sbr.result
+++ b/mysql-test/suite/galera/r/galera_sbr.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
diff --git a/mysql-test/suite/galera/r/galera_sbr_binlog.result b/mysql-test/suite/galera/r/galera_sbr_binlog.result
index 0bdaeef5b8a..c5fdecece0e 100644
--- a/mysql-test/suite/galera/r/galera_sbr_binlog.result
+++ b/mysql-test/suite/galera/r/galera_sbr_binlog.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
diff --git a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
index edf20da92c6..fbac9ff4eb7 100644
--- a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
+++ b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE information_schema;
SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads";
VARIABLE_NAME VARIABLE_VALUE
diff --git a/mysql-test/suite/galera/r/galera_serializable.result b/mysql-test/suite/galera/r/galera_serializable.result
index be3f93a081f..e3785663271 100644
--- a/mysql-test/suite/galera/r/galera_serializable.result
+++ b/mysql-test/suite/galera/r/galera_serializable.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
@@ -9,7 +11,7 @@ connection node_2;
INSERT INTO t1 VALUES (1,1);
connection node_1;
SELECT * FROM t1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
DELETE FROM t1;
connection node_1;
@@ -22,7 +24,7 @@ connection node_2;
UPDATE t1 SET f2 = 2;
connection node_1;
UPDATE t1 SET f2 = 3;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
DELETE FROM t1;
connection node_1;
@@ -33,5 +35,5 @@ connection node_2;
INSERT INTO t1 VALUES (1,2);
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_server.result b/mysql-test/suite/galera/r/galera_server.result
index cc08b826e82..5130dee3459 100644
--- a/mysql-test/suite/galera/r/galera_server.result
+++ b/mysql-test/suite/galera/r/galera_server.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
# On node_1
CREATE SERVER s1
diff --git a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
index 14407c917a1..e9f81192386 100644
--- a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
+++ b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
SET SESSION sql_log_bin = 0;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_ssl.result b/mysql-test/suite/galera/r/galera_ssl.result
index 022d06319b8..ec3b717e3f3 100644
--- a/mysql-test/suite/galera/r/galera_ssl.result
+++ b/mysql-test/suite/galera/r/galera_ssl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
diff --git a/mysql-test/suite/galera/r/galera_ssl_compression.result b/mysql-test/suite/galera/r/galera_ssl_compression.result
index 333d646376c..0acc4b97eea 100644
--- a/mysql-test/suite/galera/r/galera_ssl_compression.result
+++ b/mysql-test/suite/galera/r/galera_ssl_compression.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump.result b/mysql-test/suite/galera/r/galera_sst_mysqldump.result
index 5c530c32ce6..ec0fedf6664 100644
--- a/mysql-test/suite/galera/r/galera_sst_mysqldump.result
+++ b/mysql-test/suite/galera/r/galera_sst_mysqldump.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
Setting SST method to mysqldump ...
call mtr.add_suppression("WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to '127.0.0.1'");
call mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos");
@@ -56,6 +58,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Loading wsrep provider ...
+disconnect node_2;
+connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_after');
@@ -390,6 +395,114 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
+SET wsrep_sync_wait = 0;
+Killing server ...
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
+Starting server ...
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
+SET AUTOCOMMIT=ON;
+connection node_1;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
connection node_1;
CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
DROP USER sst;
@@ -400,3 +513,4 @@ CALL mtr.add_suppression("Can't open and lock time zone table");
CALL mtr.add_suppression("Can't open and lock privilege tables");
CALL mtr.add_suppression("Info table is not ready to be used");
CALL mtr.add_suppression("Native table .* has the wrong structure");
+CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist");
diff --git a/mysql-test/suite/galera/r/galera_sst_rsync.result b/mysql-test/suite/galera/r/galera_sst_rsync.result
index ff85a7d6c0f..dbeab68fa17 100644
--- a/mysql-test/suite/galera/r/galera_sst_rsync.result
+++ b/mysql-test/suite/galera/r/galera_sst_rsync.result
@@ -1,5 +1,5 @@
-connection node_1;
connection node_2;
+connection node_1;
Performing State Transfer on a server that has been shut down cleanly and restarted
connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
index fdb5883b590..f371bf1a948 100644
--- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
+++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been shut down cleanly and restarted
@@ -286,5 +288,113 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
+SET wsrep_sync_wait = 0;
+Killing server ...
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
+Starting server ...
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
+SET AUTOCOMMIT=ON;
+connection node_1;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
disconnect node_2;
disconnect node_1;
diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
index 990e0a29506..409da775d9a 100644
--- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
+++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT 1;
1
1
diff --git a/mysql-test/suite/galera/r/galera_status_cluster.result b/mysql-test/suite/galera/r/galera_status_cluster.result
index ad92a51b775..9db0b88adc9 100644
--- a/mysql-test/suite/galera/r/galera_status_cluster.result
+++ b/mysql-test/suite/galera/r/galera_status_cluster.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 2
diff --git a/mysql-test/suite/galera/r/galera_status_local_index.result b/mysql-test/suite/galera/r/galera_status_local_index.result
index 8c36b60cc5f..c67498fff9f 100644
--- a/mysql-test/suite/galera/r/galera_status_local_index.result
+++ b/mysql-test/suite/galera/r/galera_status_local_index.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE wsrep_local_indexes (wsrep_local_index INTEGER);
INSERT INTO wsrep_local_indexes VALUES ((SELECT variable_value FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_local_index'));
diff --git a/mysql-test/suite/galera/r/galera_status_local_state.result b/mysql-test/suite/galera/r/galera_status_local_state.result
index 65713f1975c..3fe988ee6ac 100644
--- a/mysql-test/suite/galera/r/galera_status_local_state.result
+++ b/mysql-test/suite/galera/r/galera_status_local_state.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state';
VARIABLE_VALUE = 4
1
diff --git a/mysql-test/suite/galera/r/galera_suspend_slave.result b/mysql-test/suite/galera/r/galera_suspend_slave.result
index 07433399081..ce49b491778 100644
--- a/mysql-test/suite/galera/r/galera_suspend_slave.result
+++ b/mysql-test/suite/galera/r/galera_suspend_slave.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_sync_wait_show.result b/mysql-test/suite/galera/r/galera_sync_wait_show.result
index def771ff88d..793da3246ff 100644
--- a/mysql-test/suite/galera/r/galera_sync_wait_show.result
+++ b/mysql-test/suite/galera/r/galera_sync_wait_show.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET SESSION wsrep_sync_wait = 8;
connection node_1;
CREATE DATABASE db1;
diff --git a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
index 8a86dfd11e2..a23b0523140 100644
--- a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
+++ b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_error.result b/mysql-test/suite/galera/r/galera_toi_ddl_error.result
index dafad153867..386dc28bed3 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_error.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_error.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
@@ -19,3 +21,6 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE ten;
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
+connection node_2;
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
index a5db90aa965..a7966e36133 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE parent (
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
index 68743c024a0..4dd996093ec 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
@@ -1,32 +1,46 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
connection node_1;
-SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+SET DEBUG_SYNC= 'RESET';
+SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue';
ALTER TABLE t1 ADD COLUMN f2 INTEGER;;
connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables';
+SET wsrep_retry_autocommit=0;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
SELECT COUNT(*) = 0 FROM t2;
COUNT(*) = 0
1
-INSERT INTO t1 VALUES (1);
-Got one of the listed errors
+INSERT INTO t1 VALUES (1);;
+connection node_1c;
+SET SESSION wsrep_sync_wait = 0;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t2;
+COUNT(*) = 0
+1
INSERT INTO t2 VALUES (1);
COMMIT;;
connection node_1b;
SET SESSION wsrep_sync_wait = 0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
-COUNT(*) = 1
-1
SELECT COUNT(*) = 0 FROM t2;
COUNT(*) = 0
1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+COUNT(*) = 1
+1
SET DEBUG_SYNC= 'now SIGNAL continue';
connection node_1a;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_1c;
connection node_1;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
@@ -41,9 +55,5 @@ COUNT(*) = 0
SELECT COUNT(*) = 1 FROM t2;
COUNT(*) = 1
1
-connection node_1;
-SET DEBUG_SYNC= 'RESET';
-connection node_1b;
-SET DEBUG_SYNC= 'RESET';
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
index 3844fa97d82..5412cd3faee 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER);
connection node_2;
ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123);;
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
index 722bb9d9e12..db702b1a59e 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_toi_drop_database.result b/mysql-test/suite/galera/r/galera_toi_drop_database.result
index 6d88c8ea230..48056c70126 100644
--- a/mysql-test/suite/galera/r/galera_toi_drop_database.result
+++ b/mysql-test/suite/galera/r/galera_toi_drop_database.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE DATABASE database1;
USE database1;
@@ -14,9 +16,9 @@ INSERT INTO t2 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, te
connection node_2;
DROP DATABASE database1;;
connection node_1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1a;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
connection node_1;
SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'database1';
diff --git a/mysql-test/suite/galera/r/galera_toi_ftwrl.result b/mysql-test/suite/galera/r/galera_toi_ftwrl.result
index 0f13e95b689..fdc8b294c1c 100644
--- a/mysql-test/suite/galera/r/galera_toi_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_toi_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
FLUSH TABLES WITH READ LOCK;
diff --git a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
index f5cc14ed0f1..ee8c826fd18 100644
--- a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
+++ b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
@@ -8,7 +10,7 @@ connection node_2a;
ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=EXCLUSIVE;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1;
INSERT INTO t1 VALUES (2, 2);
SELECT COUNT(*) = 2 FROM t1;
diff --git a/mysql-test/suite/galera/r/galera_toi_lock_shared.result b/mysql-test/suite/galera/r/galera_toi_lock_shared.result
index 950c4d83c70..fe1c88075d5 100644
--- a/mysql-test/suite/galera/r/galera_toi_lock_shared.result
+++ b/mysql-test/suite/galera/r/galera_toi_lock_shared.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result
index 73285d723c1..081a82e6e7d 100644
--- a/mysql-test/suite/galera/r/galera_toi_truncate.result
+++ b/mysql-test/suite/galera/r/galera_toi_truncate.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -11,7 +13,7 @@ connection node_1;
TRUNCATE TABLE t1;;
connection node_1;
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
diff --git a/mysql-test/suite/galera/r/galera_transaction_read_only.result b/mysql-test/suite/galera/r/galera_transaction_read_only.result
index b388f195fb1..55923f58b65 100644
--- a/mysql-test/suite/galera/r/galera_transaction_read_only.result
+++ b/mysql-test/suite/galera/r/galera_transaction_read_only.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_transaction_replay.result b/mysql-test/suite/galera/r/galera_transaction_replay.result
index 7fd837433d2..272086c4eba 100644
--- a/mysql-test/suite/galera/r/galera_transaction_replay.result
+++ b/mysql-test/suite/galera/r/galera_transaction_replay.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
INSERT INTO t1 VALUES (2, 'a');
@@ -9,19 +11,73 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
f1 f2
2 a
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
connection node_1;
-COMMIT;;
+COMMIT;
connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+connection node_1;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+wsrep_local_replays
+1
connection node_2;
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+DROP TABLE t1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+connection node_2;
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
COUNT(*) = 1
@@ -46,22 +102,34 @@ SELECT * FROM t1;
i j
1 0
3 0
+SET AUTOCOMMIT=ON;
PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0";
connection node_1a;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
-connection node_1;
-EXECUTE stmt1;;
-connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
-SET SESSION wsrep_on = 0;
-SET SESSION wsrep_on = 1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
INSERT INTO t1 VALUES(2,2);
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+EXECUTE stmt1;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
+SET SESSION wsrep_sync_wait=7;
SELECT * FROM t1;
i j
1 1
@@ -74,5 +142,7 @@ i j
2 2
3 1
connection node_1;
+wsrep_local_replays
+1
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_truncate.result b/mysql-test/suite/galera/r/galera_truncate.result
index 4f3d72dbca7..c649d9bbaf9 100644
--- a/mysql-test/suite/galera/r/galera_truncate.result
+++ b/mysql-test/suite/galera/r/galera_truncate.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_truncate_temporary.result b/mysql-test/suite/galera/r/galera_truncate_temporary.result
index 183ebd9d24a..81373bda739 100644
--- a/mysql-test/suite/galera/r/galera_truncate_temporary.result
+++ b/mysql-test/suite/galera/r/galera_truncate_temporary.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TEMPORARY TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
INSERT INTO t1 VALUES (1);
TRUNCATE TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_unicode_identifiers.result b/mysql-test/suite/galera/r/galera_unicode_identifiers.result
index 77848bc751f..5db1be8c910 100644
--- a/mysql-test/suite/galera/r/galera_unicode_identifiers.result
+++ b/mysql-test/suite/galera/r/galera_unicode_identifiers.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_sync_wait = 15;
connection node_2;
SET GLOBAL wsrep_sync_wait = 15;
diff --git a/mysql-test/suite/galera/r/galera_unicode_pk.result b/mysql-test/suite/galera/r/galera_unicode_pk.result
index 0e8965a76e3..bb36fd4f369 100644
--- a/mysql-test/suite/galera/r/galera_unicode_pk.result
+++ b/mysql-test/suite/galera/r/galera_unicode_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -18,7 +20,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT f1 = 'текст2' FROM t1;
f1 = 'текст2'
1
@@ -35,6 +37,6 @@ connection node_2;
COMMIT;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
COMMIT;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_update_limit.result b/mysql-test/suite/galera/r/galera_update_limit.result
index 20a94e6f504..30c89a38dff 100644
--- a/mysql-test/suite/galera/r/galera_update_limit.result
+++ b/mysql-test/suite/galera/r/galera_update_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) Engine=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_v1_row_events.result b/mysql-test/suite/galera/r/galera_v1_row_events.result
index b0ea2293119..80fe2fb6d8d 100644
--- a/mysql-test/suite/galera/r/galera_v1_row_events.result
+++ b/mysql-test/suite/galera/r/galera_v1_row_events.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method.result b/mysql-test/suite/galera/r/galera_var_OSU_method.result
index 18e8bd2271a..2b0a713e86b 100644
--- a/mysql-test/suite/galera/r/galera_var_OSU_method.result
+++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET SESSION wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method2.result b/mysql-test/suite/galera/r/galera_var_OSU_method2.result
index 0e3751645a8..ca4f617d903 100644
--- a/mysql-test/suite/galera/r/galera_var_OSU_method2.result
+++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET SESSION wsrep_OSU_method = "TOI";
diff --git a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
index ba117b4c2d5..86c30fa4b23 100644
--- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
+++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_auto_increment_control = OFF;
SET GLOBAL auto_increment_increment = 1;
@@ -59,7 +61,7 @@ connection node_1a;
COMMIT;
connection node_2a;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1a;
SELECT * FROM t1;
f1 node
diff --git a/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result
index b71cf4c831d..48c649b66a8 100644
--- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result
+++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE=InnoDB;
SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size');
diff --git a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
index ca3844bf6bf..f5472aa931f 100644
--- a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
+++ b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_certify_nonPK = OFF;
connection node_2;
SET GLOBAL wsrep_certify_nonPK = OFF;
diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result
index 378d8ca84f5..8c1070e43ce 100644
--- a/mysql-test/suite/galera/r/galera_var_cluster_address.result
+++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result
@@ -1,7 +1,11 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_2;
SET GLOBAL wsrep_cluster_address = 'foo://';
+SHOW STATUS;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
SET SESSION wsrep_sync_wait=0;
SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
COUNT(*) > 0
@@ -11,7 +15,7 @@ Variable_name Value
wsrep_ready OFF
SHOW STATUS LIKE 'wsrep_cluster_status';
Variable_name Value
-wsrep_cluster_status non-Primary
+wsrep_cluster_status Disconnected
SHOW STATUS LIKE 'wsrep_local_state';
Variable_name Value
wsrep_local_state 0
@@ -39,7 +43,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo");
CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo");
CALL mtr.add_suppression("gcs connect failed: Socket type not supported");
CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7");
-CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)");
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)");
CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110");
CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)");
CALL mtr.add_suppression("gcs connect failed: Connection timed out");
diff --git a/mysql-test/suite/galera/r/galera_var_desync_on.result b/mysql-test/suite/galera/r/galera_var_desync_on.result
index 26798e51926..6a2e501eee2 100644
--- a/mysql-test/suite/galera/r/galera_var_desync_on.result
+++ b/mysql-test/suite/galera/r/galera_var_desync_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result
index 049aa5be3cc..eae4e267df9 100644
--- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result
+++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result
@@ -1,8 +1,6 @@
-connection node_1;
connection node_2;
connection node_1;
connection node_2;
-connection node_2;
CREATE TABLE t1(i INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
SELECT * FROM t1;
@@ -16,7 +14,7 @@ Variable_name Value
wsrep_ready OFF
SHOW STATUS LIKE 'wsrep_cluster_status';
Variable_name Value
-wsrep_cluster_status non-Primary
+wsrep_cluster_status Disconnected
SELECT * FROM t1;
ERROR 08S01: WSREP has not yet prepared node for application use
SELECT 1 FROM t1;
diff --git a/mysql-test/suite/galera/r/galera_var_fkchecks.result b/mysql-test/suite/galera/r/galera_var_fkchecks.result
index 8b1b913a584..42f8085ee1a 100644
--- a/mysql-test/suite/galera/r/galera_var_fkchecks.result
+++ b/mysql-test/suite/galera/r/galera_var_fkchecks.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
index 1a8733e2e1a..d2faf5ff463 100644
--- a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
+++ b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
list of GTID variables :
diff --git a/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result
new file mode 100644
index 00000000000..39bab15ef13
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result
@@ -0,0 +1,154 @@
+SET GLOBAL wsrep_ignore_apply_errors = 1;
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+DROP TABLE t1;
+SET GLOBAL wsrep_on = OFF;
+CREATE SCHEMA s1;
+SET GLOBAL wsrep_on = ON;
+DROP SCHEMA s1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+DROP INDEX idx1 ON t1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP INDEX idx1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP COLUMN f2;
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+DELETE FROM t1 WHERE f1 = 1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+DELETE FROM t1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+DELETE FROM t1 WHERE f1 = 4;
+DELETE FROM t1 WHERE f1 = 5;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t2 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1,t2;
+CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+INSERT INTO parent VALUES (1),(2),(3);
+CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB;
+INSERT INTO child VALUES (1,1),(2,2),(3,3);
+SET SESSION wsrep_on = OFF;
+DELETE FROM child WHERE parent_id = 2;
+SET SESSION wsrep_on = ON;
+DELETE FROM parent;
+SELECT COUNT(*) = 0 FROM parent;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM child;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM parent;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM child;
+COUNT(*) = 0
+1
+DROP TABLE child, parent;
+SET GLOBAL wsrep_ignore_apply_errors = 4;
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query.");
diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
index 4db4e539c50..f5ec473fea4 100644
--- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
+++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
index 3e451abbed1..7c5fd44356e 100644
--- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
+++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL wsrep_load_data_splitting = TRUE;
diff --git a/mysql-test/suite/galera/r/galera_var_log_bin.result b/mysql-test/suite/galera/r/galera_var_log_bin.result
index b0ea2293119..80fe2fb6d8d 100644
--- a/mysql-test/suite/galera/r/galera_var_log_bin.result
+++ b/mysql-test/suite/galera/r/galera_var_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
index 6bf67a3fb60..16e868f0485 100644
--- a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
+++ b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_size.result b/mysql-test/suite/galera/r/galera_var_max_ws_size.result
index 53bac04fa86..89c9698eed4 100644
--- a/mysql-test/suite/galera/r/galera_var_max_ws_size.result
+++ b/mysql-test/suite/galera/r/galera_var_max_ws_size.result
@@ -1,8 +1,10 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB;
SET GLOBAL wsrep_max_ws_size = 1024;
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
-ERROR HY000: Got error 90 "Message too long" during COMMIT
+ERROR HY000: Got error 5 "Input/output error" during COMMIT
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
diff --git a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
index 202633a020e..d7a38d24722 100644
--- a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
+++ b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB;
SET GLOBAL wsrep_mysql_replication_bundle = 2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_node_address.result b/mysql-test/suite/galera/r/galera_var_node_address.result
index 7696d1e3f4f..cf45861c8ad 100644
--- a/mysql-test/suite/galera/r/galera_var_node_address.result
+++ b/mysql-test/suite/galera/r/galera_var_node_address.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
call mtr.add_suppression("WSREP: Stray state UUID msg: .* current group state WAIT_STATE_UUID .*");
call mtr.add_suppression("WSREP: Protocol violation. JOIN message sender .* is not in state transfer (.*). Message ignored.");
call mtr.add_suppression("WSREP: Sending JOIN failed: -[0-9]+ (Transport endpoint is not connected). Will retry in new primary component.");
diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result
index 98380238fcb..e986092ea59 100644
--- a/mysql-test/suite/galera/r/galera_var_reject_queries.result
+++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER);
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
index 382466b1387..8968f89d11b 100644
--- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
+++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_replicate_myisam = FALSE;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=MyISAM;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
index 87f8862df7e..716af033e7a 100644
--- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
+++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_1;
SET GLOBAL wsrep_replicate_myisam = TRUE;
diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result
index c28cc091ae9..e774e620ccd 100644
--- a/mysql-test/suite/galera/r/galera_var_slave_threads.result
+++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB;
CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB;
@@ -13,8 +15,11 @@ SELECT @@wsrep_slave_threads = 1;
@@wsrep_slave_threads = 1
1
SET GLOBAL wsrep_slave_threads = 1;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
-COUNT(*)
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = 3
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
1
SET GLOBAL wsrep_slave_threads = 64;
connection node_1;
@@ -23,35 +28,197 @@ connection node_2;
SELECT COUNT(*) = 1 FROM t1;
COUNT(*) = 1
1
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+0
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
+1
SET GLOBAL wsrep_slave_threads = 1;
connection node_1;
connection node_2;
-SELECT COUNT(*) FROM t2;
-COUNT(*)
-64
+SELECT COUNT(*) = 64 FROM t2;
+COUNT(*) = 64
+1
+SET wsrep_sync_wait=0;
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
+1
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
COUNT(*)
1
+SET GLOBAL wsrep_slave_threads = 5;
SET GLOBAL wsrep_slave_threads = 1;
-DROP TABLE t1;
-DROP TABLE t2;
-#
-# lp:1372840 - Changing wsrep_slave_threads causes future connections to hang
-#
+connection node_2;
+Shutting down server ...
+connection node_1;
+SET wsrep_sync_wait=0;
+show status like 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 1
+SET GLOBAL wsrep_slave_threads = 6;
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL wsrep_cluster_address='';
+SET GLOBAL wsrep_cluster_address='gcomm://';
+SET GLOBAL wsrep_slave_threads = 10;
+connection node_2;
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+1
+connection node_1;
+SET GLOBAL wsrep_slave_threads = 1;
+connection node_2;
+SET GLOBAL wsrep_slave_threads = 1;
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
connection node_1;
-CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB;
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
connection node_2;
SET GLOBAL wsrep_slave_threads = 4;
+Timeout in wait_condition.inc for SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+Id User Host db Command Time State Info Progress
+2 system user NULL Sleep 42 Waiting on cond NULL 0.000
+1 system user NULL Sleep 42 wsrep aborter idle NULL 0.000
+3 system user NULL Sleep 30 Committed 195 NULL 0.000
+4 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
+5 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+7 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+6 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+8 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
+27 root localhost:53510 test Query 0 Init show full processlist 0.000
+28 system user NULL Sleep 30 NULL NULL 0.000
+30 system user NULL Sleep 30 NULL NULL 0.000
+29 system user NULL Sleep 30 NULL NULL 0.000
SET GLOBAL wsrep_slave_threads = 1;
connection node_1;
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
DROP TABLE t1;
-connection node_2;
-SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
-NAME
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
-COUNT(*) = 1
-1
+DROP TABLE t2;
# End of tests
diff --git a/mysql-test/suite/galera/r/galera_var_sst_auth.result b/mysql-test/suite/galera/r/galera_var_sst_auth.result
index 1db83197870..6a5683e2633 100644
--- a/mysql-test/suite/galera/r/galera_var_sst_auth.result
+++ b/mysql-test/suite/galera/r/galera_var_sst_auth.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10492: Assertion failure on shutdown when wsrep_sst_auth set in config
#
diff --git a/mysql-test/suite/galera/r/galera_var_sync_wait.result b/mysql-test/suite/galera/r/galera_var_sync_wait.result
index 3dfe902767c..80fbd3f3e05 100644
--- a/mysql-test/suite/galera/r/galera_var_sync_wait.result
+++ b/mysql-test/suite/galera/r/galera_var_sync_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10161: wsrep_sync_wait not enabled when set to 1 in config file
#
diff --git a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
index 36340f505ff..5323bc9bf60 100644
--- a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
+++ b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
SET SESSION wsrep_on = FALSE;
diff --git a/mysql-test/suite/galera/r/galera_wan_restart_ist.result b/mysql-test/suite/galera/r/galera_wan_restart_ist.result
index 8a2a7d0818e..7b87d534d92 100644
--- a/mysql-test/suite/galera/r/galera_wan_restart_ist.result
+++ b/mysql-test/suite/galera/r/galera_wan_restart_ist.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_wan_restart_sst.result b/mysql-test/suite/galera/r/galera_wan_restart_sst.result
index 71786cdd023..1296744a9c1 100644
--- a/mysql-test/suite/galera/r/galera_wan_restart_sst.result
+++ b/mysql-test/suite/galera/r/galera_wan_restart_sst.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4
1
diff --git a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
index 99c680c7b12..e01825fd944 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
index fa49d8c57c2..59883f1ca7e 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -20,6 +22,6 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
include/assert_grep.inc [cluster conflict due to high priority abort for threads]
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
index ca388496794..8edf1a02e9d 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
VARIABLE_VALUE = 'Primary'
1
diff --git a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
index f19dc40205b..0f7cd134156 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
call mtr.add_suppression("WSREP\: Unknown parameter 'gmcasts\.segment'");
call mtr.add_suppression("WSREP\: Set options returned 7");
SET GLOBAL wsrep_provider_options="gmcasts.segment=1";
diff --git a/mysql-test/suite/galera/r/galera_zero_length_column.result b/mysql-test/suite/galera/r/galera_zero_length_column.result
index 572d94d6756..fa29264704f 100644
--- a/mysql-test/suite/galera/r/galera_zero_length_column.result
+++ b/mysql-test/suite/galera/r/galera_zero_length_column.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY , f2 VARCHAR(0)) ENGINE=InnoDB;
CREATE TABLE t2 (f1 VARCHAR(0)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/grant.result b/mysql-test/suite/galera/r/grant.result
index a2ca72ee8ec..0b5a34dfce1 100644
--- a/mysql-test/suite/galera/r/grant.result
+++ b/mysql-test/suite/galera/r/grant.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#6266: Changing password fails on galera cluster
#
diff --git a/mysql-test/suite/galera/r/lp1276424.result b/mysql-test/suite/galera/r/lp1276424.result
index 363758e0d66..be27ee5374f 100644
--- a/mysql-test/suite/galera/r/lp1276424.result
+++ b/mysql-test/suite/galera/r/lp1276424.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT DEFAULT NULL, UNIQUE KEY i1 (f1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (NULL);
diff --git a/mysql-test/suite/galera/r/lp1347768.result b/mysql-test/suite/galera/r/lp1347768.result
index 7beb167d538..49c8894c081 100644
--- a/mysql-test/suite/galera/r/lp1347768.result
+++ b/mysql-test/suite/galera/r/lp1347768.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE `r8kmb_redirect_links` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`old_url` varchar(255) DEFAULT NULL,
diff --git a/mysql-test/suite/galera/r/lp1376747-2.result b/mysql-test/suite/galera/r/lp1376747-2.result
index b85e130f4f4..5e5b5be6c86 100644
--- a/mysql-test/suite/galera/r/lp1376747-2.result
+++ b/mysql-test/suite/galera/r/lp1376747-2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1376747-3.result b/mysql-test/suite/galera/r/lp1376747-3.result
index a2c55b5f1f6..62893b85bcf 100644
--- a/mysql-test/suite/galera/r/lp1376747-3.result
+++ b/mysql-test/suite/galera/r/lp1376747-3.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1376747-4.result b/mysql-test/suite/galera/r/lp1376747-4.result
index f1d32aa8f69..d6884cc3746 100644
--- a/mysql-test/suite/galera/r/lp1376747-4.result
+++ b/mysql-test/suite/galera/r/lp1376747-4.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/lp1376747.result b/mysql-test/suite/galera/r/lp1376747.result
index 16d4fa3fc52..1b9dd545409 100644
--- a/mysql-test/suite/galera/r/lp1376747.result
+++ b/mysql-test/suite/galera/r/lp1376747.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1438990.result b/mysql-test/suite/galera/r/lp1438990.result
index d48d2435faa..a324121d7da 100644
--- a/mysql-test/suite/galera/r/lp1438990.result
+++ b/mysql-test/suite/galera/r/lp1438990.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
diff --git a/mysql-test/suite/galera/r/lp959512.result b/mysql-test/suite/galera/r/lp959512.result
index 55adfa360b0..589030002db 100644
--- a/mysql-test/suite/galera/r/lp959512.result
+++ b/mysql-test/suite/galera/r/lp959512.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS variable;
Warnings:
Note 1051 Unknown table 'test.variable'
diff --git a/mysql-test/suite/galera/r/mdev_10518.result b/mysql-test/suite/galera/r/mdev_10518.result
index 4ccd5fd1d23..252aa244f77 100644
--- a/mysql-test/suite/galera/r/mdev_10518.result
+++ b/mysql-test/suite/galera/r/mdev_10518.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
list of GTID variables :
diff --git a/mysql-test/suite/galera/r/mdev_9290.result b/mysql-test/suite/galera/r/mdev_9290.result
index 276ab9e8ecb..d8fc35b02f4 100644
--- a/mysql-test/suite/galera/r/mdev_9290.result
+++ b/mysql-test/suite/galera/r/mdev_9290.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-9290 : InnoDB: Assertion failure in file trx0sys.cc line 353
# InnoDB: Failing assertion: xid_seqno > trx_sys_cur_xid_seqno
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#110.result b/mysql-test/suite/galera/r/mysql-wsrep#110.result
index 6d4031d71cd..344185f4f4e 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#110.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#110.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#198.result b/mysql-test/suite/galera/r/mysql-wsrep#198.result
index 33f36d407db..5b569ffae27 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#198.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#198.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result
index fe5725cab27..e55c38ea7cc 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#201.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#201.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (DEFAULT);
connection node_2;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#216.result b/mysql-test/suite/galera/r/mysql-wsrep#216.result
new file mode 100644
index 00000000000..b07589d0c04
--- /dev/null
+++ b/mysql-test/suite/galera/r/mysql-wsrep#216.result
@@ -0,0 +1,11 @@
+SET GLOBAL wsrep_debug = ON;
+CREATE USER u1 IDENTIFIED BY 'plaintext_password';
+CREATE USER u1 IDENTIFIED BY 'plaintext_password';
+ERROR HY000: Operation CREATE USER failed for 'u1'@'%'
+0
+0
+2
+1
+DROP USER u1;
+CALL mtr.add_suppression('Operation CREATE USER failed');
+
\ No newline at end of file
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result
index 19503dd5781..bc348613d25 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#237.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result
@@ -1,6 +1,8 @@
+connection node_2;
+connection node_1;
CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
-SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue';
+SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue';
INSERT INTO t values (1);;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1a;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#247.result b/mysql-test/suite/galera/r/mysql-wsrep#247.result
index e59c6d1a299..704f0ba923c 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#247.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#247.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_desync=1;
SET wsrep_OSU_method=RSU;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#31.result b/mysql-test/suite/galera/r/mysql-wsrep#31.result
index 1092f4ddb0c..d1d2861ec3a 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#31.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#31.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#90.result b/mysql-test/suite/galera/r/mysql-wsrep#90.result
index 0b8f55e6219..b0fa06ffaf8 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#90.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#90.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET GLOBAL wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result
index 3835de514aa..774d5ce8f83 100644
--- a/mysql-test/suite/galera/r/partition.result
+++ b/mysql-test/suite/galera/r/partition.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#4953 Galera: DELETE from a partitioned table is not replicated
#
@@ -123,7 +125,7 @@ SELECT COUNT(*) = 20002 FROM t1;
COUNT(*) = 20002
1
wsrep_last_committed_diff
-1
+AS_EXPECTED_3_or_5
DROP TABLE t1;
# Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries.
connection node_1;
@@ -148,7 +150,7 @@ SELECT COUNT(*) = 20002 FROM t1;
COUNT(*) = 20002
1
wsrep_last_committed_diff
-1
+AS_EXPECTED_1_or_2
DROP TABLE t1;
connection node_1;
SET GLOBAL wsrep_load_data_splitting = 1;;
diff --git a/mysql-test/suite/galera/r/pxc-421.result b/mysql-test/suite/galera/r/pxc-421.result
index a317b3e40e1..058af15c098 100644
--- a/mysql-test/suite/galera/r/pxc-421.result
+++ b/mysql-test/suite/galera/r/pxc-421.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/query_cache.result b/mysql-test/suite/galera/r/query_cache.result
index 8592a68141c..5dabd38a982 100644
--- a/mysql-test/suite/galera/r/query_cache.result
+++ b/mysql-test/suite/galera/r/query_cache.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# Execute FLUSH/RESET commands.
# On node-1
diff --git a/mysql-test/suite/galera/r/rename.result b/mysql-test/suite/galera/r/rename.result
index a7ec431657b..3ad715fa38c 100644
--- a/mysql-test/suite/galera/r/rename.result
+++ b/mysql-test/suite/galera/r/rename.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-8598 : Failed MySQL DDL commands and Galera replication
#
diff --git a/mysql-test/suite/galera/r/rpl_row_annotate.result b/mysql-test/suite/galera/r/rpl_row_annotate.result
index 23de06f015b..61fa2bc286c 100644
--- a/mysql-test/suite/galera/r/rpl_row_annotate.result
+++ b/mysql-test/suite/galera/r/rpl_row_annotate.result
@@ -1,9 +1,15 @@
+connection node_2;
+connection node_1;
# On node_2
connection node_2;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
# On node_1
connection node_1;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
CREATE TABLE t1(i INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
DELETE FROM t1 WHERE i = 1;
@@ -68,6 +74,4 @@ mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1)
mysqld-bin.000001 # Delete_rows_v1 2 # table_id: # flags: STMT_END_F
mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */
DROP TABLE t1;
-disconnect node_2;
-disconnect node_1;
# End of test
diff --git a/mysql-test/suite/galera/r/sql_log_bin.result b/mysql-test/suite/galera/r/sql_log_bin.result
index c175a0a0e7a..6efd70ca8b8 100644
--- a/mysql-test/suite/galera/r/sql_log_bin.result
+++ b/mysql-test/suite/galera/r/sql_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
diff --git a/mysql-test/suite/galera/r/unique_key.result b/mysql-test/suite/galera/r/unique_key.result
index 9f1fc858389..bb7e22014d9 100644
--- a/mysql-test/suite/galera/r/unique_key.result
+++ b/mysql-test/suite/galera/r/unique_key.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#5552 Deadlock when inserting NULL column value in column with
# UNIQUE index
diff --git a/mysql-test/suite/galera/r/view.result b/mysql-test/suite/galera/r/view.result
index f8da811f9cc..45d5b422f3f 100644
--- a/mysql-test/suite/galera/r/view.result
+++ b/mysql-test/suite/galera/r/view.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-7222: Cluster Node Crash at CREATE DEFINER statement
#
diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result
new file mode 100644
index 00000000000..0e8a4088104
--- /dev/null
+++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result
@@ -0,0 +1,25 @@
+connection node_2;
+connection node_1;
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SHOW WARNINGS;
+Level Code Message
+Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication.
+Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SHOW WARNINGS;
+Level Code Message
+Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication.
+Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result
new file mode 100644
index 00000000000..4139ecd6472
--- /dev/null
+++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result
@@ -0,0 +1,15 @@
+connection node_2;
+connection node_1;
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm
index 233aa020a94..62d89f70dac 100644
--- a/mysql-test/suite/galera/suite.pm
+++ b/mysql-test/suite/galera/suite.pm
@@ -83,6 +83,8 @@ push @::global_suppressions,
qr|WSREP: JOIN message from member .* in non-primary configuration. Ignored.|,
qr(WSREP: Failed to remove page file .*),
qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*),
+ qr|Query apply failed:*|,
+ qr(WSREP: Ignoring error*),
);
$ENV{PATH}="$epath:$ENV{PATH}";
diff --git a/mysql-test/suite/galera/t/GAL-419.test b/mysql-test/suite/galera/t/GAL-419.test
index e50b948bf35..07abcbcc47b 100644
--- a/mysql-test/suite/galera/t/GAL-419.test
+++ b/mysql-test/suite/galera/t/GAL-419.test
@@ -5,11 +5,11 @@
--source include/galera_cluster.inc
--source include/big_test.inc
---connection node_2
+--connection node_1
SET SESSION wsrep_sync_wait = 0;
--source include/kill_galera.inc
---connection node_1
+--connection node_2
SET SESSION wsrep_sync_wait = 0;
--source include/kill_galera.inc
diff --git a/mysql-test/suite/galera/t/GCF-1081.test b/mysql-test/suite/galera/t/GCF-1081.test
new file mode 100644
index 00000000000..8296c55f1b6
--- /dev/null
+++ b/mysql-test/suite/galera/t/GCF-1081.test
@@ -0,0 +1,72 @@
+#
+# GCF-1081 - Assertion `!thd->sp_runtime_ctx`
+#
+# Test replaying of stored procedures
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0), (3, 0);
+
+DELIMITER |;
+CREATE PROCEDURE proc_update ()
+BEGIN
+ UPDATE t1 SET f2 = 1 where f1 > 0;
+END|
+DELIMITER ;|
+
+# Block the SP
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+--send CALL proc_update ();
+
+# Wait until SP is blocked
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--source include/galera_wait_sync_point.inc
+
+# Issue a conflicting insert on node #2
+--connection node_1a
+SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock';
+
+--connection node_2
+--send INSERT INTO t1 VALUES (2, 2);
+
+# Wait until it BF aborts the SP
+--connection node_1a
+SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached';
+SET GLOBAL DEBUG = '';
+
+# Unblock the SP
+--connection node_1a
+--source include/galera_clear_sync_point.inc
+--source include/galera_signal_sync_point.inc
+
+--connection node_2
+--reap
+SELECT * FROM t1;
+
+# SP succeeds
+--connection node_1
+--reap
+SELECT * FROM t1;
+
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old AS wsrep_local_replays;
+--enable_query_log
+
+DROP PROCEDURE proc_update;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/GCF-939.test b/mysql-test/suite/galera/t/GCF-939.test
new file mode 100644
index 00000000000..637d656996e
--- /dev/null
+++ b/mysql-test/suite/galera/t/GCF-939.test
@@ -0,0 +1,31 @@
+#
+# GCF-939 Avoid creation of GRA log files when applier is successfull
+#
+
+--source include/galera_cluster.inc
+
+--exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/GRA_*.log
+
+--connection node_1
+--error ER_BAD_TABLE_ERROR
+DROP TABLE t1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Expect only one GRA_*.log file
+# TODO replace_regex is somehow broken, it will filter out
+# result totally if replacement string is already in result
+# fixed this temporarily by calling list_files twice
+# to get GRA_.log two times, this works for some reason
+#
+--replace_regex /GRA_.+\.log/GRA_.log/
+--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log
+--replace_regex /GRA_.+\.log/GRA_.log/
+--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log
+
+DROP TABLE t1;
+CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query");
+--connection node_2
+CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query");
+
diff --git a/mysql-test/suite/galera/t/MW-284.test b/mysql-test/suite/galera/t/MW-284.test
index 5e17baa1bdb..b2245eace84 100644
--- a/mysql-test/suite/galera/t/MW-284.test
+++ b/mysql-test/suite/galera/t/MW-284.test
@@ -63,7 +63,9 @@ CALL mtr.add_suppression('failed registering on master');
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
--connection node_1
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=OFF;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
--connection node_2
diff --git a/mysql-test/suite/galera/t/MW-292.test b/mysql-test/suite/galera/t/MW-292.test
index ecb1273759e..9580d53d85c 100644
--- a/mysql-test/suite/galera/t/MW-292.test
+++ b/mysql-test/suite/galera/t/MW-292.test
@@ -9,7 +9,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
@@ -25,37 +25,51 @@ START TRANSACTION;
UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
-# Block the commit
+# Block the applier on node #1 and issue a conflicting update on node #2
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
---connection node_1
---send COMMIT;
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
-# Issue a conflicting update on node #2
---connection node_2
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+# Block the commit, send the COMMIT and wait until it gets blocked
-# Wait for both transactions to be blocked
---connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%';
---source include/wait_condition.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT';
---source include/wait_condition.inc
+--connection node_1
+--send COMMIT
-# Unblock the commit
--connection node_1a
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
+
+# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
-# Commit succeeds via replay
+# Commit succeeds
--connection node_1
--reap
diff --git a/mysql-test/suite/galera/t/MW-328A.test b/mysql-test/suite/galera/t/MW-328A.test
index 09aad1bcf60..097d4ac4ff6 100644
--- a/mysql-test/suite/galera/t/MW-328A.test
+++ b/mysql-test/suite/galera/t/MW-328A.test
@@ -3,8 +3,13 @@
#
#
-# Attempt to insert into t2 and check if insert actually inserted rows if
-# a success was reported.
+# test phase 1 is not deterministic
+#
+# Here we attempt to insert into t2 and check if insert actually
+# inserted rows if a success was reported.
+#
+# However, deadlocks may or may not happen in this test execution
+# it all depends on timing.
#
--source include/big_test.inc
@@ -25,7 +30,7 @@ while ($count)
{
TRUNCATE TABLE t2;
- --error 0,1213
+ --error 0,ER_LOCK_DEADLOCK
INSERT IGNORE INTO t2 SELECT f2 FROM t1;
if ($mysql_errno != 1213) {
--inc $successes
@@ -44,14 +49,31 @@ while ($count)
--enable_query_log
+
+--source suite/galera/t/MW-328-footer.inc
+
#
-# Check that the test produced both deadlocks and successes
+# Test phase 2 is deterministic
+# Here we generate a sure conflict in node 1 and verify that
+# insert failed in both nodes
#
+--connection node_1
+CREATE TABLE t1 (i int primary key, j int) engine=innodb;
+INSERT INTO t1 values (1,0);
---disable_query_log
---eval SELECT $successes > 0 AS have_successes
---eval SELECT $deadlocks > 0 AS have_deadlocks
---enable_query_log
+BEGIN;
+UPDATE t1 SET j=1 WHERE i=1;
+--connection node_2
+UPDATE t1 SET j=2 WHERE i=1;
---source suite/galera/t/MW-328-footer.inc
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SELECT * FROM t1;
+--connection node_2
+SELECT * FROM t1;
+--connection node_1
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/MW-329.test b/mysql-test/suite/galera/t/MW-329.test
index 5baa4d14966..78755fc3b42 100644
--- a/mysql-test/suite/galera/t/MW-329.test
+++ b/mysql-test/suite/galera/t/MW-329.test
@@ -11,11 +11,6 @@ CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
# We start with a populated table
INSERT INTO t1 (f1) VALUES (1),(65535);
-# Clear the wsrep_local_replays counter
-
-FLUSH STATUS;
-SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-
#
# Run concurrent INSERTs
#
@@ -42,8 +37,9 @@ DELIMITER ;|
#
--connection node_2
-CALL mtr.add_suppression("WSREP: Failed to report last committed .*");
---let $count = 200
+--let $count = 10
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
while ($count)
{
--let $signature = `SELECT LEFT(MD5(RAND()), 10)`
@@ -57,14 +53,28 @@ while ($count)
--die ROW_COUNT() = 0
}
}
- --dec $count
+
+ #
+ # Ensure at least one replay happens
+ #
+
+ --let $wsrep_replays = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+ --disable_query_log
+ if (`SELECT $wsrep_replays - $wsrep_local_replays_old > 0`) {
+ --dec $count
+ }
+ --enable_query_log
}
#
# Confirm that some transaction replays occurred
#
-SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old > 0 AS wsrep_local_replays;
+--enable_query_log
+
#
# Terminate the stored procedure
diff --git a/mysql-test/suite/galera/t/MW-336.test b/mysql-test/suite/galera/t/MW-336.test
index 4bdbfb2ecff..67715c24992 100644
--- a/mysql-test/suite/galera/t/MW-336.test
+++ b/mysql-test/suite/galera/t/MW-336.test
@@ -11,9 +11,8 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
SET GLOBAL wsrep_slave_threads = 10;
SET GLOBAL wsrep_slave_threads = 1;
-
--let $wait_timeout=600
---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
@@ -31,11 +30,11 @@ while ($count)
--connection node_1
SET GLOBAL wsrep_slave_threads = 10;
---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 20;
---let $wait_condition = SELECT COUNT(*) = 21 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 22 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 1;
@@ -62,7 +61,7 @@ while ($count)
}
--connection node_1
---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera/t/MW-360-master.opt b/mysql-test/suite/galera/t/MW-360-master.opt
new file mode 100644
index 00000000000..e51c49c3808
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-360-master.opt
@@ -0,0 +1,2 @@
+--gtid-domain-id=1 --log-bin --log-slave-updates
+
diff --git a/mysql-test/suite/galera/t/MW-360.test b/mysql-test/suite/galera/t/MW-360.test
new file mode 100644
index 00000000000..b776631cfff
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-360.test
@@ -0,0 +1,100 @@
+#
+# MW-360 DROP TABLE containing temporary tables results in binlog divergence
+#
+
+--source include/galera_cluster.inc
+--source include/have_binlog_format_row.inc
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_1
+
+#
+# Straightforward temporary table
+#
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+
+--let $local_uuid = `SELECT LEFT(@@global.gtid_executed, 36)`
+
+#
+# A mix of normal and temporary tables
+#
+
+# Temp table first, normal table second
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+DROP TABLE t1, t2;
+
+# Normal table first, temporary table second
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+DROP TABLE t1, t2;
+
+# Temporary table first, normal table second, temp table third
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+
+DROP TABLE t1, t2, t3;
+
+# Normal table first, temporary table second, normal table third
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+
+DROP TABLE t1, t2, t3;
+
+#
+# A temporary table masking a normal one
+#
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+
+DROP TABLE t1;
+DROP TABLE t1;
+
+--connection node_2
+--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--connection node_1
+--disable_query_log
+# Node 1 has extra GTID set generated by the temporary table drop
+--eval SELECT GTID_SUBSET('$gtid_executed_node2', @@global.gtid_executed) AS gtid_executed_equal;
+--enable_query_log
diff --git a/mysql-test/suite/galera/t/MW-369.inc b/mysql-test/suite/galera/t/MW-369.inc
index 5fd9ef150ae..71df979d6ba 100644
--- a/mysql-test/suite/galera/t/MW-369.inc
+++ b/mysql-test/suite/galera/t/MW-369.inc
@@ -24,7 +24,6 @@
--connection node_1
SET AUTOCOMMIT=ON;
START TRANSACTION;
-
--eval $mw_369_parent_query
#
@@ -51,7 +50,7 @@ SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
---let $galera_sync_point = local_monitor_enter_sync
+--let $galera_sync_point = local_monitor_master_enter_sync
--source include/galera_set_sync_point.inc
--connection node_1
@@ -61,7 +60,7 @@ SET SESSION wsrep_sync_wait = 0;
# Wait until both sync points have been reached
#
--connection node_1a
---let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_enter_sync
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
--source include/galera_wait_sync_point.inc
#
@@ -70,6 +69,6 @@ SET SESSION wsrep_sync_wait = 0;
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
---let $galera_sync_point = local_monitor_enter_sync
+--let $galera_sync_point = local_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
diff --git a/mysql-test/suite/galera/t/MW-369.test b/mysql-test/suite/galera/t/MW-369.test
index 720d6daf518..99242224864 100644
--- a/mysql-test/suite/galera/t/MW-369.test
+++ b/mysql-test/suite/galera/t/MW-369.test
@@ -24,7 +24,6 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
diff --git a/mysql-test/suite/galera/t/MW-388.test b/mysql-test/suite/galera/t/MW-388.test
index de1ac52bf3e..9cf176434ba 100644
--- a/mysql-test/suite/galera/t/MW-388.test
+++ b/mysql-test/suite/galera/t/MW-388.test
@@ -2,7 +2,6 @@
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
-
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
@@ -41,11 +40,11 @@ SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
--connection node_1
SET SESSION wsrep_sync_wait = 0;
-SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue';
+SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue';
--send CALL insert_proc ();
--connection node_1a
-SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached";
+SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_certification_reached";
SET GLOBAL DEBUG_DBUG = "";
diff --git a/mysql-test/suite/galera/t/MW-402.test b/mysql-test/suite/galera/t/MW-402.test
index 36b691c6295..4b83e25dc50 100644
--- a/mysql-test/suite/galera/t/MW-402.test
+++ b/mysql-test/suite/galera/t/MW-402.test
@@ -1,6 +1,6 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
#
# we must open connection node_1a here, MW-369.inc will use it later
@@ -135,7 +135,6 @@ SELECT * FROM c;
DROP TABLE c;
DROP TABLE p;
-
#
# CASCADE DELETE tests with two parent tables
# Here we cause cascaded operation on child table through
@@ -151,10 +150,11 @@ DROP TABLE p;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
-CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
- CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+ f2 INTEGER,
+ CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
-
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
@@ -171,7 +171,51 @@ INSERT INTO c VALUES (1, 1, 1, 0);
--connection node_1
--reap
-# same as previous, but statements in different order
+--connection node_2
+SELECT * FROM p1;
+SELECT * FROM p2;
+SELECT * FROM c;
+
+DROP TABLE c;
+DROP TABLE p1;
+DROP TABLE p2;
+
+#
+# CASCADE DELETE tests with two parent tables
+# Here we cause cascaded operation on child table through
+# one parent table and issue other delete operation through the
+# other parent table. The cascade progresses to same child table row where
+# we should see the conflict to happen
+#
+# As a result, the update on p2 should fail
+#
+--connection node_1
+
+CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+ f2 INTEGER,
+ CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ ON DELETE CASCADE,
+ CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)
+ ON DELETE CASCADE);
+
+INSERT INTO p1 VALUES (1, 0);
+INSERT INTO p2 VALUES (1, 0);
+
+INSERT INTO c VALUES (1, 1, 1, 0);
+
+--let $mw_369_parent_query = DELETE FROM p2 WHERE f1=1
+--let $mw_369_child_query = DELETE FROM p1 WHERE f1=1
+
+--connection node_1a
+--source MW-369.inc
+
+# Commit succeeds
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
--connection node_2
SELECT * FROM p1;
SELECT * FROM p2;
diff --git a/mysql-test/suite/galera/t/MW-416.test b/mysql-test/suite/galera/t/MW-416.test
index df4fa35abc7..48eada95cb8 100644
--- a/mysql-test/suite/galera/t/MW-416.test
+++ b/mysql-test/suite/galera/t/MW-416.test
@@ -2,11 +2,10 @@
--source include/have_innodb.inc
--source include/wait_until_ready.inc
-
CREATE USER 'userMW416'@'localhost';
GRANT SELECT, INSERT, UPDATE ON test.* TO 'userMW416'@'localhost';
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
+--let $wsrep_replicated_before = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'`
--connect userMW416, localhost, userMW416,, test, $NODE_MYPORT_1
--connection userMW416
@@ -131,4 +130,7 @@ UNINSTALL PLUGIN plg;
--connection node_1
DROP USER 'userMW416'@'localhost';
SHOW DATABASES;
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
+--let $wsrep_replicated_after = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'`
+--disable_query_log
+--eval SELECT $wsrep_replicated_after - $wsrep_replicated_before AS wsrep_replicated_after_diff
+--enable_query_log
diff --git a/mysql-test/suite/galera/t/MW-86-master.opt b/mysql-test/suite/galera/t/MW-86-master.opt
new file mode 100644
index 00000000000..8a755e98b00
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-86-master.opt
@@ -0,0 +1 @@
+--log-bin --log-slave-updates
diff --git a/mysql-test/suite/galera/t/MW-86-wait1.test b/mysql-test/suite/galera/t/MW-86-wait1.test
index 6c0982ad8b3..aee5a0b2486 100644
--- a/mysql-test/suite/galera/t/MW-86-wait1.test
+++ b/mysql-test/suite/galera/t/MW-86-wait1.test
@@ -6,13 +6,15 @@
--source include/galera_cluster.inc
--source include/have_binlog_format_row.inc
--source include/have_debug_sync.inc
+SET @orig_debug=@@debug;
--connection node_2
# Make sure no signals have been leftover from previous tests to surprise us.
SELECT @@debug_sync;
+set debug_sync='RESET';
SET SESSION wsrep_sync_wait = 1;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
--connection node_1
CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB;
@@ -90,17 +92,16 @@ SHOW WARNINGS;
--enable_result_log
# Unblock the background INSERT and remove the sync point.
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+#SET GLOBAL debug_dbug = "-d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = @orig_debug;
+SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
# This will wait for the background INSERT to complete before we quit
# from the test.
DROP TABLE t_wait1;
-SET GLOBAL debug = NULL;
-SET debug_sync='RESET';
-
# Make sure no pending signals are leftover to surprise subsequent tests.
SELECT @@debug_sync;
diff --git a/mysql-test/suite/galera/t/MW-86-wait8.test b/mysql-test/suite/galera/t/MW-86-wait8.test
index 65e612c5c8e..c40cd8b77c7 100644
--- a/mysql-test/suite/galera/t/MW-86-wait8.test
+++ b/mysql-test/suite/galera/t/MW-86-wait8.test
@@ -4,13 +4,14 @@
--source include/galera_cluster.inc
--source include/have_binlog_format_row.inc
--source include/have_debug_sync.inc
+SET @orig_debug=@@debug;
--connection node_2
# Make sure no signals have been leftover from previous tests to surprise us.
SELECT @@debug_sync;
SET SESSION wsrep_sync_wait = 8;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
--connection node_1
CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB;
@@ -112,8 +113,11 @@ SHOW WARNINGS;
--enable_query_log
# Unblock the background INSERT and remove the sync point.
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
+#SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = @orig_debug;
+
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
@@ -121,8 +125,5 @@ SET SESSION wsrep_sync_wait = default;
# from the test.
DROP TABLE t_wait8;
-SET GLOBAL debug = NULL;
-SET debug_sync='RESET';
-
# Make sure no pending signals are leftover to surprise subsequent tests.
SELECT @@debug_sync;
diff --git a/mysql-test/suite/galera/t/MW-86.test b/mysql-test/suite/galera/t/MW-86.test
new file mode 100644
index 00000000000..2614eb89504
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-86.test
@@ -0,0 +1,193 @@
+--source include/galera_cluster.inc
+--source include/have_binlog_format_row.inc
+
+#
+# Test 1: SHOW commands no longer obey wsrep_sync_wait = 1
+#
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 1;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+--disable_result_log
+
+--connection node_1
+CREATE DATABASE db1;
+CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO bar VALUES (1);
+
+--connection node_2
+SHOW BINARY LOGS;
+
+SHOW BINLOG EVENTS;
+
+--error ER_NO_SUCH_TABLE
+SHOW COLUMNS FROM t1;
+
+--error 0
+SHOW CREATE DATABASE db1;
+
+--error ER_EVENT_DOES_NOT_EXIST
+SHOW CREATE EVENT e1;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW CREATE FUNCTION f1;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW CREATE PROCEDURE p1;
+
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t1;
+
+--error ER_TRG_DOES_NOT_EXIST
+SHOW CREATE TRIGGER tr1;
+
+--error ER_NO_SUCH_TABLE
+SHOW CREATE VIEW v1;
+
+SHOW DATABASES;
+
+SHOW ENGINE InnoDB STATUS;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW FUNCTION CODE f1;
+
+SHOW FUNCTION STATUS;
+
+SHOW GRANTS FOR 'root'@'localhost';
+
+--error ER_NO_SUCH_TABLE
+SHOW INDEX FROM t1;
+
+SHOW OPEN TABLES;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW PROCEDURE CODE p1;
+
+SHOW PROCEDURE STATUS;
+
+SHOW PRIVILEGES;
+
+SHOW STATUS LIKE 'wsrep_cluster_size';
+
+SHOW TABLE STATUS;
+
+SHOW TABLES;
+
+SHOW TRIGGERS;
+
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+
+--error 0
+SHOW WARNINGS;
+
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+
+SET SESSION wsrep_sync_wait = 8;
+DROP DATABASE db1;
+
+
+#
+# Test 2: SHOW commands now obey wsrep_sync_wait = 8
+#
+
+--connection node_2
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S";
+SET SESSION wsrep_sync_wait = 8;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+
+--connection node_1
+CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO q VALUES (1);
+
+--connection node_2
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW BINARY LOGS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW BINLOG EVENTS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW COLUMNS FROM t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE DATABASE db1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE EVENT e1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE FUNCTION f1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE PROCEDURE p1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE TABLE t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE TRIGGER tr1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE VIEW v1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW DATABASES;
+
+--error 0
+SHOW ENGINE InnoDB STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW FUNCTION CODE f1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW FUNCTION STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW GRANTS FOR 'root'@'localhost';
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW INDEX FROM t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW OPEN TABLES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW PROCEDURE CODE p1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW PROCEDURE STATUS;
+
+--error 0
+SHOW PRIVILEGES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW STATUS LIKE 'wsrep_cluster_size';
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TABLE STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TABLES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TRIGGERS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+
+--error 0
+SHOW WARNINGS;
+
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig"
+
+SET SESSION wsrep_sync_wait = 15;
+SET GLOBAL debug_dbug=NULL;
+SET debug_sync='RESET';
+DROP TABLE q, bar;
+SELECT @@debug_sync;
\ No newline at end of file
diff --git a/mysql-test/suite/galera/t/disabled.def b/mysql-test/suite/galera/t/disabled.def
new file mode 100644
index 00000000000..43b652200d1
--- /dev/null
+++ b/mysql-test/suite/galera/t/disabled.def
@@ -0,0 +1,13 @@
+galera_wsrep_provider_unset_set : lp1379204 'Unsupported protocol downgrade: incremental data collection disabled. Expect abort.'
+galera_kill_nochanges : mysql-wsrep#24 Galera server does not restart properly if killed
+galera_toi_ddl_fk_insert : qa#39 galera_toi_ddl_fk_insert fails sporadically
+galera_sst_xtrabackup-v2-options : SST Encryption does not work with xtrabackup 2.4.2
+#galera_autoinc_sst_xtrabackup : due to cert index preload, this test will never pass in current form (gcache.size=1)
+GCF-574 : CTAS is not supported together with SR
+galera_split_brain : is worked on with tracker GCF-998
+galera_sr_kill_all_pcrecovery : is worked on with tracker GCF-1068
+galera_var_notify_cmd : is worked on with tracker GCF-1071
+galera_gcache_recover_manytrx : is worked on with tracker GCF-1077
+GCF-1081 : tries to BF abort earlier trx, needs to be reimplemented
+galera_bf_abort_group_commit : requires galera_sr_bf_abort.inc, probably needs reimplementation
+galera_as_slave_gtid_replicate_do_db_cc : assertion
diff --git a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
index d8ecaacaa4c..6f688b39fd5 100644
--- a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
+++ b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
@@ -1 +1 @@
---lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=5
+--lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=60
diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test
index 49f3c993256..1c439ffff63 100644
--- a/mysql-test/suite/galera/t/galera_as_master.test
+++ b/mysql-test/suite/galera/t/galera_as_master.test
@@ -64,4 +64,6 @@ RESET SLAVE ALL;
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
--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_master_gtid.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
index 19517556331..75caba5420a 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf
@@ -1,8 +1,6 @@
!include ../galera_2nodes_as_master.cnf
[mysqld]
-gtid-mode=ON
log-bin=mysqld-bin
log-slave-updates
-enforce-gtid-consistency
binlog-format=ROW
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 9db104b7cab..9be065e448b 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid.test
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid.test
@@ -27,10 +27,6 @@ INSERT INTO t1 VALUES(1);
--eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
-
--connection node_2
INSERT INTO t1 VALUES(2);
@@ -39,10 +35,6 @@ INSERT INTO t1 VALUES(2);
--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
-
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
@@ -55,10 +47,6 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
-
--connection node_1
DROP TABLE t1;
@@ -66,5 +54,17 @@ DROP TABLE t1;
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
+--connection node_1
+--let $gtid_executed_node1 = `SELECT @@global.gtid_executed;`
+
+--connection node_2
+--disable_query_log
+--eval SELECT '$gtid_executed_node1' = @@global.gtid_executed 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
+--enable_query_log
+
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf
index 19517556331..75caba5420a 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf
@@ -1,8 +1,6 @@
!include ../galera_2nodes_as_master.cnf
[mysqld]
-gtid-mode=ON
log-bin=mysqld-bin
log-slave-updates
-enforce-gtid-consistency
binlog-format=ROW
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 23606d7ac4c..61c7eed6543 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
@@ -24,6 +24,8 @@ INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--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;
diff --git a/mysql-test/suite/galera/t/galera_as_slave.test b/mysql-test/suite/galera/t/galera_as_slave.test
index 849b75eadd1..144c0a4413d 100644
--- a/mysql-test/suite/galera/t/galera_as_slave.test
+++ b/mysql-test/suite/galera/t/galera_as_slave.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -29,14 +30,14 @@ INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES (2);
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_1
SELECT COUNT(*) = 2 FROM t1;
INSERT INTO t1 VALUES (3);
--connection node_2
SELECT COUNT(*) = 3 FROM t1;
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
@@ -46,5 +47,7 @@ DROP TABLE t1;
STOP SLAVE;
RESET SLAVE ALL;
---connection node_1
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
index 59483d0591c..503d409cc57 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
##
## Verify the correct operation of the auto-increment when
@@ -62,14 +63,13 @@ select * from t1;
show variables like 'binlog_format';
show variables like 'auto_increment_increment';
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
-
+--connection node_1
select * from t1;
show variables like 'binlog_format';
show variables like 'auto_increment_increment';
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
@@ -79,5 +79,7 @@ DROP TABLE t1;
STOP SLAVE;
RESET SLAVE ALL;
---connection node_1
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid.test b/mysql-test/suite/galera/t/galera_as_slave_gtid.test
index c2331a2ae05..3b0f191ad83 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_gtid.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.test
@@ -8,18 +8,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -34,17 +35,21 @@ SELECT LENGTH(@@global.gtid_binlog_state) > 1;
--source include/wait_condition.inc
--disable_query_log
+
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal;
+
--enable_query_log
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_1
SELECT COUNT(*) = 1 FROM t1;
--disable_query_log
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal;
--enable_query_log
---connection node_1
+--connection node_3
DROP TABLE t1;
#
@@ -55,7 +60,7 @@ DROP TABLE t1;
--sleep 1
---connection node_3
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf
new file mode 100644
index 00000000000..e0852c50c44
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf
@@ -0,0 +1,17 @@
+!include ../galera_2nodes_as_slave.cnf
+
+[mysqld]
+#gtid-mode=ON
+log-bin=master-bin
+log-bin-index=master-bin
+log-slave-updates
+#enforce-gtid-consistency
+binlog-format=ROW
+
+[mysqld.2]
+replicate-do-db=test1
+replicate-wild-do-table=test1.%
+
+[mysqld.3]
+replicate-do-db=test1
+replicate-wild-do-table=test1.%
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
new file mode 100644
index 00000000000..7071d4901c8
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
@@ -0,0 +1,150 @@
+#
+# Test Galera as a slave to a MySQL master using GTIDs
+#
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connection node_1
+RESET MASTER;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root';
+--enable_query_log
+START SLAVE;
+
+--connection node_1
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+
+#
+# First , some autocommit stuff
+#
+
+# Simple inserts
+
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+
+# Update that only covers test2.t1
+
+UPDATE test2.t1 SET test2.t1.f2 = 'cde';
+
+# Multi-table UPDATE
+
+UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz';
+
+# Multi-table DELETE
+
+DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3;
+
+#
+# Multi-statement transactions
+#
+
+# Transaction which is not replicated at all
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO test2.t1 (f1) VALUES (999);
+INSERT INTO test2.t1 (f1) VALUES (9999);
+COMMIT;
+
+# Transaction that is completely replicated
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (111);
+INSERT INTO test1.t1 (f1) VALUES (222);
+COMMIT;
+
+# Transaction that is partially replicated
+
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (333);
+INSERT INTO test2.t1 (f1) VALUES (99999);
+COMMIT;
+
+#
+# Make sure binary logs and gtid_executed strings are equal
+#
+
+--sleep 2
+--connection node_2
+--let $effective_uuid = `SELECT LEFT(@@global.gtid_current_pos, 36)`
+--let $gtid_executed_node2 = `SELECT @@global.gtid_current_pos;`
+
+--replace_result $effective_uuid <effective_uuid>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+
+--connection node_3
+
+--disable_query_log
+--eval SELECT '$gtid_executed_node2' = @@global.gtid_current_pos AS gtid_executed_equal;
+--enable_query_log
+
+--replace_result $effective_uuid <effective_uuid>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+
+#
+# Final consistency checks
+#
+
+--let $diff_servers = 2 3
+--source include/diff_servers.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2);
+SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333);
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm';
+
+--error 1049
+USE test2;
+
+#
+# Cleanup
+#
+
+--connection node_1
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+
+--sleep 1
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+STOP SLAVE;
+RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test
new file mode 100644
index 00000000000..1604016f3c3
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test
@@ -0,0 +1,176 @@
+#
+# Test the case where a Galera slave to async replication goes non-prim while
+# a stream of replication events including filtered events is arriving
+#
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+--source include/big_test.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1;
+--enable_query_log
+START SLAVE USER='root';
+
+--connection node_1
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 2 FROM test1.t1;
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--let $slave_sql_errno = 1047
+--source include/wait_for_slave_sql_error.inc
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+
+--connection node_2
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (5);
+INSERT INTO test2.t1 (f1) VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+SET SESSION wsrep_on=ON;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_ready';
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (6);
+INSERT INTO test2.t1 (f1) VALUES (6);
+
+--connection node_2
+START SLAVE;
+
+#
+# Consistency checks
+#
+
+--sleep 2
+--connection node_2
+--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1;
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1;
+--source include/wait_condition.inc
+
+--connection node_2
+--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--let $effective_uuid_1 = `SELECT SUBSTRING_INDEX(@@global.gtid_executed, ':', 1)`
+--let $effective_uuid_2 = `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(@@global.gtid_executed, '\n', -1), ':', 1)`
+
+--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+
+--error 1049
+USE test2;
+
+--connection node_3
+
+--disable_query_log
+--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal;
+--enable_query_log
+
+--error 1049
+USE test2;
+
+--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+
+#
+# Cleanup
+#
+
+--connection node_1
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+
+--sleep 1
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+STOP SLAVE;
+RESET SLAVE ALL;
+CALL mtr.add_suppression("GTID replication failed");
+CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed");
+CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query");
+CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query");
+CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047");
diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
index 46a93458271..53b5498a87d 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
@@ -7,22 +7,23 @@
--source include/have_innodb.inc
--source include/big_test.inc
+--source include/galera_cluster.inc
# Step #1. Establish replication
#
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
-#
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
---source include/galera_cluster.inc
+# As node 4 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_4 connection here
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root';
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_4, MASTER_USER='root';
--enable_query_log
START SLAVE;
SET SESSION wsrep_sync_wait = 0;
---connection node_1
+--connection node_4
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
--connection node_2
@@ -34,22 +35,21 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
---connection node_3
+--connection node_1
--source include/wait_until_connected_again.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
# Step #3. Force async replication to fail by creating a replication event while the slave is non-prim
---connection node_1
+--connection node_4
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
--connection node_2
--sleep 5
--let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1)
---connection node_3
+--connection node_1
--disable_query_log
--eval SELECT "$value" IN ("Error 'Unknown command' on query. Default database: 'test'. Query: 'BEGIN'", "Node has dropped from cluster") AS expected_error
--enable_query_log
@@ -58,7 +58,7 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
--connection node_2
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
---connection node_3
+--connection node_1
--source include/wait_until_connected_again.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
@@ -74,7 +74,7 @@ START SLAVE;
--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
--source include/wait_condition.inc
---connection node_1
+--connection node_4
DROP TABLE t1;
--sleep 2
@@ -92,5 +92,7 @@ CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be
CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
---connection node_1
+--connection node_4
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_preordered.test b/mysql-test/suite/galera/t/galera_as_slave_preordered.test
index 6f221f83b3a..5b3c78b2cb1 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_preordered.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_preordered.test
@@ -6,14 +6,15 @@
--source include/have_innodb.inc
--source include/have_log_bin.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--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_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE USER='root';
@@ -21,7 +22,7 @@ START SLAVE USER='root';
# Issue many large-ish transaction on the async master
#
---connection node_1
+--connection node_3
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -63,8 +64,7 @@ while ($count)
SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
---connection node_3
+--connection node_1
SELECT COUNT(*) = 2 * 100 * 10 * 10 FROM t1;
SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
@@ -72,7 +72,7 @@ SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
# Cleanup
#
---connection node_1
+--connection node_3
DROP TABLE t1;
DROP TABLE ten;
@@ -80,5 +80,8 @@ DROP TABLE ten;
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ten';
+--source include/wait_condition.inc
+
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
index 460e040c010..fa5f3f9c7c6 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
@@ -36,7 +37,7 @@ INSERT INTO t1 VALUES(5);
SELECT COUNT(*) = 4 FROM t1;
# Bundle is now complete, the last INSERT and the DROP are delivered
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
index b4bf5f02171..7e557717744 100644
--- a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
+++ b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
[mysqld.1]
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf
new file mode 100644
index 00000000000..612418c17c0
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf
@@ -0,0 +1,15 @@
+!include ../galera_2nodes.cnf
+
+# We set repl.commit_order=1 in order to disable provider commit
+# ordering.
+
+[mysqld.1]
+log-bin
+log-slave-updates
+wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1'
+
+[mysqld.2]
+
+log-bin
+log-slave-updates
+wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1'
\ No newline at end of file
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test
new file mode 100644
index 00000000000..255298565f0
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test
@@ -0,0 +1,76 @@
+#
+# This test uses galera_sr_bf_abort.inc to probe various BF abort points
+# for SR transactions with wsrep provider commit ordering disabled.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Control connection for manipulating sync points on node 1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+# SR bf abort on fragment
+--let $wsrep_trx_fragment_size = 1
+--echo galera_sr_bf_abort_at_commit = 0
+--let $galera_sr_bf_abort_at_commit = 0
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+# SR bf abort on commit fragment
+--let $wsrep_trx_fragment_size = 1
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+# Normal bf abort on commit
+--let $wsrep_trx_fragment_size = 0
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test
new file mode 100644
index 00000000000..8c105b3c37c
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test
@@ -0,0 +1,22 @@
+#
+# This test verifies that the server can be shut down even if
+# some of the wsrep transactions are in QUERY_COMMITTING state.
+# In this case the shutdown sequence may do a BF abort for the
+# connection.
+#
+
+--source include/have_innodb.inc
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+
+--connection node_2
+SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue';
+--send INSERT INTO t1 VALUES (1)
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/restart_mysqld.inc
+
+--connection node_1
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_commit_empty.test b/mysql-test/suite/galera/t/galera_commit_empty.test
new file mode 100644
index 00000000000..4e1a1e4eb2c
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_commit_empty.test
@@ -0,0 +1,35 @@
+# Test empty transactions.
+#
+# Check that the empty transaction gets terminated by starting and new
+# transaction after it. If the empty transaction is not terminated
+# appropriately, the following START TRANSACTION will fail.
+#
+# Also check that empty transactions don't generate any write sets.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+START TRANSACTION;
+COMMIT;
+
+START TRANSACTION;
+COMMIT;
+
+START TRANSACTION READ ONLY;
+COMMIT;
+
+START TRANSACTION;
+COMMIT;
+
+START TRANSACTION;
+START TRANSACTION;
+COMMIT;
+
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--disable_query_log
+--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before AS wsrep_last_committed_diff
+--enable_query_log
diff --git a/mysql-test/suite/galera/t/galera_create_table_as_select.test b/mysql-test/suite/galera/t/galera_create_table_as_select.test
new file mode 100644
index 00000000000..a6c1f657280
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_create_table_as_select.test
@@ -0,0 +1,145 @@
+#
+# CREATE TABLE AS SELECT tests
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+SET SESSION default_storage_engine=InnoDB;
+
+# Left table already exists
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 AS SELECT * FROM t2;
+DROP TABLE t1,t2;
+
+# Right table does not exist
+--error ER_NO_SUCH_TABLE
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+# No right table at all
+CREATE TABLE t1 AS SELECT 1 FROM DUAL;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+# Empty right table
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Right table is MyISAM
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Right side is a subquery
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT f1 = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Inside a stored procedure
+
+--connection node_1
+DELIMITER |;
+CREATE PROCEDURE sp1 ()
+BEGIN
+ CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+ INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+ CREATE TABLE t1 AS SELECT * FROM t2;
+END|
+DELIMITER ;|
+CALL sp1();
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1, t2;
+DROP PROCEDURE sp1;
+
+# Inside a prepared statement
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2';
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+
+#
+# Multi-master conflict
+#
+
+--connection node_1
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+--send CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t2;
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_1a
+UNLOCK TABLES;
+
+--connection node_1
+--error ER_TABLE_EXISTS_ERROR,ER_LOCK_DEADLOCK
+--reap
+
+DROP TABLE t1, t2;
+
+#
+# Temporary table
+#
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+--error ER_NO_SUCH_TABLE
+SELECT * FROM t1;
+
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query");
+
+--connection node_1
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test
index 0ad97916302..f5e1566d731 100644
--- a/mysql-test/suite/galera/t/galera_defaults.test
+++ b/mysql-test/suite/galera/t/galera_defaults.test
@@ -19,7 +19,7 @@ source ../wsrep/include/check_galera_version.inc;
# Global Variables
-SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -54,8 +54,10 @@ ORDER BY VARIABLE_NAME;
$wsrep_provider_options =~ s/gcs\.recv_q_hard_limit = .*?;/<GCS_RECV_Q_HARD_LIMIT>;/sgio;
$wsrep_provider_options =~ s/ist\.recv_addr = .*?;/<IST_RECV_ADDR>;/sgio;
$wsrep_provider_options =~ s/evs\.evict = .*?;/<EVS_EVICT>;/sgio;
+ $wsrep_provider_options =~ s/repl\.proto_max = .*?;/<REPL_PROTO_MAX>;/sgio;
$wsrep_provider_options =~ s/signal = .*?;\s*//sgio;
$wsrep_provider_options =~ s/dbug = .*?;\s*//sgio;
+ $wsrep_provider_options =~ s/gcs.recv_q_hard_limit = .*?;\s*/<RECV_Q_HARD_LIMIT>;/sgio;
$wsrep_provider_options =~ s/repl.proto_max = .*?;\s*/<REPL_PROTO_MAX>;/sgio;
print $wsrep_provider_options."\n";
EOF
diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_format.test b/mysql-test/suite/galera/t/galera_forced_binlog_format.test
index 364f41529a4..e9d7fa1c3a3 100644
--- a/mysql-test/suite/galera/t/galera_forced_binlog_format.test
+++ b/mysql-test/suite/galera/t/galera_forced_binlog_format.test
@@ -7,7 +7,10 @@
--source include/galera_cluster.inc
--connection node_1
+SEt GLOBAL wsrep_on=OFF;
RESET MASTER;
+SEt GLOBAL wsrep_on=ON;
+FLUSH BINARY LOGS;
SET SESSION binlog_format = 'STATEMENT';
@@ -40,6 +43,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
DROP USER dummy@localhost;
DROP DATABASE testdb_9401;
---source include/galera_end.inc
+#--source include/galera_end.inc
--echo # End of tests
diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
index 690e890cdea..857a1a34485 100644
--- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test
+++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
@@ -12,7 +12,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--connection node_1
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
index b7fd9cf3aed..aeca4c6a6ec 100644
--- a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
+++ b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
@@ -48,8 +48,8 @@ DROP TABLE t1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
# Confirm that IST did not take place
---let $assert_text = IST first seqno 2 not found from cache, falling back to SST
---let $assert_select = IST first seqno 2 not found from cache, falling back to SST
+--let $assert_text = IST first seqno [24] not found from cache, falling back to SST
+--let $assert_select = IST first seqno [24] not found from cache, falling back to SST
--let $assert_count = 1
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
--let $assert_only_after = starting as process
diff --git a/mysql-test/suite/galera/t/galera_gcs_fragment.test b/mysql-test/suite/galera/t/galera_gcs_fragment.test
index 80d3a5cb659..a36f5f05257 100644
--- a/mysql-test/suite/galera/t/galera_gcs_fragment.test
+++ b/mysql-test/suite/galera/t/galera_gcs_fragment.test
@@ -54,7 +54,7 @@ INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# Deadlock error should be returned since write set send was
# interrupted by gcs
--connection node_1
---error ER_LOCK_DEADLOCK
+--error ER_ERROR_DURING_COMMIT
--reap
# Do additional insert to verify that node_1 remain operational
diff --git a/mysql-test/suite/galera/t/galera_gtid-master.opt b/mysql-test/suite/galera/t/galera_gtid-master.opt
index 8a755e98b00..30317469ae7 100644
--- a/mysql-test/suite/galera/t/galera_gtid-master.opt
+++ b/mysql-test/suite/galera/t/galera_gtid-master.opt
@@ -1 +1 @@
---log-bin --log-slave-updates
+--log-bin --log-slave-updates --loose-new-servers-for-galera_gtid-test
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave.test b/mysql-test/suite/galera/t/galera_gtid_slave.test
index 19bfd8e17db..a356f1fceca 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave.test
+++ b/mysql-test/suite/galera/t/galera_gtid_slave.test
@@ -58,6 +58,16 @@ SELECT @@global.gtid_binlog_state;
--connection node_1
DROP TABLE t1,t2;
+SET GLOBAL wsrep_on=OFF;
+reset master;
+SET GLOBAL wsrep_on=ON;
+#
+# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
+# is difficult to understand given that it is an aggregate query. A "query execution was interrupted"
+# warning is also reported by MTR, which is also weird.
+#
+
+--sleep 1
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
@@ -70,10 +80,14 @@ DROP TABLE t1,t2;
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
--connection node_3
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
--connection node_1
reset master;
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
index 3fe94ad16b7..1b1c2411bc2 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
+++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
@@ -8,21 +8,21 @@
--source include/big_test.inc
--source include/have_innodb.inc
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--echo #Connection 2
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1,master_use_gtid=slave_pos;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3,master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--sleep 1
-
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
@@ -30,7 +30,6 @@ INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
--source include/save_master_gtid.inc
-
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
@@ -40,9 +39,8 @@ INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 3
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't2';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 6 FROM t2;
@@ -53,8 +51,8 @@ INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
#Perform SST
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -62,7 +60,6 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
--source include/save_master_gtid.inc
-
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
@@ -71,22 +68,21 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 4 FROM t1;
--source include/wait_condition.inc
---let $node_1= node_2
---let $node_2= node_3
+--let $node_1= node_1
+--let $node_2= node_2
--source include/auto_increment_offset_save.inc
---echo Shutting down server ...
---source include/shutdown_mysqld.inc
-
-
--echo #Connection 2
--connection node_2
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
SET AUTOCOMMIT=OFF;
@@ -94,51 +90,46 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 2
+--connection node_2
--echo Starting server ...
--source include/start_mysqld.inc
+
--source include/wait_until_ready.inc
--source include/auto_increment_offset_restore.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES ('node3_committed_after');
-INSERT INTO t1 VALUES ('node3_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
-
---echo #Connection 2
---connection node_2
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 8 FROM t1;
--source include/wait_condition.inc
Select * from t1 order by f1;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 2
+--connection node_2
Select * from t1 order by f1;
#SST Done
--sleep 1
+--echo #Connection 1
+--connection node_1
+SELECT @@global.gtid_binlog_state;
--echo #Connection 2
--connection node_2
SELECT @@global.gtid_binlog_state;
-
--echo #Connection 3
--connection node_3
-SELECT @@global.gtid_binlog_state;
-
---echo #Connection 1
---connection node_1
SET AUTOCOMMIT=ON;
#drop table t1;
#CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
-
--echo #Connection 2
--connection node_2
SET AUTOCOMMIT=ON;
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
SET AUTOCOMMIT=ON;
#
@@ -148,10 +139,9 @@ SET AUTOCOMMIT=ON;
STOP slave;
--sleep 1
INSERT INTO t1 VALUES ('node2_slave_stoped');
-
---echo #Connection 1
---connection node_1
-INSERT INTO t1 VALUES ('node1_normal_entry');
+--echo #Connection 3
+--connection node_3
+INSERT INTO t1 VALUES ('node3_normal_entry');
--source include/save_master_gtid.inc
#start slave
@@ -163,16 +153,14 @@ start slave;
INSERT INTO t1 VALUES ('node2_slave_started');
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 12 FROM t1;
--source include/wait_condition.inc
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
DROP TABLE t2,t1;
# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
@@ -181,27 +169,26 @@ DROP TABLE t2,t1;
#
--sleep 3
-
--echo #Connection 2
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
-
--echo #Connection 2
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
+set global wsrep_on=OFF;
reset master;
-
---echo #Connection 3
---connection node_3
-reset master;
-
+set global wsrep_on=ON;
--echo #Connection 1
--connection node_1
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
+--echo #Connection 3
+--connection node_3
reset master;
diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
index 41a1aab382b..1542376b2b8 100644
--- a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
+++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth=root:
innodb_flush_log_at_trx_commit=0
diff --git a/mysql-test/suite/galera/t/galera_ist_progress.test b/mysql-test/suite/galera/t/galera_ist_progress.test
index 3ba63415c28..dd93161eab8 100644
--- a/mysql-test/suite/galera/t/galera_ist_progress.test
+++ b/mysql-test/suite/galera/t/galera_ist_progress.test
@@ -58,8 +58,8 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
--let $assert_only_after = Need state transfer
---let $assert_text = Receiving IST: 11 writesets, seqnos
---let $assert_select = Receiving IST: 11 writesets, seqnos
+--let $assert_text = Receiving IST: 1[13] writesets
+--let $assert_select = Receiving IST: 1[13] writesets
--source include/assert_grep.inc
--let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete
diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
index 633318629a6..5e2343aa3e6 100644
--- a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
+++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
@@ -7,7 +7,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
# This could cause out of storage if run /dev/shm
--source include/big_test.inc
diff --git a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
index a762b939f69..75dff78149d 100644
--- a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth=root:
[mysqld.1]
diff --git a/mysql-test/suite/galera/t/galera_kill_applier.test b/mysql-test/suite/galera/t/galera_kill_applier.test
index d04b72bce0a..b66e0bcbbd0 100644
--- a/mysql-test/suite/galera/t/galera_kill_applier.test
+++ b/mysql-test/suite/galera/t/galera_kill_applier.test
@@ -6,7 +6,6 @@
--source include/have_innodb.inc
--connection node_1
---sleep 2
--let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE IS NULL LIMIT 1`
--disable_query_log
diff --git a/mysql-test/suite/galera/t/galera_log_bin.test b/mysql-test/suite/galera/t/galera_log_bin.test
index 2f0faa761c5..57df53e29b1 100644
--- a/mysql-test/suite/galera/t/galera_log_bin.test
+++ b/mysql-test/suite/galera/t/galera_log_bin.test
@@ -36,4 +36,6 @@ DROP TABLE t1;
DROP TABLE t2;
--connection node_1
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_migrate.cnf b/mysql-test/suite/galera/t/galera_migrate.cnf
index ed48f208e52..2e1e9f161a9 100644
--- a/mysql-test/suite/galera/t/galera_migrate.cnf
+++ b/mysql-test/suite/galera/t/galera_migrate.cnf
@@ -29,11 +29,13 @@ wsrep_sync_wait = 15
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+log-slave-updates
[mysqld.4]
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+log-slave-updates
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
index 08ed3fac67e..5a33c16c86e 100644
--- a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
+++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
@@ -32,8 +32,8 @@ INSERT INTO t2 VALUES (1);
--connection node_2a
--sleep 1
SET SESSION wsrep_sync_wait=0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%';
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%';
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 0 FROM t2;
@@ -44,7 +44,7 @@ UNLOCK TABLES;
--eval SET SESSION wsrep_sync_wait = $wsrep_sync_wait_orig;
SELECT COUNT(*) = 1 FROM t1;
SELECT COUNT(*) = 1 FROM t2;
-SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%';
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%';
--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test
index 8680d62a36d..d2156cb3577 100644
--- a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test
+++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test
@@ -42,7 +42,7 @@ while ($count)
SELECT COUNT(*) = 20000 FROM t1;
SELECT COUNT(DISTINCT f1) = 20000 FROM t1;
-SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%';
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%';
--disable_query_log
--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
diff --git a/mysql-test/suite/galera/t/galera_parallel_simple.test b/mysql-test/suite/galera/t/galera_parallel_simple.test
index 2cd840123cf..51bb1355ba4 100644
--- a/mysql-test/suite/galera/t/galera_parallel_simple.test
+++ b/mysql-test/suite/galera/t/galera_parallel_simple.test
@@ -47,7 +47,7 @@ SET SESSION wsrep_sync_wait = 0;
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock%';
--source include/wait_condition.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'applied write set%';
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committing%';
--source include/wait_condition.inc
UNLOCK TABLES;
diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test
new file mode 100644
index 00000000000..ae8647eae22
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_pc_recovery.test
@@ -0,0 +1,93 @@
+#
+# Test the pc.recovery=1 option. Killing all nodes simultaneously and
+# restarting them should succeed and the cluster should re-form.
+#
+
+--source include/have_innodb.inc
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Instruct MTR to not restart the nodes automatically when they are killed
+
+--let $NODE_1_PIDFILE = `SELECT @@pid_file`
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+--let $NODE_2_PIDFILE = `SELECT @@pid_file`
+
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--exec kill -9 `cat $NODE_1_PIDFILE` `cat $NODE_2_PIDFILE`
+
+# Perform --wsrep-recover and preserve the positions into variables by placing them in $MYSQL_TMP_DIR/galera_wsrep_start_position.inc and then --source'ing it
+
+--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.1.log > $MYSQL_TMP_DIR/galera_wsrep_recover.1.log 2>&1
+--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.2.log > $MYSQL_TMP_DIR/galera_wsrep_recover.2.log 2>&1
+
+--perl
+ use strict;
+ my $wsrep_start_position1 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.1.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`;
+ chomp($wsrep_start_position1);
+
+ my $wsrep_start_position2 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.2.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`;
+ chomp($wsrep_start_position2);
+
+ die if $wsrep_start_position1 eq '' || $wsrep_start_position2 eq '';
+
+ open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die;
+ print FILE "--let \$galera_wsrep_start_position1 = $wsrep_start_position1\n";
+ print FILE "--let \$galera_wsrep_start_position2 = $wsrep_start_position2\n";
+ close FILE;
+EOF
+
+--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc
+
+if ($galera_wsrep_start_position1 == '') {
+ --die "Could not obtain wsrep_start_position."
+}
+
+if ($galera_wsrep_start_position2 == '') {
+ --die "Could not obtain wsrep_start_position."
+}
+
+--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc
+
+# Instruct MTR to perform the actual restart using --wsrep-start-position . Proper --wsrep_cluster_address is used as my.cnf only contains 'gcomm://' for node #1
+
+--exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position1 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position2 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+
+--sleep 5
+--connection node_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Confirm that the cluster has re-formed and data is present
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("points to own listening address, blacklisting");
+CALL mtr.add_suppression("non weight changing install in S_PRIM");
+CALL mtr.add_suppression("No re-merged primary component found");
+
+--connection node_2
+CALL mtr.add_suppression("points to own listening address, blacklisting");
+CALL mtr.add_suppression("non weight changing install in S_PRIM");
+CALL mtr.add_suppression("No re-merged primary component found");
diff --git a/mysql-test/suite/galera/t/galera_split_brain.test b/mysql-test/suite/galera/t/galera_split_brain.test
index a85a2ad9b8d..91a2cc326a2 100644
--- a/mysql-test/suite/galera/t/galera_split_brain.test
+++ b/mysql-test/suite/galera/t/galera_split_brain.test
@@ -1,6 +1,8 @@
#
-# Confirm that with two nodes, killing one causes the other to stop accepting connections
-# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_* tests.
+# Confirm that with two nodes, killing one causes the other to stop accepting
+# connections.
+# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_*
+# tests.
#
--source include/galera_cluster.inc
diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.test b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
index a424942da30..6dc3bf7a5a3 100644
--- a/mysql-test/suite/galera/t/galera_ssl_upgrade.test
+++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
@@ -46,4 +46,8 @@ SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_N
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+# 5. Make sure node_2 is ready as well
+--connection node_2
+--source include/galera_wait_ready.inc
+
# Upgrade complete. Both nodes now use the new key and certificate
diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
index 574ae28b54a..cf2ba68d0cf 100644
--- a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
@@ -5,7 +5,9 @@
[mysqld.1]
wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true'
-
+wsrep_causal_reads=0
+wsrep_sync_wait=0
[mysqld.2]
wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
-
+wsrep_causal_reads=0
+wsrep_sync_wait=0
diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.test b/mysql-test/suite/galera/t/galera_sst_mysqldump.test
index 835fac94a68..b72fa687411 100644
--- a/mysql-test/suite/galera/t/galera_sst_mysqldump.test
+++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.test
@@ -1,6 +1,6 @@
--source include/big_test.inc
--source include/galera_cluster.inc
-
+--source include/have_innodb.inc
--source suite/galera/include/galera_sst_set_mysqldump.inc
--let $node_1=node_1
@@ -14,7 +14,6 @@
--source suite/galera/include/galera_st_shutdown_slave.inc
--source suite/galera/include/galera_st_clean_slave.inc
-
--source suite/galera/include/galera_st_kill_slave.inc
--source suite/galera/include/galera_st_kill_slave_ddl.inc
diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf
index 44e5573b3e6..b7bca487fc5 100644
--- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf
@@ -5,9 +5,13 @@
[mysqld.1]
wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true'
+wsrep_causal_reads=0
+wsrep_sync_wait=0
[mysqld.2]
wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
+wsrep_causal_reads=0
+wsrep_sync_wait=0
[mysqld]
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
index 3abf2549aae..db17e3f81b7 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
index 0025b259ec5..2aef1376ab6 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
index 63d05104a37..5a989ea8177 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_error.test b/mysql-test/suite/galera/t/galera_toi_ddl_error.test
index c586d97bdb5..6ee2a6e9b16 100644
--- a/mysql-test/suite/galera/t/galera_toi_ddl_error.test
+++ b/mysql-test/suite/galera/t/galera_toi_ddl_error.test
@@ -27,3 +27,8 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP TABLE ten;
+
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
+
+--connection node_2
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
\ No newline at end of file
diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
index 12c83a1f87a..91bcadc0e5d 100644
--- a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
+++ b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
@@ -11,20 +11,31 @@
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
---connection node_1
-SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
---send ALTER TABLE t1 ADD COLUMN f2 INTEGER;
-
--let $galera_connection_name = node_1a
--let $galera_server_number = 1
--source include/galera_connect.inc
+SET SESSION wsrep_sync_wait = 0;
--let $galera_connection_name = node_1b
--let $galera_server_number = 1
--source include/galera_connect.inc
+# node_1c tests write to unrelated table trough a transaction
+--let $galera_connection_name = node_1c
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+
+--connection node_1
+SET DEBUG_SYNC= 'RESET';
+SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+--sleep 10
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables';
+
+# if we would retry the insert, it would fail for wrong column count
+# on second try
+SET wsrep_retry_autocommit=0;
# Allowed
SELECT COUNT(*) = 0 FROM t1;
@@ -32,33 +43,49 @@ SELECT COUNT(*) = 0 FROM t1;
# Allowed
SELECT COUNT(*) = 0 FROM t2;
-# Not allowed
---error ER_LOCK_DEADLOCK,ER_ERROR_DURING_COMMIT
-INSERT INTO t1 VALUES (1);
+# Not allowed, this will hang because of ALTER
+--send INSERT INTO t1 VALUES (1);
+
+--connection node_1c
+SET SESSION wsrep_sync_wait = 0;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
# Allowed
+SELECT COUNT(*) = 0 FROM t1;
+
+# Allowed
+SELECT COUNT(*) = 0 FROM t2;
+
+# Allowed (until commit)
INSERT INTO t2 VALUES (1);
# Hangs
--send COMMIT;
---sleep 1
--connection node_1b
SET SESSION wsrep_sync_wait = 0;
# The Commit issued above is still not done
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+--sleep 1
SELECT COUNT(*) = 0 FROM t2;
+
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+
SET DEBUG_SYNC= 'now SIGNAL continue';
--connection node_1a
+--error ER_LOCK_DEADLOCK
+--reap
+
+--connection node_1c
+# this will succeeed, becaus the query will be replayed
--reap
--connection node_1
--reap
+
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 1 FROM t2;
@@ -66,11 +93,5 @@ SELECT COUNT(*) = 1 FROM t2;
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 1 FROM t2;
---connection node_1
-SET DEBUG_SYNC= 'RESET';
-
---connection node_1b
-SET DEBUG_SYNC= 'RESET';
-
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/t/galera_transaction_replay.test b/mysql-test/suite/galera/t/galera_transaction_replay.test
index 29870829ba3..655714f26c9 100644
--- a/mysql-test/suite/galera/t/galera_transaction_replay.test
+++ b/mysql-test/suite/galera/t/galera_transaction_replay.test
@@ -1,12 +1,25 @@
#
-# This test tests the operation of transaction replay. If a potentially conflicting remote transaction arrives at
-# just the right time during the commit of a local transaction, the local transaction will be aborted and replayed.
+# This test tests the operation of transaction replay. If a potentially
+# conflicting remote transaction arrives at just the right time during
+# the commit of a local transaction, the local transaction will be aborted
+# and replayed.
+#
+# Because the write set with higher sequence number cannot BF abort
+# the victim with lower sequence number, the conflicting remote transaction
+# must be executed first and must be allowed to proceed up to the apply
+# monitor before sending the COMMIT for the transaction to be replayed.
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+######################################################################
+#
+# Scenario #1, the victim will have higher seqno and will be replayed
+#
+######################################################################
--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
@@ -21,34 +34,123 @@ START TRANSACTION;
UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
-# Block the commit
+# Block the applier on node #1 and issue a conflicting update on node #2
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Block the commit, send the COMMIT and wait until it gets blocked
+
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_set_sync_point.inc
--connection node_1
---send COMMIT;
+--send COMMIT
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
--source include/galera_wait_sync_point.inc
-# Issue a conflicting update on node #2
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+# Commit succeeds
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
--connection node_2
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+DROP TABLE t1;
+
+#########################################################################
+#
+# Scenario #2, the victim will have lower seqno and will not be replayed
+#
+#########################################################################
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+# Block the commit, send the COMMIT and wait until it gets blocked
+
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+--send COMMIT
-# Wait for both transactions to be blocked
--connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%';
---source include/wait_condition.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT';
---source include/wait_condition.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+
+# Set sync point at the end of BF abort, issue a conflicting update
+# and wait for the conflicting update to hit the sync point.
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
-# Unblock the commit
--connection node_1a
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Let the transactions proceed
--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
# Commit succeeds
@@ -58,10 +160,10 @@ UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
-# wsrep_local_replays has increased by 1
+# wsrep_local_replays should have not increased
--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
--disable_query_log
---eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 0 AS wsrep_local_replays;
--enable_query_log
--connection node_2
@@ -70,55 +172,84 @@ SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
DROP TABLE t1;
-#echo "# test for PS replaying"
+########################################
#
# test replaying of prepared statements
#
+########################################
+
--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
CREATE TABLE t1 (i int primary key, j int) ENGINE=INNODB;
INSERT INTO t1 VALUES (1, 0), (3, 0);
SELECT * FROM t1;
-
+SET AUTOCOMMIT=ON;
PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0";
-# block the commit of PS
+
+# Block the applier on node #1 and issue a conflicting update on node #2
--connection node_1a
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
---connection node_1
---send EXECUTE stmt1;
+--connection node_2
+INSERT INTO t1 VALUES(2,2);
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
-# Issue a conflicting update on node_2
---connection node_2
-#UPDATE t1 SET j=2;
-INSERT INTO t1 VALUES(2,2);
+# Block the commit, send the EXECUTE stmt1 and wait until it gets blocked
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
-# Wait until applying begins in node_1
---connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Write_rows_log_event::write_row%';
---source include/wait_condition.inc
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+--send EXECUTE stmt1
-# Unblock the PS commit
--connection node_1a
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
+
+# Let the conflicting INSERT proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
# Commit succeeds
--connection node_1
--reap
+SET SESSION wsrep_sync_wait=7;
SELECT * FROM t1;
--connection node_2
SELECT * FROM t1;
--connection node_1
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test
index 6d99d35cdac..85ae73ffda4 100644
--- a/mysql-test/suite/galera/t/galera_var_cluster_address.test
+++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test
@@ -19,8 +19,8 @@
SET GLOBAL wsrep_cluster_address = 'foo://';
# With wsrep_sync_wait, this returns an error
-#--error ER_LOCK_WAIT_TIMEOUT
-#SHOW STATUS;
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW STATUS;
SET SESSION wsrep_sync_wait=0;
@@ -29,7 +29,7 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
# Must return 'OFF'
SHOW STATUS LIKE 'wsrep_ready';
-# Must return 'Non-primary'
+# Must return 'Disconnected'
SHOW STATUS LIKE 'wsrep_cluster_status';
# Must return 0 = 'Initialized'
@@ -49,10 +49,9 @@ SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VA
--connection node_2
--disable_query_log
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2';
+--source include/galera_wait_ready.inc
--enable_query_log
---source include/wait_until_connected_again.inc
-
--connection node_1
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
@@ -63,7 +62,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo");
CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo");
CALL mtr.add_suppression("gcs connect failed: Socket type not supported");
CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7");
-CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)");
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)");
CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110");
CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)");
CALL mtr.add_suppression("gcs connect failed: Connection timed out");
diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test
index 1f01c4aac07..cdb12bea9ed 100644
--- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test
+++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test
@@ -32,7 +32,7 @@ SET SESSION wsrep_sync_wait=0;
# Must return 'OFF'
SHOW STATUS LIKE 'wsrep_ready';
-# Must return 'Non-primary'
+# Must return 'Disconnected'
SHOW STATUS LIKE 'wsrep_cluster_status';
--error ER_UNKNOWN_COM_ERROR
@@ -53,6 +53,7 @@ SET @@session.wsrep_dirty_reads=OFF;
--error ER_UNKNOWN_COM_ERROR
SELECT i, variable_name, variable_value FROM t1, information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads" AND i = 1;
+
SELECT 1;
USE information_schema;
@@ -65,6 +66,7 @@ SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history;
--eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved'
--enable_query_log
--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
--connection node_1
USE test;
@@ -72,8 +74,6 @@ SELECT * FROM t1;
# Cleanup
DROP TABLE t1;
---source include/auto_increment_offset_restore.inc
-
--source include/galera_end.inc
--echo # End of test
diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
new file mode 100644
index 00000000000..269e28465d8
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
@@ -0,0 +1,235 @@
+#
+# Test option wsrep_ignore_apply_errors
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+#
+# Ignore reconciling DDL errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 1;
+
+# Drop table that does not exist
+--connection node_1
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+DROP TABLE t1;
+
+# Drop schema that does not exist
+SET GLOBAL wsrep_on = OFF;
+CREATE SCHEMA s1;
+SET GLOBAL wsrep_on = ON;
+DROP SCHEMA s1;
+
+# Drop index that does not exist using DROP INDEX
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+DROP INDEX idx1 ON t1;
+DROP TABLE t1;
+
+# Drop index that does not exist using ALTER TABLE
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP INDEX idx1;
+DROP TABLE t1;
+
+# Drop column that does not exist
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP COLUMN f2;
+DROP TABLE t1;
+
+
+#
+# Ignore reconciling DML errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+# Delete row that does not exist
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+DELETE FROM t1 WHERE f1 = 1;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+DROP TABLE t1;
+
+# Delete row that does not exist in a multi statement transaction
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+#
+# Multi-row delete where only one row does not exist
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+--connection node_1
+DELETE FROM t1;
+
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1;
+
+#
+# Multi-statement delete where only one row does not exist
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+--connection node_1
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+DELETE FROM t1 WHERE f1 = 4;
+DELETE FROM t1 WHERE f1 = 5;
+COMMIT;
+SET AUTOCOMMIT=ON;
+
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1;
+
+#
+# Multi-table delete
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t2;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t2 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+
+--connection node_1
+DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1,t2;
+
+#
+# Foreign keys
+#
+
+--connection node_1
+CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+INSERT INTO parent VALUES (1),(2),(3);
+CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB;
+INSERT INTO child VALUES (1,1),(2,2),(3,3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM child;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM child WHERE parent_id = 2;
+SET SESSION wsrep_on = ON;
+
+--connection node_1
+DELETE FROM parent;
+SELECT COUNT(*) = 0 FROM parent;
+SELECT COUNT(*) = 0 FROM child;
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM parent;
+SELECT COUNT(*) = 0 FROM child;
+DROP TABLE child, parent;
+
+#
+# Ignore all DDL errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 4;
+
+# Create a table that already exists
+--connection node_2
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+DROP TABLE t1;
+
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
+
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query.");
diff --git a/mysql-test/suite/galera/t/galera_var_log_bin.cnf b/mysql-test/suite/galera/t/galera_var_log_bin.cnf
index f7f17e3720a..30ccee2024e 100644
--- a/mysql-test/suite/galera/t/galera_var_log_bin.cnf
+++ b/mysql-test/suite/galera/t/galera_var_log_bin.cnf
@@ -3,3 +3,8 @@
[mysqld]
log-bin
+[mysqld.1]
+log-slave-updates
+
+[mysqld.2]
+log-slave-updates
diff --git a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test
index 142f02546b4..8fc4a3e338d 100644
--- a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test
+++ b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test
@@ -16,7 +16,7 @@
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET SESSION wsrep_retry_autocommit = 0;
-SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue';
+SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue';
--send INSERT INTO t1 (f1) VALUES (2)
--connection node_1a
@@ -42,8 +42,8 @@ DROP TABLE t1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET SESSION wsrep_retry_autocommit = 1;
-SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue';
---send INSERT INTO t1 (f1) VALUES (2)
+SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue';
+--send INSERT INTO t1 (f1) VALUES (3)
--connection node_1a
SET DEBUG_SYNC = 'now WAIT_FOR before_rep';
@@ -68,12 +68,16 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET SESSION wsrep_retry_autocommit = 1;
SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit';
-SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 2';
+SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue EXECUTE 2';
+--sleep 5
+show processlist;
---send INSERT INTO t1 VALUES (2);
+--send INSERT INTO t1 VALUES (4);
--connection node_1a
SET DEBUG_SYNC = 'now WAIT_FOR before_rep';
+--sleep 5
+show processlist;
--connection node_2
TRUNCATE TABLE t1;
@@ -107,9 +111,9 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET SESSION wsrep_retry_autocommit = 64;
SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit';
-SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 64';
+SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue EXECUTE 64';
---send INSERT INTO t1 VALUES (2)
+--send INSERT INTO t1 VALUES (5)
--disable_query_log
--disable_result_log
diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test
index 80edcb2aff9..122d7dd5ae2 100644
--- a/mysql-test/suite/galera/t/galera_var_slave_threads.test
+++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test
@@ -21,7 +21,8 @@ SELECT @@wsrep_slave_threads = 1;
SET GLOBAL wsrep_slave_threads = 1;
# There is a separate wsrep_aborter thread at all times
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
#
# Increase the number of slave threads. The change takes effect immediately
@@ -37,9 +38,15 @@ INSERT INTO t1 VALUES (1);
--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
--source include/wait_condition.inc
-SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) FROM t1;
+
+#
+# note, in wsrep API #26, we have 2 rollbacker threads, counted as system user's
+#
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
#
@@ -63,51 +70,113 @@ while ($count)
--enable_result_log
--connection node_2
-SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) = 64 FROM t2;
+SET wsrep_sync_wait=0;
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
--source include/wait_condition.inc
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+--let $wsrep_provider_node2 = `SELECT @@wsrep_provider`
---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+SET GLOBAL wsrep_slave_threads = 5;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
-DROP TABLE t1;
-DROP TABLE t2;
+SET GLOBAL wsrep_slave_threads = 1;
+
+#
+# test phase for bug https://github.com/codership/mysql-wsrep/issues/319
+#
---echo #
---echo # lp:1372840 - Changing wsrep_slave_threads causes future connections to hang
---echo #
+# shutdown node 2
+--connection node_2
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+# wait until node_1 is ready as one node cluster
--connection node_1
-CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB;
+SET wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+show status like 'wsrep_cluster_size';
---connection node_2
-SET GLOBAL wsrep_slave_threads = 4;
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+# step up slave threads to 6, and make sure all appliers and rollbacker thread are running
+SET GLOBAL wsrep_slave_threads = 6;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
+# change to invalid cluster address
SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL wsrep_cluster_address='';
---connection node_1
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-DROP TABLE t1;
+# join back to single node cluster
+SET GLOBAL wsrep_cluster_address='gcomm://';
+--source include/wait_until_connected_again.inc
---connection node_2
+# we should have 1 applier thread now
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
-# Wait until above DDL is replicated
---let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
+# test if we can increase applier count now (fails in bug #319)
+SET GLOBAL wsrep_slave_threads = 10;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
-SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
+# restart node 2
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+#
#
-# make sure that we are left with exactly one applier thread before we leaving the test
+# cleanup to original state
#
---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+--connection node_1
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+
+--connection node_2
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+
+# Generate 64 replication events, to help node 1 to purge excessive applier threads
+--let $count = 64
+while ($count)
+{
+ INSERT INTO t2 VALUES (DEFAULT);
+ --dec $count
+}
+
+--connection node_1
+# Generate 64 replication events, to help node 2 to purge excessive applier threads
+--let $count = 64
+while ($count)
+{
+ INSERT INTO t2 VALUES (DEFAULT);
+ --dec $count
+}
+
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 4;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_slave_threads = 1;
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
+
+DROP TABLE t1;
+DROP TABLE t2;
--echo # End of tests
diff --git a/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt
new file mode 100644
index 00000000000..beae84b3862
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt
@@ -0,0 +1 @@
+--log-bin
diff --git a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
index 6ba8ce786c8..28025363019 100644
--- a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
+++ b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
@@ -5,7 +5,6 @@
#
--source include/galera_cluster.inc
---source include/have_innodb.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected';
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
new file mode 100644
index 00000000000..beae84b3862
--- /dev/null
+++ b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
@@ -0,0 +1 @@
+--log-bin
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#237.test b/mysql-test/suite/galera/t/mysql-wsrep#237.test
index cba8dfeb275..174266bdbc5 100644
--- a/mysql-test/suite/galera/t/mysql-wsrep#237.test
+++ b/mysql-test/suite/galera/t/mysql-wsrep#237.test
@@ -7,13 +7,13 @@
CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
--connection node_1
-SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue';
+SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue';
--send INSERT INTO t values (1);
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connection node_1a
SET SESSION wsrep_sync_wait = 0;
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_replication'
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_certification'
--source include/wait_condition.inc
--connection node_2
diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test
index bb5a02411c3..7fa6b9e800c 100644
--- a/mysql-test/suite/galera/t/partition.test
+++ b/mysql-test/suite/galera/t/partition.test
@@ -131,9 +131,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY)
--connection node_2
SELECT COUNT(*) = 20002 FROM t1;
-# LOAD-ing 20002 rows causes 3 commits to be registered
+# LOAD-ing 20002 rows causes
+# 3 commits to be registered when the Galera library does not support streaming replication and
+# 5 commits to be registered when the Galera library supports streaming replication
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 3 AS wsrep_last_committed_diff;
+--replace_result 3 AS_EXPECTED_3_or_5 5 AS_EXPECTED_3_or_5
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
@@ -161,7 +164,7 @@ SELECT COUNT(*) = 101 FROM t1;
# LOAD-ing 101 rows causes 1 commit to be registered
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff;
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
@@ -188,9 +191,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY)
--connection node_2
SELECT COUNT(*) = 20002 FROM t1;
-# LOAD-ing 20002 rows causes 1 commit to be registered
+# LOAD-ing 20002 rows causes
+# 1 commit to be registered when the Galera library does not support streaming replication and
+# 2 commits to be registered when the Galera library supports streaming replication
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff;
+--replace_result 1 AS_EXPECTED_1_or_2 2 AS_EXPECTED_1_or_2
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.test b/mysql-test/suite/galera/t/rpl_row_annotate.test
index b1cfdb36639..b9bae724d7f 100644
--- a/mysql-test/suite/galera/t/rpl_row_annotate.test
+++ b/mysql-test/suite/galera/t/rpl_row_annotate.test
@@ -3,11 +3,15 @@
--echo # On node_2
--connection node_2
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
--echo # On node_1
--connection node_1
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
CREATE TABLE t1(i INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
DELETE FROM t1 WHERE i = 1;
@@ -38,5 +42,5 @@ let $start_pos= `select @binlog_start_pos`;
# Cleanup
DROP TABLE t1;
---source include/galera_end.inc
+#--source include/galera_end.inc
--echo # End of test
diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test
new file mode 100644
index 00000000000..f189368cc0f
--- /dev/null
+++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test
@@ -0,0 +1,26 @@
+-- source include/galera_cluster.inc
+
+-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'`
+
+if ($sr)
+{
+ -- skip The test requires a wsrep provider that does not support streaming replication.
+}
+
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET SESSION wsrep_trx_fragment_size = 0;
+-- error ER_WRONG_VALUE_FOR_VAR
+SET SESSION wsrep_trx_fragment_size = 123;
+SHOW WARNINGS;
+
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET GLOBAL wsrep_trx_fragment_size = 0;
+-- error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL wsrep_trx_fragment_size = 123;
+SHOW WARNINGS;
+
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test
new file mode 100644
index 00000000000..a970cc09afc
--- /dev/null
+++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test
@@ -0,0 +1,22 @@
+-- source include/galera_cluster.inc
+
+-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'`
+
+if (!$sr)
+{
+ -- skip The test requires a wsrep provider that supports streaming replication.
+}
+
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
index 91aa53ad7b1..cc6107d62ce 100644
--- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
+++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
@@ -17,6 +17,7 @@ wsrep-sync-wait=15
#galera_port=(a)OPT.port
#ist_port=(a)OPT.port
#sst_port=(a)OPT.port
+#wsrep-new-cluster
wsrep-cluster-address='gcomm://'
wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S'
diff --git a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
index 3495ad2342b..d4037d8958c 100644
--- a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
+++ b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
@@ -9,6 +9,6 @@
my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
- system("kill -19 $mysqld_pid");
+ system("kill -SIGSTOP $mysqld_pid");
exit(0);
EOF
diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
index b1bbb1406a1..6393a30da6f 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_3;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
index e1528c6f74f..d43b42bec45 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
@@ -11,6 +13,7 @@ connection node_3;
INSERT INTO t2 VALUES (1);
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_3;
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
index 53e35939a79..56348889cf9 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
@@ -13,6 +13,3 @@ COUNT(*) = 1
1
DROP TABLE t1;
include/assert_grep.inc [Streaming the backup to joiner at \[::1\]]
-include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:]
-include/assert_grep.inc [IST receiver addr using tcp://\[::1\]]
-include/assert_grep.inc [Prepared IST receiver, listening at: tcp://\[::1\]]
diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
index 3d4dbcc00b0..7780c3f73b8 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_3;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result
index 4f9951c382f..8211fb8501e 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_3;
@@ -12,7 +14,7 @@ connection node_3;
SELECT f1 = 111 FROM t1;
f1 = 111
1
-SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%';
+SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%';
COUNT(*) IN (1, 2)
1
SET GLOBAL wsrep_slave_threads = 1;;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
index 69995acb982..ee49330e892 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
@@ -1,8 +1,15 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER);
+connection node_1;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
SET SESSION wsrep_sync_wait = 0;
+connection node_2;
SET GLOBAL wsrep_provider_options = 'pc.bootstrap=1';
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
@@ -11,15 +18,21 @@ SHOW STATUS LIKE 'wsrep_cluster_status';
Variable_name Value
wsrep_cluster_status Primary
INSERT INTO t1 VALUES (1);
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
+connection node_2;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
+connection node_3;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
index 9f845ffe776..d991e497706 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
@@ -67,7 +67,6 @@ VARIABLE_VALUE = 4
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
-SET GLOBAL wsrep_provider_options = 'pc.weight=1';
SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight';
VARIABLE_VALUE = 1
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
new file mode 100644
index 00000000000..89520a7c565
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
@@ -0,0 +1,77 @@
+connection node_2;
+connection node_1;
+SHOW CREATE TABLE wsrep_schema.cluster;
+Table Create Table
+cluster CREATE TABLE `cluster` (
+ `cluster_uuid` char(36) NOT NULL,
+ `view_id` bigint(20) NOT NULL,
+ `view_seqno` bigint(20) NOT NULL,
+ `protocol_version` int(11) NOT NULL,
+ PRIMARY KEY (`cluster_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE wsrep_schema.members;
+Table Create Table
+members CREATE TABLE `members` (
+ `node_uuid` char(36) NOT NULL,
+ `cluster_uuid` char(36) NOT NULL,
+ `node_name` char(32) NOT NULL,
+ `node_incoming_address` varchar(256) NOT NULL,
+ PRIMARY KEY (`node_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM wsrep_schema.cluster;
+COUNT(*) = 1
+1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members;
+COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size')
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+COUNT(*) = 1
+1
+SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members;
+node_incoming_address LIKE '127.0.0.1:%'
+1
+1
+1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+1
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+COUNT(*) = 1
+1
+connection node_2;
+connection node_1;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+COUNT(*) = 2
+1
+connection node_2;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+connection node_1;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+connection node_1;
+CALL mtr.add_suppression("SYNC message from member");
+connection node_2;
+CALL mtr.add_suppression("SYNC message from member");
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.test b/mysql-test/suite/galera_3nodes/t/GAL-501.test
index 60ed5989227..9e3aff0c437 100644
--- a/mysql-test/suite/galera_3nodes/t/GAL-501.test
+++ b/mysql-test/suite/galera_3nodes/t/GAL-501.test
@@ -7,6 +7,12 @@
--source include/galera_cluster.inc
--source include/have_ipv6.inc
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
+
# Confirm that initial handshake happened over ipv6
SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';
diff --git a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
index a2ad0765028..5366d2a4a6e 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
@@ -29,5 +29,7 @@ INSERT INTO t2 VALUES (1);
--error ER_LOCK_DEADLOCK
COMMIT;
+--connection node_3
+--source include/galera_wait_ready.inc
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
index 03236a3cb93..a4767928681 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
@@ -60,9 +60,9 @@ DROP TABLE t1;
--source include/galera_resume.inc
--source include/wait_until_connected_again.inc
-CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
-
--disable_query_log
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node3';
--enable_query_log
---source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd.test b/mysql-test/suite/galera_3nodes/t/galera_garbd.test
index a68ba8ce15b..519f992d1b4 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_garbd.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test
@@ -32,7 +32,10 @@ INSERT INTO t1 VALUES (1);
SELECT COUNT(*) = 1 FROM t1;
--echo Killing garbd ...
---exec pkill --oldest --full garbd.*$NODE_GALERAPORT_3
+# FreeBSD's /bin/pkill only supports short versions of the options:
+# -o Select only the oldest (least recently started)
+# -f Match against full argument lists
+--exec pkill -o -f garbd.*$NODE_GALERAPORT_3
--sleep 5
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf
index 3728e1ce005..1412ab4c808 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf
+++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf
@@ -8,15 +8,21 @@ wsrep-cluster-address=gcomm://
wsrep_provider_options='base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port'
+wsrep_causal_reads=0
+wsrep_sync_wait=0
[mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port'
+wsrep_causal_reads=0
+wsrep_sync_wait=0
[mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port'
+wsrep_causal_reads=0
+wsrep_sync_wait=0
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
index 8a80be0d2a9..5cc8fb04cdd 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
@@ -5,18 +5,22 @@ wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="root:"
[mysqld.1]
+wsrep_node_name='node_1'
wsrep-cluster-address=gcomm://
wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port'
[mysqld.2]
+wsrep_node_name='node_2'
+wsrep_sst_donor='node_1'
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port'
[mysqld.3]
+wsrep_node_name='node_3'
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port'
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
index 84eee017700..6756cce6e02 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
@@ -42,20 +42,22 @@ DROP TABLE t1;
--let $assert_select = Streaming the backup to joiner at \[::1\]
--source include/assert_grep.inc
---let $assert_count = 1
---let $assert_text = async IST sender starting to serve tcp://\[::1\]:
---let $assert_select = async IST sender starting to serve tcp://\[::1\]:
---source include/assert_grep.inc
-
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
-
---let $assert_text = IST receiver addr using tcp://\[::1\]
---let $assert_select = IST receiver addr using tcp://\[::1\]
---source include/assert_grep.inc
-
---let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\]
---let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\]
---source include/assert_grep.inc
+# asserts below are not deterministic
+# --let $assert_count = 2
+# --let $assert_text = async IST sender starting to serve tcp://\[::1\]:
+# --let $assert_select = async IST sender starting to serve tcp://\[::1\]:
+# --source include/assert_grep.inc
+#
+# --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
+#
+# --let $assert_text = IST receiver addr using tcp://\[::1\]
+# --let $assert_select = IST receiver addr using tcp://\[::1\]
+# --source include/assert_grep.inc
+#
+# --let $assert_count = 1
+# --let $assert_text = Prepared IST receiver for 4-7, listening at: tcp://\[::1\]
+# --let $assert_select = Prepared IST receiver for 4-7, listening at: tcp://\[::1\]
+# --source include/assert_grep.inc
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
index a67b30e3fa1..9e43c90bfc1 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
@@ -11,7 +11,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--let $galera_connection_name = node_3
--let $galera_server_number = 3
diff --git a/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test
index 7d80d8036a1..659df2b3c93 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test
@@ -31,7 +31,7 @@ SET GLOBAL wsrep_slave_threads = 2;
--connection node_3
SELECT f1 = 111 FROM t1;
-SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%';
+SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%';
--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
index 57026ce6928..1a61471d581 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
+++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
@@ -1,5 +1,7 @@
-# We need a dedicated .cnf file, even if empty, in order to force this test to run
-# alone on a freshly started cluster. Otherwise there are adverse interactions with
-# following tests such as galera_3nodes.galera_var_dirty_reads2
+# We need a dedicated .cnf file, even if empty, in order to force this test
+# to run alone on a freshly started cluster. Otherwise there are adverse
+# interactions with following tests such as
+# galera_3nodes.galera_var_dirty_reads2
+!include ../galera_3nodes.cnf
!include ../galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
index 0a94e7cd85d..2959a49327e 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
@@ -1,11 +1,11 @@
#
-# Test the pc.weight wsrep provider option. We set Node #1 to have a high weight and then
-# suspend it. This will cause Nodes #2 and #3 to transition to non-primary component.
+# Test the pc.weight wsrep provider option. We set Node #1 to have a high
+# weight and then suspend it. This will cause Nodes #2 and #3 to transition
+# to non-primary component.
#
--source include/big_test.inc
--source include/galera_cluster.inc
---source include/have_innodb.inc
--connection node_1
SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight';
@@ -55,6 +55,9 @@ SHOW STATUS LIKE 'wsrep_local_state_comment';
--connection node_1
# For Node #1, we expect a primary component of size 1
+# (NOTE: this is a bit racy as nodes 2 and 3 will try to reconnect ASAP.
+# to avoid the raice they should be suspended first as well, but that's
+# not currently possible)
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
@@ -66,24 +69,18 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state';
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
-SET GLOBAL wsrep_provider_options = 'pc.weight=1';
-SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight';
-
-# Resume cluster connectivity on node_1
---connection node_1
-SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
-
---let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
---source include/wait_condition.inc
+# wait for nodes 2 and 3 to reconnect
--connection node_2
---source include/wait_condition.inc
+--source include/galera_wait_ready.inc
--connection node_3
---source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+
+# On all nodes, we now expect a Primary component of size 3, Synced and ready
--connection node_1
---source include/wait_condition.inc
+--source include/galera_wait_ready.inc
# On all nodes, we now expect a Primary component of size 3, weight 3, Synced and ready
SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
diff --git a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
index 3e8b1557e7b..8e73dee70ae 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
@@ -25,6 +25,7 @@ SELECT COUNT(*) = 1 FROM db2.t2B;
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connection node_3
+--source include/galera_wait_ready.inc
SELECT COUNT(*) = 0 FROM db1.t1;
SELECT COUNT(*) = 1 FROM db2.t2A;
SELECT COUNT(*) = 1 FROM db2.t2B;
diff --git a/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test
new file mode 100644
index 00000000000..9c0b074ab0b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test
@@ -0,0 +1,74 @@
+#
+# This test performs basic checks on the contents of the wsrep_schema
+#
+# wsrep_schema.members_history checks are temporarily disabled until it
+# can be made configurable.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Make the test fail if table structure has changed
+
+SHOW CREATE TABLE wsrep_schema.cluster;
+SHOW CREATE TABLE wsrep_schema.members;
+#disabled SHOW CREATE TABLE wsrep_schema.members_history;
+
+# Checks for the wsrep_schema.cluster table
+
+SELECT COUNT(*) = 1 FROM wsrep_schema.cluster;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+
+# Checks for the wsrep_schema.members table
+
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members;
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+
+SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members;
+
+# Checks for the wsrep_schema.members_history table
+
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history;
+#disabled SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members_history;
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+
+#disabled SELECT last_view_id = (SELECT view_id FROM wsrep_schema.cluster) FROM wsrep_schema.members_history;
+#disabled SELECT last_view_seqno = (SELECT view_seqno FROM wsrep_schema.cluster) FROM wsrep_schema.members_history;
+#disabled SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members_history;
+#disabled SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members_history;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history;
+#disabled SELECT COUNT(*) = 2 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_1
+CALL mtr.add_suppression("SYNC message from member");
+
+--connection node_2
+CALL mtr.add_suppression("SYNC message from member");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf
new file mode 100644
index 00000000000..62c8214b8f2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf
@@ -0,0 +1 @@
+!include ../galera_3nodes/galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc
new file mode 100644
index 00000000000..5c74adc46a2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc
@@ -0,0 +1,58 @@
+#
+# Test that after an inconsistency vote that kicked out node #2, the
+# cluster is able to recover
+#
+
+# Nodes #1 and #3 remain in the cluster
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connect node_3X, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3X
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Node #2 is kicked out
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+SET SESSION wsrep_on=ON;
+
+# Restore cluster
+
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--exec echo "wait" > $_expect_file_name
+# Exclude SHOW commands run during server shutdown from sync waiting
+--disable_query_log
+SET SESSION wsrep_sync_wait = 7;
+--enable_query_log
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--sleep 5
+--source include/start_mysqld.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Confirm that the t1 table is now identical throughout
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+--connection node_3X
+SHOW CREATE TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/my.cnf b/mysql-test/suite/galera_3nodes_ee/my.cnf
new file mode 100644
index 00000000000..bb25b95ceea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/my.cnf
@@ -0,0 +1 @@
+!include galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result
new file mode 100644
index 00000000000..0d52b668e91
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result
@@ -0,0 +1,23 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f1 INTEGER);
+CREATE TABLE test.t1 (f1 INTEGER);
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+DROP TABLE test.t1;
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result
new file mode 100644
index 00000000000..6a0af777277
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result
@@ -0,0 +1,16 @@
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+FLUSH TABLES WITH READ LOCK;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+UNLOCK TABLES;
+DROP TABLE t1;
+SET SESSION wsrep_on = OFF;
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result
new file mode 100644
index 00000000000..ff67cab1303
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result
@@ -0,0 +1,31 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+INSERT INTO t1 VALUES (1, 'b');
+SET SESSION wsrep_sync_wait = 0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_on=ON;
+SELECT * FROM t1;
+f1 f2
+1 a
+SELECT * FROM t1;
+f1 f2
+1 a
+SELECT * FROM t1;
+f1 f2
+1 a
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster.");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result
new file mode 100644
index 00000000000..4c699913890
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result
@@ -0,0 +1,48 @@
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+LOCK TABLE t1 WRITE;
+INSERT INTO t1 VALUES (1, 'b');
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+UNLOCK TABLES;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SHOW STATUS LIKE 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 0
+SET GLOBAL wsrep_on=OFF;
+SELECT * FROM t1;
+f1 f2
+1 a
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+SHOW STATUS LIKE 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 1
+SELECT * FROM t1;
+f1 f2
+1 b
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SELECT * FROM t1;
+f1 f2
+1 b
+SELECT * FROM t1;
+f1 f2
+1 b
+SELECT * FROM t1;
+f1 f2
+1 b
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result
new file mode 100644
index 00000000000..a93b73feafc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result
@@ -0,0 +1,21 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+Killing server ...
+Killing server ...
+DROP TABLE test.t1;
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result
new file mode 100644
index 00000000000..5071d6746d1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result
@@ -0,0 +1,19 @@
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1);
+LOCK TABLE t1 WRITE;
+SET GLOBAL wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+UNLOCK TABLES;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SET GLOBAL wsrep_sync_wait=15;
+DROP TABLE test.t1;
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result
new file mode 100644
index 00000000000..be092572de3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result
@@ -0,0 +1,32 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+CALL mtr.add_suppression('discarding established');
+CALL mtr.add_suppression('Quorum: No node with complete state');
+ERROR HY000: Lost connection to MySQL server during query
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result
new file mode 100644
index 00000000000..b8b0f1ca130
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result
new file mode 100644
index 00000000000..29b87232164
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result
@@ -0,0 +1,35 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+Performing --wsrep-recover ...
+Using --wsrep-start-position when starting mysqld ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result
new file mode 100644
index 00000000000..0d687a4d43f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result
new file mode 100644
index 00000000000..b9b9fabb1bc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result
@@ -0,0 +1,46 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("inconsistent with group");
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result
new file mode 100644
index 00000000000..e16dfc643d0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result
@@ -0,0 +1,50 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("Non-blocking operation end failed");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result
new file mode 100644
index 00000000000..3efc772cea0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_OSU_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 42000: Multiple primary key defined
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression("SYNC message from member");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("TO isolation end failed");
+CALL mtr.add_suppression("SYNC message from member");
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result
new file mode 100644
index 00000000000..7aa1ac5d8bf
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("inconsistent with group");
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result
new file mode 100644
index 00000000000..dd4e3674786
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+SET SESSION lock_wait_timeout=2;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+ERROR HY000: Got error 6 during COMMIT
+SET SESSION wsrep_sync_wait = 0;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+INSERT INTO t1 VALUES (2,2);
+SET SESSION wsrep_on = OFF;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate");
+CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6");
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result
new file mode 100644
index 00000000000..3b7b96d8fde
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result
@@ -0,0 +1,32 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result
new file mode 100644
index 00000000000..79c7990b158
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1,2);
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result
new file mode 100644
index 00000000000..4b704facf24
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result
@@ -0,0 +1,35 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -1");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result
new file mode 100644
index 00000000000..a0a30f23e25
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result
@@ -0,0 +1,19 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+CREATE SCHEMA test;
+ERROR HY000: Can't create database 'test'; database exists
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("inconsistent with group");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result
new file mode 100644
index 00000000000..64c8b85d440
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result
@@ -0,0 +1,60 @@
+Setting SST method to mysqldump ...
+GRANT ALL PRIVILEGES ON *.* TO 'sst';
+SET GLOBAL wsrep_sst_auth = 'sst:';
+SET GLOBAL wsrep_sst_method = 'mysqldump';
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_on=ON;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("is inconsistent with group");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'");
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+DROP USER sst;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found");
+CALL mtr.add_suppression("InnoDB: New log files created");
+CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables");
+CALL mtr.add_suppression("Can't open and lock time zone table");
+CALL mtr.add_suppression("Can't open and lock privilege tables");
+CALL mtr.add_suppression("Info table is not ready to be used");
+CALL mtr.add_suppression("Native table .* has the wrong structure");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result
new file mode 100644
index 00000000000..c2b618b86c4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (5, 'X');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 131070;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (2, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (3, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (4, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (5, REPEAT('A', 65535));
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+START TRANSACTION;
+INSERT INTO t1 VALUES (11, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (12, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (13, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (14, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (15, REPEAT('A', 65535));
+SET SESSION wsrep_on=OFF;
+Starting mysqld
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'");
+CALL mtr.add_suppression("Write_rows apply failed");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("no THD for trx");
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result
new file mode 100644
index 00000000000..3a6ad0f620f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test
new file mode 100644
index 00000000000..6dc89594c05
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+#
+# 1. Create different inconsistencies on nodes 2 and 3
+#
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f1 INTEGER);
+#
+# 2. The following should generate different errors on nodes 2 and 3 and
+# trigger voting with 3 different votes. node_1 should remain alone
+# in the cluster.
+#
+--connection node_1
+CREATE TABLE test.t1 (f1 INTEGER);
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+# Test cleanup
+DROP TABLE test.t1;
+#
+# 3. Wait for nodes 2 and 3 to drop out of the cluster and restart them to
+# recover the initial configuration.
+#
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/restart_mysqld.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
+--connection node_3
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test
new file mode 100644
index 00000000000..01dbb2147b3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test
@@ -0,0 +1,47 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+# create inconsistency
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+# block the node
+FLUSH TABLES WITH READ LOCK;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t1
+--source include/wait_condition.inc
+--sleep 1
+
+--connection node_3
+SELECT COUNT(*) = 0 FROM t1;
+UNLOCK TABLES;
+# Wait until the node leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+
+--connection node_1
+# Wait until node #3 leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+DROP TABLE t1;
+
+--connection node_3
+SET SESSION wsrep_on = OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf
new file mode 100644
index 00000000000..7b7770e3ad1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf
@@ -0,0 +1,8 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
+
+# [mysqld.3]
+# wsrep-sst-method=mysqldump
+# wsrep_sst_receive_address=127.0.0.2:@mysqld.3.port
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test
new file mode 100644
index 00000000000..0e8e8cc4276
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test
@@ -0,0 +1,68 @@
+#
+# GCF-363 Inconsistency voting: If in a 3-node cluster the nodes with applier
+# error survive, the other node can not join properly
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+INSERT INTO t1 VALUES (1, 'b');
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+--connection node_1
+# Wait until node #3 leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# need to use another connection to restart the node due to GCF-1000
+--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3a
+# ATM (12.11.2016) mysqldump SST does not seem to be working, rsync SST
+# requires node restart
+# SET GLOBAL wsrep_cluster_address= 'gcomm://127.0.0.1:13001';
+SET SESSION wsrep_on=OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_on=ON;
+
+--connection node_1
+SELECT * FROM t1;
+
+--connection node_2
+SELECT * FROM t1;
+
+--connection node_3a
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+
+--connection node_3a
+CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster.");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test
new file mode 100644
index 00000000000..b4146a12ebd
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test
@@ -0,0 +1,84 @@
+#
+# GCF-376: slaves become inconsistent if master goes non-prim during
+# inconsistency voting
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+LOCK TABLE t1 WRITE;
+
+--connection node_1
+INSERT INTO t1 VALUES (1, 'b');
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+
+# --sleep 10
+# Wait until node #1 leaves the cluster
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+UNLOCK TABLES;
+
+# Wait until node #2 leaves the cluster
+--source include/wsrep_wait_disconnect.inc
+
+--connection node_1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SET GLOBAL wsrep_on=OFF;
+SELECT * FROM t1;
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SELECT * FROM t1;
+
+# reconnect node #1
+--connection node_1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+# reconnect node #2
+--connection node_2
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test
new file mode 100644
index 00000000000..fae92aab4e8
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test
@@ -0,0 +1,67 @@
+#
+# This test tests that one successful node wins over two nodes that fail for
+# different reasons
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+# create inconsistency on node 2
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+# create inconsistency on node 3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+# wait for nodes 2 and 3 drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# reconnect nodes 2 and 3, since they failed
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_3
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_1
+DROP TABLE test.t1;
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_3
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test
new file mode 100644
index 00000000000..e600db4453b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test
@@ -0,0 +1,61 @@
+#
+# This test tests voting (successful slave wins) in the absence of the master
+# for trasaction.
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--let $wsrep_provider_orig = `SELECT @@wsrep_provider`
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1);
+LOCK TABLE t1 WRITE;
+SET GLOBAL wsrep_sync_wait=0;
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_3
+# wait for node_1 to disappear
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+UNLOCK TABLES;
+# wait to go non-Primary due to inconsistency voting
+#--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+#--source include/wait_condition.inc
+# Somehow the above times out so we use connectin to node 3
+
+--connection node_3
+# wait for node_1 to disappear
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+SET GLOBAL wsrep_sync_wait=15;
+DROP TABLE test.t1;
+
+# reconnect node 2, since it is now inconsistent
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+--sleep 1
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test
new file mode 100644
index 00000000000..4183dfcfaf5
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test
@@ -0,0 +1,75 @@
+# NB-DDL: Assertion `header_size_max() + csize <= size' failed in gu::RecordSetOutBase::write_header
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+# Set the ALTER to block on the master
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+# Wait until the ALTER has blocked on the master
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables';
+--source include/wait_condition.inc
+
+# Restart the master
+--source include/kill_galera.inc
+--sleep 5
+
+# Make sure the ALTER is aborted on node #1
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'
+--source include/wait_condition.inc
+
+--connection node_2a
+--source include/start_mysqld.inc
+--sleep 5
+
+# Confirm that all nodes have the same view of the database
+--connection node_1
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--let $galera_connection_name = node_2b
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2b
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_3
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+CALL mtr.add_suppression('discarding established');
+CALL mtr.add_suppression('Quorum: No node with complete state');
+
+--connection node_2
+--error 2013
+--reap
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test
new file mode 100644
index 00000000000..688ada7a120
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test
@@ -0,0 +1,73 @@
+#
+# This test kills the master (node_2 for this query) while the DDL is running there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+# Set the ALTER to block on the master
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+# Wait until the ALTER has blocked on the master
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables';
+--source include/wait_condition.inc
+
+# Restart the master
+--source include/kill_galera.inc
+--sleep 5
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_2a
+--source include/start_mysqld.inc
+--sleep 5
+
+# Confirm that all nodes have the same view of the database
+--connection node_1
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--let $galera_connection_name = node_2b
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2b
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_3
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+# CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+# CALL mtr.add_suppression('discarding established');
+# CALL mtr.add_suppression('Quorum: No node with complete state');
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test
new file mode 100644
index 00000000000..8f08f357046
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test
@@ -0,0 +1,73 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Kill the slave (node #3)
+--source include/kill_galera.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+
+# Restart node #3
+--connection node_3
+--let $galera_wsrep_recover_server_id=3
+--source suite/galera/include/galera_wsrep_recover.inc
+
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf
new file mode 100644
index 00000000000..36b1fa112a1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf
@@ -0,0 +1,11 @@
+!include ../galera_3nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=1'
+
+[mysqld.2]
+wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=1'
+
+[mysqld.3]
+wsrep_provider_options='base_port=(a)mysqld.3.#galera_port;gcache.size=1'
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test
new file mode 100644
index 00000000000..9caf2e7299e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test
@@ -0,0 +1,70 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Kill the slave (node #3)
+--source include/kill_galera.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+
+# Restart node #3
+--connection node_3
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test
new file mode 100644
index 00000000000..f7ff2e379a3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test
@@ -0,0 +1,38 @@
+#
+# Test the situation where the master is in the majority when an NBO DDL fails on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+
+--connection node_2
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Run DDL that will fail on nodes #1 and #3 but succeed on node #2
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("inconsistent with group");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test
new file mode 100644
index 00000000000..3fca44efa2a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test
@@ -0,0 +1,38 @@
+#
+# This test has the master in the majority when an
+# NBO DDL succeeds on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+--connection node_2
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("Non-blocking operation end failed");
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test
new file mode 100644
index 00000000000..151ae4f6ad8
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test
@@ -0,0 +1,35 @@
+#
+# This test has the master (node #2) in the minority when an
+# NBO DDL fails on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+SET SESSION wsrep_OSU_method='NBO';
+
+--error ER_MULTIPLE_PRI_KEY
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+DROP TABLE t1;
+CALL mtr.add_suppression("SYNC message from member");
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("TO isolation end failed");
+CALL mtr.add_suppression("SYNC message from member");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test
new file mode 100644
index 00000000000..b6a971a8e01
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test
@@ -0,0 +1,41 @@
+#
+# This test has the master (node #2) in the minority when an
+# NBO DDL succeeds on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Node #2 goes non-prim because it is in the minority
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_2
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Slave SQL: Error");
+
+--connection node_2
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_3
+--source include/galera_wait_ready.inc
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test
new file mode 100644
index 00000000000..79ff032f02b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test
@@ -0,0 +1,92 @@
+#
+# Test the case where a master node (node #2) goes non-primary while a DDL is running
+# The DDL times out and the node leaves the cluster, to rejoin via SST.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Issue a DDL
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+SET SESSION lock_wait_timeout=2;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--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 STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Isolate the master (node #2)
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# Confirm that the DDL remains blocked in NBO
+
+--connection node_2a
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end'
+--source include/wait_condition.inc
+
+# DDL should now return a failure
+
+--connection node_2
+--error ER_ERROR_DURING_COMMIT
+--reap
+
+# Node #2 is now non-prim
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connection node_1
+INSERT INTO t1 VALUES (2,2);
+
+--connection node_2
+# So we restart it to force SST
+SET SESSION wsrep_on = OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+# Confirm that the nodes are identical
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate");
+CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6");
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test
new file mode 100644
index 00000000000..995828b3ca1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test
@@ -0,0 +1,80 @@
+#
+# Test the case where a master node (node #2) goes non-primary while a DDL is running
+# The non-prim situation is resolved in time and the DDL completes successfully
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Issue a DDL
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--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 STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Isolate the master (node #2)
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# Confirm that the DDL remains blocked in NBO
+
+--connection node_2a
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end'
+--source include/wait_condition.inc
+
+# Reconnect node #2 to cluster
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# DDL should now be complete
+
+--connection node_2
+--reap
+
+# Confirm that the nodes are identical
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test
new file mode 100644
index 00000000000..58f7f00ed71
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test
@@ -0,0 +1,66 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Shutdown the slave (node #3)
+--source include/shutdown_mysqld.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+
+# Restart node #3
+--connection node_3
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test
new file mode 100644
index 00000000000..d4f3a4ffedd
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test
@@ -0,0 +1,69 @@
+#
+# Test the case where a slave node goes non-primary while a DDL is running
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -1");
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test
new file mode 100644
index 00000000000..23cfcd036a0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test
@@ -0,0 +1,63 @@
+#
+# This test tests that TOI failure on 2 nodes (master and slave) for the
+# same reason, wins over success on a third slave.
+# In particular this tests that master and slave TOI cast the same vote for
+# the same error
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+# create inconsistency on node 3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+# This should fail on nodes 1 and 2 and succeed on node 3
+--connection node_1
+--error ER_DB_CREATE_EXISTS
+CREATE SCHEMA test;
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+# wait for node 3 to drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+# wait for node 3 to drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# reconnect node 3, since it failed
+--connection node_3
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_1
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_3
+CALL mtr.add_suppression("inconsistent with group");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test
new file mode 100644
index 00000000000..bc696ed6896
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test
@@ -0,0 +1,80 @@
+#
+# Test that mysqldump SST is possible after a vote without a cluster restart
+#
+
+--source include/galera_cluster.inc
+--source suite/galera/include/galera_sst_set_mysqldump.inc
+
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+
+--connection node_2
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Run DDL that will fail on nodes #1 and #3 but succeed on node #2
+
+--connection node_1
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+
+# Nodes #1 and #3 remain in the cluster
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Node #2 is kicked out
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SET SESSION wsrep_on=ON;
+
+# Restore cluster
+
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2'
+--enable_query_log
+--enable_reconnect
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Confirm that the table is now identical throughout
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+SET SESSION wsrep_on=ON;
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+CALL mtr.add_suppression("is inconsistent with group");
+
+--connection node_3
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'");
+
+--connection node_1
+--source suite/galera/include/galera_sst_restore.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt
new file mode 100644
index 00000000000..196498bb9fa
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt
@@ -0,0 +1,2 @@
+--wsrep-ignore-apply-errors=0
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test
new file mode 100644
index 00000000000..7655c818de6
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test
@@ -0,0 +1,87 @@
+#
+# Test voting while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
+
+# Introduce inconsistency
+--connection node_2
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (5, 'X');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+
+# Perform an SR transaction that will hit the inconsistency
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 131070;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (2, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (3, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (4, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (5, REPEAT('A', 65535));
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Perform another SR transaction in order to have stuff in the wsrep_schema.SR table
+START TRANSACTION;
+INSERT INTO t1 VALUES (11, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (12, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (13, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (14, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (15, REPEAT('A', 65535));
+
+# Node #2 has dropped from the cluster due to voting
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Bring node #2 back via SST
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--source include/shutdown_mysqld.inc
+
+--sleep 10
+
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
+--source include/wait_condition.inc
+
+# Node #2 should have some entries in its SR table post-restart
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Commit second SR transaction
+--connection node_1
+COMMIT;
+
+# Confirm that all nodes are identical
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'");
+CALL mtr.add_suppression("Write_rows apply failed");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("no THD for trx");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test
new file mode 100644
index 00000000000..95bc16dd42b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+--send INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+
+--connection node_1
+--reap
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf
new file mode 100644
index 00000000000..62c8214b8f2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf
@@ -0,0 +1 @@
+!include ../galera_3nodes/galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_sr/my.cnf b/mysql-test/suite/galera_3nodes_sr/my.cnf
new file mode 100644
index 00000000000..bb25b95ceea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/my.cnf
@@ -0,0 +1 @@
+!include galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result
new file mode 100644
index 00000000000..ac3813176c9
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (2);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+ERROR 08S01: WSREP has not yet prepared node for application use
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+DROP TABLE t1;
+CALL mtr.add_suppression("replication aborted");
+CALL mtr.add_suppression("WSREP: fragment replication failed: 3");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result
new file mode 100644
index 00000000000..68a8fde0abc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COUNT(*)
+5
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COUNT(*)
+5
+COMMIT;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result
new file mode 100644
index 00000000000..03c7963c6d5
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+0
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1
+COMMIT;
+SELECT * FROM t1;
+f1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result
new file mode 100644
index 00000000000..52544166e29
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result
@@ -0,0 +1,20 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (31),(32),(33);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+0
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+0
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result
new file mode 100644
index 00000000000..9064030aa89
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result
@@ -0,0 +1,256 @@
+SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_last_fragment_commit_before_fragment_removal
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_last_fragment_commit_after_fragment_removal
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_success";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_success
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_after_certify";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_after_certify
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_before_certify";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_before_certify
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result
new file mode 100644
index 00000000000..a0f002ac627
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result
@@ -0,0 +1,100 @@
+SET GLOBAL debug="d,crash_apply_cb_before_append_frag";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_apply_cb_after_append_frag";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result
new file mode 100644
index 00000000000..cddd8918a2a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result
@@ -0,0 +1,177 @@
+SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result
new file mode 100644
index 00000000000..35a96650037
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_on = OFF;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result
new file mode 100644
index 00000000000..7680f0380af
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result
@@ -0,0 +1,15 @@
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+ERROR HY000: Lost connection to MySQL server during query
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result
new file mode 100644
index 00000000000..5ecf1b6ec00
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result
@@ -0,0 +1,62 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("failed to send SR rollback for");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result
new file mode 100644
index 00000000000..eb539eba919
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result
@@ -0,0 +1,25 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+COMMIT;
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result
new file mode 100644
index 00000000000..dcf291bacc7
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result
new file mode 100644
index 00000000000..a849a44832e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result
@@ -0,0 +1,38 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+COUNT(*) = 15
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 15 FROM t1;
+COUNT(*) = 15
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result
new file mode 100644
index 00000000000..7bc36c3d0af
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result
@@ -0,0 +1,44 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+COUNT(*) = 15
+1
+ROLLBACK;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result
new file mode 100644
index 00000000000..8b015c26977
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result
@@ -0,0 +1,31 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+ROLLBACK;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result
new file mode 100644
index 00000000000..285421c4d25
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t2 WRITE;
+INSERT INTO t2 VALUES (1);
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result
new file mode 100644
index 00000000000..0daf6484d04
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result
@@ -0,0 +1,84 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (200);
+INSERT INTO t1 VALUES (201);
+INSERT INTO t1 VALUES (202);
+INSERT INTO t1 VALUES (203);
+INSERT INTO t1 VALUES (204);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (300);
+INSERT INTO t1 VALUES (301);
+INSERT INTO t1 VALUES (302);
+INSERT INTO t1 VALUES (303);
+INSERT INTO t1 VALUES (304);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+wsrep_gcomm_uuid_match
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+wsrep_gcomm_uuid_match
+1
+INSERT INTO t1 VALUES (30);
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (33);
+INSERT INTO t1 VALUES (34);
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test
new file mode 100644
index 00000000000..ea8bed454ca
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test
@@ -0,0 +1,47 @@
+--source include/galera_cluster.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (2);
+--error ER_UNKNOWN_COM_ERROR
+COMMIT;
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
+--source include/wait_condition.inc
+DROP TABLE t1;
+
+CALL mtr.add_suppression("replication aborted");
+CALL mtr.add_suppression("WSREP: fragment replication failed: 3");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test
new file mode 100644
index 00000000000..ab029594f4d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+SELECT COUNT(*) FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COMMIT;
+SELECT COUNT(*) FROM t1;
+
+--connection node_2
+SELECT COUNT(*) FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test
new file mode 100644
index 00000000000..34d8ec55f1a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test
@@ -0,0 +1,80 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the case where the cluster splits 3 ways.
+# The master transitions to a non-prim view and back to prim. Its ongoing
+# should fail to commit.
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+#
+# Isolate node_2 into a separate non-primary component
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+--disable_query_log
+SET WSREP_ON=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SET WSREP_ON=ON;
+--enable_query_log
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+#
+# Confirm that node_1 has no transactions in SR table
+#
+
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+#
+# Restore cluster
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT * FROM t1;
+COMMIT;
+
+--connection node_1
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test
new file mode 100644
index 00000000000..6e5da4bf349
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test
@@ -0,0 +1,30 @@
+#
+# GCF-609 SR: Assertion wsrep_apply_cb on slave after master causes a duplicate key error
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+INSERT INTO t1 VALUES (31),(32),(33);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test
new file mode 100644
index 00000000000..38d95556e48
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test
@@ -0,0 +1,137 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_last_fragment_commit_before_fragment_removal
+#
+
+--connection node_2
+--enable_reconnect
+SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_last_fragment_commit_before_fragment_removal
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_last_fragment_commit_after_fragment_removal
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_last_fragment_commit_after_fragment_removal
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_last_fragment_commit_success
+#
+# Case crash_last_fragment_commit_success is commented out,
+# the changes will be visible on slave due to succesful commit,
+# so the galera_sr_crash_post_check will fail.
+#
+
+# --connection node_2
+# SET GLOBAL debug="d,crash_last_fragment_commit_success";
+# --source suite/galera_3nodes/include/galera_expect_node_crash.inc
+# --source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+# --echo crash_last_fragment_commit_success
+
+# --connection node_2
+# --error 2006,2013
+# COMMIT;
+
+# --source include/start_mysqld.inc
+# --source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_success
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_success";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_success
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_after_certify
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_after_certify";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_after_certify
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_before_certify
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_before_certify";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_before_certify
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test
new file mode 100644
index 00000000000..24a518af9f7
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test
@@ -0,0 +1,49 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_apply_cb_before_append_frag
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_before_append_frag";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc
+
+--connection node_3
+--error 0,2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--sleep 5
+--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc
+
+#
+# crash_apply_cb_after_append_frag
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_after_append_frag";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc
+
+--connection node_3
+--error 0,2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--sleep 5
+--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc
+
+--connection node_1
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test
new file mode 100644
index 00000000000..79948e5a46d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test
@@ -0,0 +1,70 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--enable_reconnect
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_commit_cb_last_fragment_commit_success
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_commit_cb_before_last_fragment_commit
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_apply_cb_after_fragment_removal
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_apply_cb_before_fragment_removal
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test
new file mode 100644
index 00000000000..c585aba78d4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test
@@ -0,0 +1,101 @@
+#
+# GCF-817 SR: master removes SR trx in non-primary view
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--connection node_1a
+# Force node #1 to go non-primary
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+SET SESSION wsrep_on = OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# SR table on master should still contain entries after going non-Prim
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# SR table on slave should eventually clean up entries when master goes non-Prim
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Restore node #1 to primary
+
+--connection node_1a
+#
+# The following sleep is a workaround for issue GCF-861.
+# Normally it's sufficient to make sure that the CC happened
+# by checking that wsrep_cluster_size has shrinked, as above.
+# However that is not always enough, so we sleep a few seconds.
+# See GCF-861 on how to reproduce.
+#
+
+--connection node_1a
+--sleep 6
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--source include/galera_wait_ready.inc
+
+# SR table on master should contain no entries after going back to Prim state
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+--connection node_2
+# And none on slave
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+# SR table is now empty everywhere
+--connection node_1a
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test
new file mode 100644
index 00000000000..95d40803506
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test
@@ -0,0 +1,36 @@
+#
+# GCF-832 SR: wsrep_schema.SR table remains populated on all nodes after crash
+# followed by immediate recovery
+#
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+--connection node_2
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+
+--let $_server_id= `SELECT @@server_id`
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
+--exec echo "wait" > $_expect_file_name
+
+CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+--error 2013
+COMMIT;
+
+--source include/start_mysqld.inc
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--enable_reconnect
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/disabled.def b/mysql-test/suite/galera_3nodes_sr/t/disabled.def
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test
new file mode 100644
index 00000000000..a55109e57e4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test
@@ -0,0 +1,127 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of gmcast.isolate on master during an SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+
+#
+# Trigger gmcast.isolate=1 .
+# The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+
+#
+# Expect that the transaction is cleaned up entirely across the cluster and in all wsrep_schema.SR tables
+#
+
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_3
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+#
+# Restore cluster
+#
+
+--connection node_1a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1a
+--source include/galera_wait_ready.inc
+
+#
+# Confirm that the previous transaction is gone on Node #1 as well
+#
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Confirm that the transaction can be retried
+#
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+CALL mtr.add_suppression("failed to send SR rollback for");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test
new file mode 100644
index 00000000000..ff892aa20a6
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test
@@ -0,0 +1,56 @@
+#
+# This test kills the slave before a Streaming Replication transaction has started
+# and restarts it when the transaction is already in progress. IST should
+# bring the slave up to date so that it can receive the complete transaction.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+COMMIT;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 10 FROM t1;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test
new file mode 100644
index 00000000000..50b8ef0302f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test
@@ -0,0 +1,56 @@
+#
+# This test kills the master while a Streaming Replication transaction is in progress
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/kill_galera.inc
+
+--connection node_3
+# We expect that uncommitted values are no longer present
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# and we can insert them again
+--error 0
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+--source include/start_mysqld.inc
+# --sleep 5
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--sleep 1
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test
new file mode 100644
index 00000000000..7b11dfeddea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test
@@ -0,0 +1,75 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+
+--connection node_2
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+
+--connection node_1
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 15 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test
new file mode 100644
index 00000000000..2e62810cef4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test
@@ -0,0 +1,76 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent even if ROLLBACK
+# is issued on the SR transaction after restart.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+
+--connection node_2
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test
new file mode 100644
index 00000000000..603483a419c
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test
@@ -0,0 +1,56 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+ROLLBACK;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_2
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test
new file mode 100644
index 00000000000..267552afb60
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test
@@ -0,0 +1,71 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# but before a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+
+# Block node #2's applier before table t1's inserts have come into play
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+# Expect that the SR table will get some entries after the restart
+# --let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+# --source include/wait_conditions.inc
+
+# SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+# SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_1
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf
new file mode 100644
index 00000000000..910d945949a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf
@@ -0,0 +1,5 @@
+!include ../galera_3nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;pc.weight=3'
+
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test
new file mode 100644
index 00000000000..82d693eb28d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test
@@ -0,0 +1,169 @@
+#
+# Test the case where the cluster splits 3 ways . The master remains in the
+# primary component and is able to commit its transaction.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+#
+# Begin a separate SR transaction on every node and confirm that each node
+# has SR table entries for every transaction
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (200);
+INSERT INTO t1 VALUES (201);
+INSERT INTO t1 VALUES (202);
+INSERT INTO t1 VALUES (203);
+INSERT INTO t1 VALUES (204);
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 2 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (300);
+INSERT INTO t1 VALUES (301);
+INSERT INTO t1 VALUES (302);
+INSERT INTO t1 VALUES (303);
+INSERT INTO t1 VALUES (304);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+--connection node_1a
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 3 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+#
+# Isolate nodes #2 and #3 into separate non-primary components
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_3a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+
+#
+# Restore cluster
+#
+
+--connection node_2a
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_3a
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--let $node_1_gcomm_uuid = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'`
+
+--connection node_2a
+--source include/wait_condition.inc
+
+--connection node_3a
+--source include/wait_condition.inc
+
+
+#
+# Confirm that the rejoined nodes only have node #1's transaction in their SR tables
+#
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+--disable_query_log
+--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR;
+--enable_query_log
+
+--connection node_3
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+--disable_query_log
+--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR;
+--enable_query_log
+
+#
+# Finalize transaction on node #1
+#
+
+--connection node_1
+INSERT INTO t1 VALUES (30);
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (33);
+INSERT INTO t1 VALUES (34);
+COMMIT;
+
+#
+# Confirm that transaction is replicated correctly and SR tables are empty at the end of the test
+#
+
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+--connection node_2
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+--connection node_3
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+--connection node_3
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file
diff --git a/mysql-test/suite/galera_ee/galera_2nodes.cnf b/mysql-test/suite/galera_ee/galera_2nodes.cnf
new file mode 100644
index 00000000000..0412b5654dd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/galera_2nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_ee/galera_4nodes.cnf b/mysql-test/suite/galera_ee/galera_4nodes.cnf
new file mode 100644
index 00000000000..7b37e62c314
--- /dev/null
+++ b/mysql-test/suite/galera_ee/galera_4nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_4nodes.cnf
diff --git a/mysql-test/suite/galera_ee/my.cnf b/mysql-test/suite/galera_ee/my.cnf
new file mode 100644
index 00000000000..ca163a540d9
--- /dev/null
+++ b/mysql-test/suite/galera_ee/my.cnf
@@ -0,0 +1 @@
+!include galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_ee/r/GCF-329A.result b/mysql-test/suite/galera_ee/r/GCF-329A.result
new file mode 100644
index 00000000000..c429b0b8973
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-329A.result
@@ -0,0 +1,30 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+CALL mtr.add_suppression("Failed to send NBO-end");
+CALL mtr.add_suppression("Failed to acquire total order isolation");
+CALL mtr.add_suppression("Aborting");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'");
diff --git a/mysql-test/suite/galera_ee/r/GCF-329B.result b/mysql-test/suite/galera_ee/r/GCF-329B.result
new file mode 100644
index 00000000000..2a56bd4964a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-329B.result
@@ -0,0 +1,16 @@
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+Killing server ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-360.result b/mysql-test/suite/galera_ee/r/GCF-360.result
new file mode 100644
index 00000000000..7dc9ba37c19
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-360.result
@@ -0,0 +1,416 @@
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
diff --git a/mysql-test/suite/galera_ee/r/GCF-421.result b/mysql-test/suite/galera_ee/r/GCF-421.result
new file mode 100644
index 00000000000..78dab709e32
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-421.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+DROP TABLE t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("TO isolation failed for");
diff --git a/mysql-test/suite/galera_ee/r/GCF-546.result b/mysql-test/suite/galera_ee/r/GCF-546.result
new file mode 100644
index 00000000000..dde91db8422
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-546.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+ERROR 42000: Multiple primary key defined
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+CALL mtr.add_suppression("TO isolation failed");
+CALL mtr.add_suppression("ALTER TABLE isolation failure");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+CALL mtr.add_suppression("Slave SQL: Error");
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-563.result b/mysql-test/suite/galera_ee/r/GCF-563.result
new file mode 100644
index 00000000000..8de6dfd36e7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-563.result
@@ -0,0 +1,52 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP TABLE t2;
+SET GLOBAL wsrep_slave_threads=1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-849.result b/mysql-test/suite/galera_ee/r/GCF-849.result
new file mode 100644
index 00000000000..599d5451f2a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-849.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-854.result b/mysql-test/suite/galera_ee/r/GCF-854.result
new file mode 100644
index 00000000000..0752a169d73
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-854.result
@@ -0,0 +1,16 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (2,2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera-features#117.result b/mysql-test/suite/galera_ee/r/galera-features#117.result
new file mode 100644
index 00000000000..f44269df9f0
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera-features#117.result
@@ -0,0 +1,29 @@
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f2 INTEGER);
+SET GLOBAL wsrep_on=ON;
+CREATE TABLE test.t1 (f1 INTEGER);
+ERROR 42S01: Table 't1' already exists
+SET SESSION wsrep_sync_wait=0;
+SHOW CREATE TABLE test.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+DROP TABLE test.t1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_on=OFF;
+SHOW CREATE TABLE test.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("WSREP: Failed to execute TOI action");
+CALL mtr.add_suppression("WSREP: TO isolation end failed");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result
new file mode 100644
index 00000000000..0090878afd8
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result
@@ -0,0 +1,14 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2);;
+SET SESSION wsrep_sync_wait=0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query");
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result
new file mode 100644
index 00000000000..abc6c3f4148
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result
@@ -0,0 +1,44 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (2);
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3);
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result
new file mode 100644
index 00000000000..1f1d58cdd76
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result
@@ -0,0 +1,22 @@
+SET GLOBAL wsrep_replicate_myisam=ON;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET GLOBAL wsrep_replicate_myisam=FALSE;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result
new file mode 100644
index 00000000000..252fe9d6740
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result
@@ -0,0 +1,30 @@
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO t1 VALUES (1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 7 FROM t1;
+COUNT(*) = 7
+1
+ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+Warnings:
+Warning 1681 'IGNORE' is deprecated and will be removed in a future release.
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result
new file mode 100644
index 00000000000..21e6c51374b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result
@@ -0,0 +1,37 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result
new file mode 100644
index 00000000000..70ef1bc083e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result
@@ -0,0 +1,39 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (2);
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER;
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3,4);
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result
new file mode 100644
index 00000000000..923df0d13cf
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result
new file mode 100644
index 00000000000..eb780a6b264
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result
@@ -0,0 +1,29 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2);;
+SET SESSION wsrep_sync_wait=0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) NOT NULL,
+ PRIMARY KEY (`f1`),
+ KEY `f2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) NOT NULL,
+ PRIMARY KEY (`f1`),
+ KEY `f2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET GLOBAL wsrep_slave_threads = 1;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result
new file mode 100644
index 00000000000..6a15c68c393
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result
@@ -0,0 +1,45 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t3 VALUES (1);
+INSERT INTO t3 VALUES (2);
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t3;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t3;
+COUNT(*) = 2
+1
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result
new file mode 100644
index 00000000000..d66cfd5234c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8;
+INSERT INTO t1 VALUES (1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY HASH (f1)
+PARTITIONS 8 */
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result
new file mode 100644
index 00000000000..22d9dfbc26a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2;
+ERROR 42S01: Table 't2' already exists
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t3;
+COUNT(*) = 1
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t2;
+DROP TABLE t3;
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query.");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result
new file mode 100644
index 00000000000..3ac59facc0f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result
@@ -0,0 +1,38 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result
new file mode 100644
index 00000000000..4c43149e28d
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(1);
+SET SESSION wsrep_osu_method=NBO;
+CREATE INDEX i1 ON t1 (f1);
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED;
+ERROR 23000: Duplicate entry '1' for key 'i1'
+CREATE INDEX i1 ON t1 (f1) LOCK=SHARED;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ KEY `i1` (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ KEY `i1` (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 3 FROM t1;
+COUNT(*) = 3
+1
+DROP INDEX i1 ON t1 LOCK=EXCLUSIVE;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result
new file mode 100644
index 00000000000..8715790653a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+ERROR 42S21: Duplicate column name 'f2'
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER;
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 4
+1
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 4
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result
new file mode 100644
index 00000000000..f45f100b73c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result
@@ -0,0 +1,13 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result
new file mode 100644
index 00000000000..476e35eac95
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t1 WRITE;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t2 VALUES (1);;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t2 VALUES (1);
+CREATE TABLE t3 (t4 INTEGER);
+UNLOCK TABLES;
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result
new file mode 100644
index 00000000000..d17e5c5a777
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result
@@ -0,0 +1,35 @@
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+COUNT(*) = 3
+1
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 1
+1
+ERROR HYN: You are not owner of thread N
+ERROR HYN: You are not owner of thread N
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+INSERT INTO t1 VALUES (1,2);
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result
new file mode 100644
index 00000000000..76ff10dc4d7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+include/assert_grep.inc [Master should report that it can not donate SST]
+include/assert_grep.inc [Slave should report that it could not join]
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Will never receive state");
+CALL mtr.add_suppression("terminated unexpectedly");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result
new file mode 100644
index 00000000000..17d26ed6b8e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result
@@ -0,0 +1,14 @@
+RESET MASTER;
+RESET MASTER;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result
new file mode 100644
index 00000000000..545e8ad3969
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method='NBO';
+CREATE TABLE t2 (f1 INTEGER);
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+RENAME TABLE t1 TO t2;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+DROP TABLE t1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+REPAIR TABLE t1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+CREATE USER u1 IDENTIFIED BY 'p1';
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+DROP USER u1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+SET SESSION wsrep_osu_method=TOI;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression('ALTER TABLE isolation failure');
diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result
new file mode 100644
index 00000000000..361e1f71258
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result
@@ -0,0 +1,44 @@
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+SET SESSION wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_on=ON;
+DROP TABLE t1;
+CREATE TABLE t2 (f1 INTEGER);
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+SET SESSION wsrep_on=OFF;
+Killing server ...
+Starting mysqld
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("inconsistent with group");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result
new file mode 100644
index 00000000000..e3dd272e1d3
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result
@@ -0,0 +1,47 @@
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'A');
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (2, 'B');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+SET SESSION wsrep_on=OFF;
+Killing server ...
+Starting mysqld
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("inconsistent with group");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result
new file mode 100644
index 00000000000..089d0303750
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result
@@ -0,0 +1,5 @@
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result
new file mode 100644
index 00000000000..b513ef9d560
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result
@@ -0,0 +1,7 @@
+SET SESSION wsrep_OSU_method=TOI;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET SESSION wsrep_OSU_method=NBO;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result
new file mode 100644
index 00000000000..3a6ad0f620f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result
new file mode 100644
index 00000000000..50e5f97fdb7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED;;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (1);
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/GCF-329A.test b/mysql-test/suite/galera_ee/t/GCF-329A.test
new file mode 100644
index 00000000000..284aa971b44
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-329A.test
@@ -0,0 +1,42 @@
+#
+# GCF-329: NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+--source include/restart_mysqld.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+--source include/galera_wait_ready.inc
+
+SELECT COUNT(*) = 1 FROM t1;
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SHOW CREATE TABLE t1;
+
+--connection node_1
+--reap
+SHOW CREATE TABLE t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+CALL mtr.add_suppression("Failed to send NBO-end");
+CALL mtr.add_suppression("Failed to acquire total order isolation");
+CALL mtr.add_suppression("Aborting");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'");
diff --git a/mysql-test/suite/galera_ee/t/GCF-329B.test b/mysql-test/suite/galera_ee/t/GCF-329B.test
new file mode 100644
index 00000000000..248301280cc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-329B.test
@@ -0,0 +1,53 @@
+#
+# GCF-329 NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+
+# Enable the master to continue running during the split-brain situation that
+# occurs when the slave is killed
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--source include/kill_galera.inc
+
+--let $galera_connection_name = node_1a
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SET SESSION wsrep_OSU_method=TOI;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-360.cnf b/mysql-test/suite/galera_ee/t/GCF-360.cnf
new file mode 100644
index 00000000000..28e51f87e8e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-360.cnf
@@ -0,0 +1,17 @@
+!include ../galera_4nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.2]
+wsrep_provider_options='base_port=(a)mysqld.2.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.3]
+wsrep_provider_options='base_port=(a)mysqld.3.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.4]
+wsrep_provider_options='base_port=(a)mysqld.4.#galera_port'
+wsrep_ignore_apply_errors=0
diff --git a/mysql-test/suite/galera_ee/t/GCF-360.test b/mysql-test/suite/galera_ee/t/GCF-360.test
new file mode 100644
index 00000000000..e2684135810
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-360.test
@@ -0,0 +1,64 @@
+#
+# GCF-360 Inconsistency voting: node goes non-prim on DDL that fails everywhere
+#
+# We issue 400 DDLs in total to make this test more stressful#
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 100
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+
+--disable_query_log
+while ($count)
+{
+ --connection node_1
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_2
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_3
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_4
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_1
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_2
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_3
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_4
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --dec $count
+}
+
+--enable_query_log
+
+--connection node_1
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_2
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_3
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_4
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
diff --git a/mysql-test/suite/galera_ee/t/GCF-421.test b/mysql-test/suite/galera_ee/t/GCF-421.test
new file mode 100644
index 00000000000..2fca972e88f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-421.test
@@ -0,0 +1,46 @@
+#
+# GCF-421 NB-DDL: Applier thread fails with concurrent DDL
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%ALTER%'
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+DROP TABLE t1;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+DROP TABLE t1;
+
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+
+--connection node_1
+--reap
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+CALL mtr.add_suppression("TO isolation failed for");
+
+--connection node_2
+CALL mtr.add_suppression("TO isolation failed for");
+
+
diff --git a/mysql-test/suite/galera_ee/t/GCF-546.test b/mysql-test/suite/galera_ee/t/GCF-546.test
new file mode 100644
index 00000000000..5c3e0aacc8a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-546.test
@@ -0,0 +1,47 @@
+#
+# GCF-546 NB-DDL: Assertion `thd->wsrep_trx_meta.gtid.seqno == (-1)' failed in wsrep_to_isolation_begin with conflicting DDL on same table
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+
+--connection node_1
+--reap
+
+--connection node_2
+--error ER_MULTIPLE_PRI_KEY
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+SHOW CREATE TABLE t1;
+
+CALL mtr.add_suppression("TO isolation failed");
+CALL mtr.add_suppression("ALTER TABLE isolation failure");
+
+--connection node_1
+SHOW CREATE TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-563.test b/mysql-test/suite/galera_ee/t/GCF-563.test
new file mode 100644
index 00000000000..91a92ce2766
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-563.test
@@ -0,0 +1,63 @@
+#
+# GCF-563 NB-DDL: Assertion `kep->ref_trx(ke.key().prefix()) == ts' failed in do_clean_nbo with two independent DDLs running at the same time
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+SET GLOBAL wsrep_slave_threads=1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-849.test b/mysql-test/suite/galera_ee/t/GCF-849.test
new file mode 100644
index 00000000000..20389cfea64
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-849.test
@@ -0,0 +1,39 @@
+#
+# GCF-849 NB-DDL: Assertion `last_seen_seqno_ < global_seqno_' failed in galera::TrxHandleSlave::unserialize during IST
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Perform an ALTER under NBO
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+# Restart node #2 so that IST happens
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-854.test b/mysql-test/suite/galera_ee/t/GCF-854.test
new file mode 100644
index 00000000000..0f09720457d
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-854.test
@@ -0,0 +1,42 @@
+#
+# GCF-854 NB-DDL: Assertion `0' failed in Table_cache_manager::free_table with IST
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Perform an ALTER under NBO
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (2,2);
+
+# Restart node #2 so that IST happens
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.cnf b/mysql-test/suite/galera_ee/t/galera-features#117.cnf
new file mode 100644
index 00000000000..e20ed7fc08a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera-features#117.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.test b/mysql-test/suite/galera_ee/t/galera-features#117.test
new file mode 100644
index 00000000000..fa4af22a385
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera-features#117.test
@@ -0,0 +1,37 @@
+#
+# This test tests voting for DDLs (TOI events)
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f2 INTEGER);
+SET GLOBAL wsrep_on=ON;
+
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE test.t1 (f1 INTEGER);
+
+--connection node_1
+# wait for node_2 to disappear
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+SHOW CREATE TABLE test.t1;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+DROP TABLE test.t1;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+SET GLOBAL wsrep_on=OFF;
+SHOW CREATE TABLE test.t1;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("WSREP: Failed to execute TOI action");
+CALL mtr.add_suppression("WSREP: TO isolation end failed");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test
new file mode 100644
index 00000000000..adcb0fee2cc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test
@@ -0,0 +1,57 @@
+#
+# Test that wsrep can process two ALTERs on the same table that are conflicting
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--sleep 1
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--error 0,ER_MULTIPLE_PRI_KEY
+--reap
+
+--connection node_1a
+--error 0,ER_MULTIPLE_PRI_KEY
+--reap
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query");
+
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test
new file mode 100644
index 00000000000..fbb7e7e606b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test
@@ -0,0 +1,67 @@
+#
+# Test that ALTER ALGORITHM = COPY works with NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+
+--send ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that unrelated tables can be modified
+INSERT INTO t2 VALUES (2);
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 2 FROM t2;
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test
new file mode 100644
index 00000000000..ef463c96543
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test
@@ -0,0 +1,31 @@
+#
+# Test NBO and ALTER ENGINE
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+SET GLOBAL wsrep_replicate_myisam=ON;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_OSU_method=NBO;
+
+ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+
+--connection node_1
+SET GLOBAL wsrep_replicate_myisam=FALSE;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test
new file mode 100644
index 00000000000..5a65791db1f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test
@@ -0,0 +1,34 @@
+#
+# Test NBO and a duplicate key error
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1);
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+
+--error ER_DUP_ENTRY
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+INSERT INTO t1 VALUES (1);
+
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 7 FROM t1;
+
+--connection node_1
+ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test
new file mode 100644
index 00000000000..dafd8f22dbd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test
@@ -0,0 +1,64 @@
+#
+# Test that ALTER LOCK=EXCLUSIVE works with NBO
+# All DML and SELECTs are expected to be blocked.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--error ER_LOCK_WAIT_TIMEOUT
+SELECT * FROM t1;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+--error ER_LOCK_WAIT_TIMEOUT
+SELECT * FROM t1;
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test
new file mode 100644
index 00000000000..f0dd0c14937
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test
@@ -0,0 +1,67 @@
+#
+# Test that ALTER ALGORITHM = INPLACE works with NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method='NBO';
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that unrelated tables can be modified
+INSERT INTO t2 VALUES (2);
+
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER;
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3,4);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER;
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't1'
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test
new file mode 100644
index 00000000000..417ef75e9bb
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test
@@ -0,0 +1,15 @@
+#
+# Test multi-item ALTER TABLE under NBO
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test
new file mode 100644
index 00000000000..a0975649182
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test
@@ -0,0 +1,57 @@
+#
+# Test that wsrep can process two ALTERs on the same table that are not conflicting
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--sleep 1
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+SET GLOBAL wsrep_slave_threads = 1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test
new file mode 100644
index 00000000000..4799e7b997e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test
@@ -0,0 +1,65 @@
+#
+# Test that wsrep parallel apply can run two unrelated DDLs at the same time
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTERs to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Check that the processing of unrelated events is not affected
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+INSERT INTO t3 VALUES (1);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t3;
+INSERT INTO t3 VALUES (2);
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SELECT COUNT(*) = 2 FROM t3;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SELECT COUNT(*) = 2 FROM t3;
+
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test
new file mode 100644
index 00000000000..46e65038a8c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test
@@ -0,0 +1,29 @@
+#
+# Test that ALTER TABLE works with NBO and partitions
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING;
+INSERT INTO t1 VALUES (2);
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test
new file mode 100644
index 00000000000..a4892dc085b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test
@@ -0,0 +1,31 @@
+#
+# Test ALTER TABLE RENAME TO with NBO
+# All DML and SELECTs are expected to be blocked.
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_TABLE_EXISTS_ERROR
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2;
+
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3;
+
+--connection node_2
+SHOW CREATE TABLE t3;
+SELECT COUNT(*) = 1 FROM t3;
+
+
+SET SESSION wsrep_osu_method=TOI;
+
+DROP TABLE t2;
+DROP TABLE t3;
+
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query.");
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test
new file mode 100644
index 00000000000..2858f3b51f7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test
@@ -0,0 +1,53 @@
+#
+# Test that NBO TOI can coexist with a concurrent, non-conflicting TOI DDL
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTERs to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+--let $wait_condition = SELECT COUNT(*) < 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+SET SESSION wsrep_osu_method=TOI;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test
new file mode 100644
index 00000000000..665ab5137a6
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test
@@ -0,0 +1,34 @@
+#
+# GCF-852 Allow CREATE/DROP INDEX in NBO mode
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_NOT_SUPPORTED_YET
+CREATE INDEX i1 ON t1 (f1);
+
+--error ER_DUP_ENTRY
+CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED;
+
+--error 0
+CREATE INDEX i1 ON t1 (f1) LOCK=SHARED;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 3 FROM t1;
+
+--connection node_1
+DROP INDEX i1 ON t1 LOCK=EXCLUSIVE;
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test
new file mode 100644
index 00000000000..614c133418a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test
@@ -0,0 +1,38 @@
+#
+# Test that DDL errors are handled correctly under NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+
+SET SESSION wsrep_OSU_method=NBO;
+
+--error ER_DUP_FIELDNAME
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_1
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER;
+
+--connection node_2
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER;
+
+--connection node_1
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_2
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test
new file mode 100644
index 00000000000..71205648c8c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test
@@ -0,0 +1,21 @@
+#
+# Test the case where the DDL produces an error on all nodes
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_DUP_ENTRY
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test
new file mode 100644
index 00000000000..dc4fc8e3e35
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test
@@ -0,0 +1,55 @@
+#
+# Test that if a local MDL lock prevents a particular NBO DDL from completing then:
+# * all operations on the local node are blocked
+# * all operations on remote node are allowed
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+LOCK TABLE t1 WRITE;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+
+
+# Confirm that the ALTER is blocked
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Waiting for table metadata lock'
+--source include/wait_condition.inc
+
+# Local DML blocks
+--send INSERT INTO t2 VALUES (1);
+
+# Confirm that the INSERT is blocked
+--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1c
+SET SESSION wsrep_sync_wait = 0;
+
+--let $wait_condition = SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t2 VALUES (1)' AND STATE = 'query end'
+--source include/wait_condition.inc
+
+# Remote operations are allowed
+--connection node_2
+INSERT INTO t2 VALUES (1);
+CREATE TABLE t3 (t4 INTEGER);
+
+--connection node_1a
+UNLOCK TABLES;
+
+--connection node_1
+--reap
+
+--connection node_1b
+--reap
+
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test
new file mode 100644
index 00000000000..e5c5885c8df
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test
@@ -0,0 +1,81 @@
+#
+# Check that non-blocking DDL indeed runs in a separate thread as seen in SHOW PROCESSLIST
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--connection node_2
+# At the start, we only have 2 applier threads, 1 standard applier and
+# 1 aborter and 1 post aborter
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+
+# Set ALTER TABLE to block in the applier thread. wsrep_sync_wait = 0 for the duration, as causal reads will be blocked
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method='NBO';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+# There is a separate applier thread for the ALTER TABLE
+--let $wait_condition = SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+--source include/wait_condition.inc
+
+# The applier thread is blocked
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER';
+
+--let $ddl_applier_id = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'`
+
+# The DDL has not yet been applied
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+# The DDL applier thread can not be killed
+--disable_query_log
+--replace_regex /[0-9]+/N/
+--error ER_KILL_DENIED_ERROR
+--eval KILL CONNECTION $ddl_applier_id;
+
+--replace_regex /[0-9]+/N/
+--error ER_KILL_DENIED_ERROR
+--eval KILL QUERY $ddl_applier_id;
+--enable_query_log
+
+# Then, if we unblock the applier thread
+--disable_query_log
+--eval SET GLOBAL debug = '$debug_orig';
+--enable_query_log
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table';
+SET SESSION wsrep_sync_wait = 7;
+
+# ... the applier thread will terminate
+--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER';
+
+# The alter has now been applied
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+# Both DDL and DML are now possible
+
+INSERT INTO t1 VALUES (1,2);
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--connection node_1
+--reap
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test
new file mode 100644
index 00000000000..38be1674f97
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test
@@ -0,0 +1,89 @@
+#
+# This test attempts to perform SST on slave while DDL is still in progress on master
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--let $MYSQLD2_DATADIR = `SELECT @@datadir`
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Remove grastate.dat from node #2 so that SST is guaranteed
+--remove_file $MYSQLD2_DATADIR/grastate.dat
+
+# Begin an ALTER and block
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Attempt to restart node #2. With grastate.dat removed, SST should be attempted
+
+--connection node_2
+--exec echo "restart" > $_expect_file_name
+--sleep 1
+--exec echo "wait" > $_expect_file_name
+--sleep 5
+
+--connection node_1a
+--let $assert_text= Master should report that it can not donate SST
+--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err
+--let $assert_select= Non-blocking operation in progress, cannot donate SST
+--let $assert_match= Non-blocking operation in progress, cannot donate SST
+--source include/assert_grep.inc
+
+--let $assert_text= Slave should report that it could not join
+--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err
+--let $assert_select= Will never receive state
+--let $assert_match= Will never receive state
+--source include/assert_grep.inc
+
+
+# Restart node_2 again, now with the DDL out of the way
+--connection node_1a
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace';
+
+--connection node_1
+--reap
+
+--connection node_2
+--source include/start_mysqld.inc
+SHOW CREATE TABLE t1;
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+
+--connection node_2
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Will never receive state");
+CALL mtr.add_suppression("terminated unexpectedly");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt
new file mode 100644
index 00000000000..4a13f55f2dc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt
@@ -0,0 +1,2 @@
+--log-slave-updates --log-bin
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test
new file mode 100644
index 00000000000..a8db548688a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test
@@ -0,0 +1,37 @@
+#
+# Test that performing NBO operations on TEMPORARY tables does not cause
+# undue replication or binlogging
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+RESET MASTER;
+
+--connection node_2
+RESET MASTER;
+
+--connection node_1
+CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER);
+
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+
+--connection node_1
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_2
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test
new file mode 100644
index 00000000000..1d80c0614d7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test
@@ -0,0 +1,42 @@
+#
+# Test that various statements not supported under NBO return error
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method='NBO';
+
+--error ER_NOT_SUPPORTED_YET
+CREATE TABLE t2 (f1 INTEGER);
+
+--error ER_NOT_SUPPORTED_YET
+RENAME TABLE t1 TO t2;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER;
+
+--error ER_NOT_SUPPORTED_YET
+DROP TABLE t1;
+
+--error ER_NOT_SUPPORTED_YET
+REPAIR TABLE t1;
+
+--error ER_NOT_SUPPORTED_YET
+CREATE USER u1 IDENTIFIED BY 'p1';
+
+--error ER_NOT_SUPPORTED_YET
+DROP USER u1;
+
+SET SESSION wsrep_osu_method=TOI;
+
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CALL mtr.add_suppression('ALTER TABLE isolation failure');
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf
new file mode 100644
index 00000000000..8f0fa4a30bc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf
@@ -0,0 +1,5 @@
+!include ../galera_4nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
+
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test
new file mode 100644
index 00000000000..1aff71a454e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test
@@ -0,0 +1,87 @@
+#
+# Test the case where a node that dropped prior to an inconsistency vote is able
+# to rejoin via IST after the vote is complete
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Isolate node #4
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+
+# Wait for node #4 to leave cluster
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Introduce inconsistency on node #3
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_on=ON;
+DROP TABLE t1;
+
+# Wait for node #3 to be voted out
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Do some more stuff on the cluster to add to the IST stream
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+# Rejoin node #4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+--source include/galera_wait_ready.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good
+--connection node_4
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+
+# Rejoin node #3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+--source include/kill_galera.inc
+--sleep 1
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+# Confirm node #3 has rejoined
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good and all nodes have identical data
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_3
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_4
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf
new file mode 100644
index 00000000000..b2cba42c0bd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf
@@ -0,0 +1,4 @@
+!include ../galera_4nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test
new file mode 100644
index 00000000000..8dd910c85ee
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test
@@ -0,0 +1,91 @@
+#
+# Test the case where a node that dropped prior to an inconsistency vote is able
+# to rejoin via IST after the vote is complete
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Isolate node #4
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+
+# Wait for node #4 to leave cluster
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'A');
+
+# Introduce inconsistency on node #3
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (2, 'B');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+
+# Wait for node #3 to be voted out
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Rejoin node #4
+--connection node_4
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+--source include/galera_wait_ready.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good
+--connection node_4
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+
+# Rejoin node #3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+--source include/kill_galera.inc
+--sleep 1
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+# Confirm node #3 has rejoined
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good and all nodes have identical data
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+
+--connection node_3
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_4
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test
new file mode 100644
index 00000000000..ddbf77838ce
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test
@@ -0,0 +1,16 @@
+# NB-DDL: Assertion `thd == _current_thd()' failed in check_stack_overrun
+
+--source include/galera_cluster.inc
+
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_OSU_method=NBO;
+
+--connection node_2
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_1
+SET GLOBAL wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt
new file mode 100644
index 00000000000..d9d2edc09af
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt
@@ -0,0 +1 @@
+--wsrep_OSU_method=NBO
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test
new file mode 100644
index 00000000000..33d15f10ec3
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test
@@ -0,0 +1,11 @@
+# NB-DDL: Assertion `thd->wsrep_nbo_ctx' failed in lock_table_names when starting server with --wsrep-OSU-method=NBO
+
+--source include/galera_cluster.inc
+
+SET SESSION wsrep_OSU_method=TOI;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET SESSION wsrep_OSU_method=NBO;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test
new file mode 100644
index 00000000000..f7e2ccbf828
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test
@@ -0,0 +1,38 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+--send INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+--connection node_1
+--reap
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test
new file mode 100644
index 00000000000..d7110d0791a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (1);
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 1 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+
diff --git a/mysql-test/suite/galera_sr/galera_2nodes.cnf b/mysql-test/suite/galera_sr/galera_2nodes.cnf
new file mode 100644
index 00000000000..0412b5654dd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/galera_2nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_sr/my.cnf b/mysql-test/suite/galera_sr/my.cnf
new file mode 100644
index 00000000000..ca163a540d9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/my.cnf
@@ -0,0 +1 @@
+!include galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_sr/r/GCF-1008.result b/mysql-test/suite/galera_sr/r/GCF-1008.result
new file mode 100644
index 00000000000..541ac3cddfb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1008.result
@@ -0,0 +1,70 @@
+connection node_2;
+connection node_1;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+connection node_2;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+connection node_2a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,before_local_commit_monitor_enter';
+connection node_2;
+COMMIT;
+connection node_2b;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_1;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+REPLACE INTO t1 VALUES (1,'y');
+connection node_2b;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_2a;
+SET GLOBAL wsrep_provider_options = 'signal=before_local_commit_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+connection node_2;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+connection node_2a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,before_certify_apply_monitor_enter';
+connection node_2;
+COMMIT;
+connection node_2b;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_1;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+REPLACE INTO t1 VALUES (1,'y');
+connection node_2b;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_2a;
+SET GLOBAL wsrep_provider_options = 'signal=before_certify_apply_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1018.result b/mysql-test/suite/galera_sr/r/GCF-1018.result
new file mode 100644
index 00000000000..fc624aec10d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1018.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) VALUES ('a');
+INSERT INTO t1 (f2) VALUES ('b');
+INSERT INTO t1 (f2) VALUES ('c');
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_certify_apply_monitor_enter';
+SET SESSION wsrep_trx_fragment_size = 64;
+DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+INSERT INTO t1 (f2) VALUES ('d'),('e');
+SET GLOBAL wsrep_provider_options = 'signal=after_certify_apply_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+Got one of the listed errors
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1018B.result b/mysql-test/suite/galera_sr/r/GCF-1018B.result
new file mode 100644
index 00000000000..b1c7efed7a6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1018B.result
@@ -0,0 +1,8 @@
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1043A.result b/mysql-test/suite/galera_sr/r/GCF-1043A.result
new file mode 100644
index 00000000000..cc90461291d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1043A.result
@@ -0,0 +1,21 @@
+connection node_2;
+connection node_1;
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+Running a concurrent test with the following queries:
+DELETE FROM t1
+REPLACE INTO t1 VALUES (1,'y'),(2,'x')
+REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y')
+connection node_1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+connection node_1a;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+connection node_2;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-1043B.result b/mysql-test/suite/galera_sr/r/GCF-1043B.result
new file mode 100644
index 00000000000..c86857b0a3f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1043B.result
@@ -0,0 +1,15 @@
+Running a concurrent test with the following queries:
+DELETE FROM t1
+INSERT INTO t1 VALUES (1,'y'),(2,'x')
+UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-1051.result b/mysql-test/suite/galera_sr/r/GCF-1051.result
new file mode 100644
index 00000000000..56e1f575047
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1051.result
@@ -0,0 +1,46 @@
+connection node_2;
+connection node_1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+connection node_1;
+START TRANSACTION;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+connection node_1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+connection node_2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+connection node_1;
+SET AUTOCOMMIT=OFF;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (2);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+connection node_1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+connection node_2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1060.result b/mysql-test/suite/galera_sr/r/GCF-1060.result
new file mode 100644
index 00000000000..bddb3182e46
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1060.result
@@ -0,0 +1,15 @@
+Running a concurrent test with the following queries:
+TRUNCATE TABLE t1
+INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x')
+INSERT INTO t1 VALUE (4, 'z');
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-437.result b/mysql-test/suite/galera_sr/r/GCF-437.result
new file mode 100644
index 00000000000..5d04022655f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-437.result
@@ -0,0 +1,12 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+ERROR HY000: Writing one row to the row-based binary log failed
+CALL mtr.add_suppression("InnoDB: The total blob data length*");
+CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139");
+CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1");
+CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage");
+DROP TABLE t1;
+DROP table ten;
diff --git a/mysql-test/suite/galera_sr/r/GCF-561.result b/mysql-test/suite/galera_sr/r/GCF-561.result
new file mode 100644
index 00000000000..a3c7ab585e4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-561.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 21S01: Column count doesn't match value count at row 1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-571.result b/mysql-test/suite/galera_sr/r/GCF-571.result
new file mode 100644
index 00000000000..7bf522aae36
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-571.result
@@ -0,0 +1,67 @@
+connection node_2;
+connection node_1;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+SAVEPOINT A;
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1a;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+0
+connection node_1;
+ROLLBACK TO SAVEPOINT A;
+connection node_1a;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+0
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+COUNT(*) = 1
+0
+connection node_2;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+0
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+COUNT(*) = 1
+0
+connection node_1;
+ROLLBACK;
+connection node_1a;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+connection node_2;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+connection node_1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-572.result b/mysql-test/suite/galera_sr/r/GCF-572.result
new file mode 100644
index 00000000000..9a2ff2b294f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-572.result
@@ -0,0 +1,37 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'node1');
+connection node_1a;
+INSERT INTO t1 VALUES (5, 'node2');
+connection node_1;
+INSERT INTO t1 VALUES (5, 'node1');
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+5 node2
+SET SESSION wsrep_trx_fragment_size = 10000;
+START TRANSACTION;
+INSERT INTO t1 VALUE (10, 'node1');
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+connection node_1a;
+INSERT INTO t1 VALUES(15, 'node2');
+connection node_1;
+SELECT * FROM t1;
+f1 f2
+5 node2
+10 node1
+INSERT INTO t1 VALUES(15, 'node1');
+ERROR 23000: Duplicate entry '15' for key 'PRIMARY'
+COMMIT;
+SELECT * FROM t1;
+f1 f2
+5 node2
+10 node1
+15 node2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-574.result b/mysql-test/suite/galera_sr/r/GCF-574.result
new file mode 100644
index 00000000000..bbf817c8c6c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-574.result
@@ -0,0 +1,11 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+wsrep_last_committed_delta
+1
+SELECT COUNT(*) = 10000 FROM t1;
+COUNT(*) = 10000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/GCF-580.result b/mysql-test/suite/galera_sr/r/GCF-580.result
new file mode 100644
index 00000000000..3ee69c6c4b3
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-580.result
@@ -0,0 +1,13 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+last_committed_matches_fragment_count
+1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-585.result b/mysql-test/suite/galera_sr/r/GCF-585.result
new file mode 100644
index 00000000000..6305c4ad31e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-585.result
@@ -0,0 +1,25 @@
+create table t1 (f1 integer primary key) engine=innodb;
+set autocommit=off;
+set session wsrep_trx_fragment_size=1;
+start transaction;
+insert into t1 values (1);
+insert into t1 values (2),(1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+alter table t1 drop primary key;
+drop table t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+update t1 set f1 = 100 where f1 = 10;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+SET SESSION wsrep_trx_fragment_size=1;
+SET SESSION innodb_lock_wait_timeout=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+delete from t1 where f1 > 10;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+delete from t1 where f1 > 10 and f1 < 100;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-597.result b/mysql-test/suite/galera_sr/r/GCF-597.result
new file mode 100644
index 00000000000..e2f35e95e28
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-597.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-620.result b/mysql-test/suite/galera_sr/r/GCF-620.result
new file mode 100644
index 00000000000..ac02d49e086
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-620.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 200;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-623.result b/mysql-test/suite/galera_sr/r/GCF-623.result
new file mode 100644
index 00000000000..790eb1fd89d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-623.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-627.result b/mysql-test/suite/galera_sr/r/GCF-627.result
new file mode 100644
index 00000000000..6c8fad03ed4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-627.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+DROP TABLE t1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (2);
+ERROR 42S02: Table 'test.t1' doesn't exist
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/GCF-845.result b/mysql-test/suite/galera_sr/r/GCF-845.result
new file mode 100644
index 00000000000..3fa6d1bb704
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-845.result
@@ -0,0 +1,14 @@
+CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB;
+SET SESSION AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (161);
+COMMIT;
+DELETE FROM t1 WHERE f1 > 13;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+include/assert_grep.inc [No BF-BF log line found]
diff --git a/mysql-test/suite/galera_sr/r/GCF-851.result b/mysql-test/suite/galera_sr/r/GCF-851.result
new file mode 100644
index 00000000000..6da002ec081
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-851.result
@@ -0,0 +1,24 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+SET SESSION AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+START TRANSACTION;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-867.result b/mysql-test/suite/galera_sr/r/GCF-867.result
new file mode 100644
index 00000000000..0aa19bbd537
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-867.result
@@ -0,0 +1,2 @@
+CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-889.result b/mysql-test/suite/galera_sr/r/GCF-889.result
new file mode 100644
index 00000000000..b5402f105a4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-889.result
@@ -0,0 +1,18 @@
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+DELETE FROM t1 WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Could not execute Delete_rows event on table");
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-900.result b/mysql-test/suite/galera_sr/r/GCF-900.result
new file mode 100644
index 00000000000..e4eab9fbebe
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-900.result
@@ -0,0 +1,13 @@
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 128;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 0);
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (2, 0);
+ALTER TABLE t1 DROP COLUMN f2;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (3, 0);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera-features#56.result b/mysql-test/suite/galera_sr/r/galera-features#56.result
new file mode 100644
index 00000000000..1d04b6f9cee
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera-features#56.result
@@ -0,0 +1,32 @@
+connection node_2;
+connection node_1;
+SET SESSION wsrep_trx_fragment_size = 1;
+connection node_1;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+connection node_2;
+SET GLOBAL wsrep_slave_threads = 4;
+SET SESSION wsrep_trx_fragment_size = 1;
+connection node_1;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+connection node_1a;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+connection node_2;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+connection node_1;
+connection node_1a;
+connection node_2;
+SELECT COUNT(*) = 30000 FROM t1;
+COUNT(*) = 30000
+1
+SELECT COUNT(DISTINCT f1) = 30000 FROM t1;
+COUNT(DISTINCT f1) = 30000
+1
+SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+COUNT(*) = 6
+0
+connection default;
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result
new file mode 100644
index 00000000000..ad274b0cb7f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result
@@ -0,0 +1,448 @@
+SET SESSION wsrep_sync_wait = 0;
+galera_sr_bf_abort_at_commit = 0
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_blob.result b/mysql-test/suite/galera_sr/r/galera_sr_blob.result
new file mode 100644
index 00000000000..c1c51f843c4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_blob.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+wsrep_last_committed_delta
+1
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT LENGTH(f1) = 65535 FROM t1;
+LENGTH(f1) = 65535
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result
new file mode 100644
index 00000000000..35b014979bb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result
@@ -0,0 +1,45 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result
new file mode 100644
index 00000000000..a2c61693c61
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result
@@ -0,0 +1,46 @@
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (16);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result
new file mode 100644
index 00000000000..60cf5ca2633
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t2;
+COUNT(*) = 5
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result
new file mode 100644
index 00000000000..be28892edbb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES(1);;
+COMMIT;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result
new file mode 100644
index 00000000000..ef68cd7ade0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result
new file mode 100644
index 00000000000..d2e8bc592bf
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (5);;
+COMMIT;
+ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result
new file mode 100644
index 00000000000..3f735746d95
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result
new file mode 100644
index 00000000000..ce94576cb95
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result
@@ -0,0 +1,41 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES (1);
+INSERT INTO t1 (f1) VALUES (2);
+INSERT INTO t1 (f1) VALUES (3);
+INSERT INTO t1 (f1) VALUES (4);
+INSERT INTO t1 (f1) VALUES (5);
+INSERT INTO t1 (f1) VALUES (6);
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result
new file mode 100644
index 00000000000..2227336cfad
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+DROP SCHEMA test;
+SELECT COUNT(*) = 0 FROM test.t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+INSERT INTO test.t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO test.t1 VALUES (6, 6);
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result
new file mode 100644
index 00000000000..a3c7ab585e4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 21S01: Column count doesn't match value count at row 1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result
new file mode 100644
index 00000000000..e9edcc9ea34
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result
@@ -0,0 +1,34 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t2 DROP COLUMN f2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+INSERT INTO t1 VALUES (6, 6);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result
new file mode 100644
index 00000000000..5ea1adee877
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
+CREATE UNIQUE INDEX i1 ON t1 (f1(512));
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1024;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result
new file mode 100644
index 00000000000..839a3ef1f71
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result
@@ -0,0 +1,34 @@
+CREATE TABLE grandparent (
+id INT NOT NULL PRIMARY KEY
+) ENGINE=InnoDB;
+CREATE TABLE parent (
+id INT NOT NULL PRIMARY KEY,
+grandparent_id INT,
+FOREIGN KEY (grandparent_id)
+REFERENCES grandparent(id)
+ON UPDATE CASCADE
+) ENGINE=InnoDB;
+CREATE TABLE child (
+id INT NOT NULL PRIMARY KEY,
+grandparent_id INT,
+FOREIGN KEY (grandparent_id)
+REFERENCES parent(grandparent_id)
+ON UPDATE CASCADE
+) ENGINE=InnoDB;
+INSERT INTO grandparent VALUES (1),(2),(3),(4);
+INSERT INTO parent VALUES (1,1), (2,2);
+INSERT INTO child VALUES (1,1), (2,2);
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE grandparent SET id = 5 WHERE id = 1;
+SET SESSION innodb_lock_wait_timeout = 1;
+UPDATE grandparent SET id = 10 WHERE id = 5;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+DELETE FROM child;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+COMMIT;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE child;
+DROP TABLE parent;
+DROP TABLE grandparent;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_gtid.result b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result
new file mode 100644
index 00000000000..be631d1d916
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result
@@ -0,0 +1,57 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES (1);
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_trx_fragment_size=1;
+UPDATE t1 SET f1 = 2;
+connection node_1;
+SET SESSION wsrep_trx_fragment_size=0;
+connection node_2;
+SET SESSION wsrep_trx_fragment_size=0;
+connection node_1;
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000002 <Pos> Gtid_list 1 <End_log_pos> []
+mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001
+mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000002
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY)
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000002 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
+mysqld-bin.000002 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000002 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000002 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000002 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-3
+mysqld-bin.000002 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2
+mysqld-bin.000002 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000002 <Pos> Update_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000002 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+connection node_2;
+SELECT 1 FROM DUAL;
+1
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000003 <Pos> Gtid_list 2 <End_log_pos> []
+mysqld-bin.000003 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000003
+mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
+mysqld-bin.000003 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY)
+mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000003 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
+mysqld-bin.000003 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000003 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000003 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000003 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-3
+mysqld-bin.000003 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2
+mysqld-bin.000003 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000003 <Pos> Update_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000003 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result
new file mode 100644
index 00000000000..2b85b5ec58c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result
@@ -0,0 +1,11 @@
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result
new file mode 100644
index 00000000000..8108e3b60cb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result
@@ -0,0 +1,21 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result
new file mode 100644
index 00000000000..6a274b7f2ae
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result
new file mode 100644
index 00000000000..6a274b7f2ae
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result
new file mode 100644
index 00000000000..4968ba1e0b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result
@@ -0,0 +1,25 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result
new file mode 100644
index 00000000000..f85870ec76a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result
@@ -0,0 +1,17 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing query ...
+ERROR 70100: Query execution was interrupted
+INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result
new file mode 100644
index 00000000000..758f306189c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result
@@ -0,0 +1,39 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t2 WRITE;
+INSERT INTO t2 VALUES (1);
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 15 FROM t1;
+COUNT(*) = 15
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result
new file mode 100644
index 00000000000..f1a445bf7d4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result
@@ -0,0 +1,28 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 50000 FROM t1;
+COUNT(*) > 50000
+1
+ROLLBACK;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result
new file mode 100644
index 00000000000..1310ed318b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result
@@ -0,0 +1,8 @@
+SET SESSION wsrep_trx_fragment_size = 512;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 20000 FROM t1;
+COUNT(*) = 20000
+1
+wsrep_last_committed_diff
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result
new file mode 100644
index 00000000000..b25a8877005
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result
@@ -0,0 +1,9 @@
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_load_data_splitting = TRUE;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 95000 FROM t1;
+COUNT(*) = 95000
+1
+wsrep_last_committed_diff
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result
new file mode 100644
index 00000000000..cb8e84383bc
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result
@@ -0,0 +1,124 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB;
+connection node_2;
+connection node_1;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1a;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+connection node_2;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t3 VALUES (1);
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t4 VALUES (1);
+connection node_1;
+INSERT INTO t1 VALUES (2);
+COMMIT;
+connection node_1a;
+INSERT INTO t2 VALUES (2);
+COMMIT;
+connection node_2;
+INSERT INTO t3 VALUES (2);
+COMMIT;
+connection node_2a;
+INSERT INTO t4 VALUES (2);
+COMMIT;
+connection node_1;
+SELECT COUNT(*) = 2 FROM t4;
+COUNT(*) = 2
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> []
+mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-1
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-3
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+connection node_2;
+SELECT COUNT(*) = 2 FROM t4;
+COUNT(*) = 2
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 <Pos> Gtid_list 2 <End_log_pos> []
+mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000001
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-1
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-3
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2)
+mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result
new file mode 100644
index 00000000000..b44436c9cea
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result
@@ -0,0 +1,28 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 100000 FROM t1;
+COUNT(*) = 100000
+1
+ROLLBACK;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_myisam.result b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result
new file mode 100644
index 00000000000..7d2a84814ba
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET GLOBAL wsrep_replicate_myisam = TRUE;
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT LENGTH(f1) = 65535 FROM t1;
+LENGTH(f1) = 65535
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result
new file mode 100644
index 00000000000..9d47bddb9b4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result
@@ -0,0 +1,40 @@
+Setting SST method to mysqldump ...
+GRANT ALL PRIVILEGES ON *.* TO 'sst';
+SET GLOBAL wsrep_sst_auth = 'sst:';
+SET GLOBAL wsrep_sst_method = 'mysqldump';
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1000;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+UPDATE t1 SET f2 = REPEAT('y', 255);
+Shutting down server ...
+Starting server ...
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+UPDATE t1 SET f2 = REPEAT('z', 255);
+COMMIT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255);
+COUNT(*) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
+SET SESSION wsrep_trx_fragment_size=0;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+DROP USER sst;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found");
+CALL mtr.add_suppression("InnoDB: New log files created");
+CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables");
+CALL mtr.add_suppression("Can't open and lock time zone table");
+CALL mtr.add_suppression("Can't open and lock privilege tables");
+CALL mtr.add_suppression("Info table is not ready to be used");
+CALL mtr.add_suppression("Native table .* has the wrong structure");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result
new file mode 100644
index 00000000000..d63418adabe
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result
@@ -0,0 +1,26 @@
+SET GLOBAL wsrep_slave_threads = 5;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+ROLLBACK;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result
new file mode 100644
index 00000000000..c99dd3df549
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result
new file mode 100644
index 00000000000..8af64da9a19
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+ROLLBACK;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result
new file mode 100644
index 00000000000..d1b8985be82
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK TO SAVEPOINT s1;
+INSERT INTO t1 VALUES (21, 'c');
+INSERT INTO t1 VALUES (22, 'c');
+INSERT INTO t1 VALUES (23, 'c');
+INSERT INTO t1 VALUES (24, 'c');
+INSERT INTO t1 VALUES (25, 'c');
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a';
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 5
+1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result
new file mode 100644
index 00000000000..21e6ef4b057
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result
@@ -0,0 +1,22 @@
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+ALTER TABLE t1 CHANGE f1 f1 INTEGER;
+ALTER TABLE t1 DROP PRIMARY KEY;
+INSERT INTO t1 VALUES (1, 'abc');
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t2 SELECT * FROM t1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO t2 VALUES (1, 'abc');
+INSERT INTO t2 VALUES (2, 'abc');
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_sbr.result b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result
new file mode 100644
index 00000000000..c83db3d5ea6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result
@@ -0,0 +1,16 @@
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION BINLOG_FORMAT='STATEMENT';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result
new file mode 100644
index 00000000000..d3e1739af93
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result
@@ -0,0 +1,20 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT COUNT(*) = 3 FROM t1;
+COUNT(*) = 3
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result
new file mode 100644
index 00000000000..98488dc773e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13);
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (21),(22),(23);
+INSERT INTO t1 VALUES (14),(15),(16);
+COMMIT;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16);
+COUNT(*) = 6
+1
+INSERT INTO t1 VALUES (24),(25),(26);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 12 FROM t1;
+COUNT(*) = 12
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result
new file mode 100644
index 00000000000..b1be41eb762
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result
@@ -0,0 +1,10 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SELECT COUNT(*) = 10000 FROM t1;
+COUNT(*) = 10000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result
new file mode 100644
index 00000000000..29bb71704e2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result
@@ -0,0 +1,198 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+Start of Simple Insert
+INSERT INTO t1 VALUES (4);
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Simple Insert
+
+ROLLBACK;
+Start of Multi-row Update
+UPDATE t1 SET f1 = f1 + 10;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 156 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 197 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 239 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 280 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 322 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Multi-row Update
+
+ROLLBACK;
+Start of Multi-table Update
+UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 82 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 123 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 243
+<ISO TIMESTAMP> server id 1 end_log_pos 164 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 284
+<ISO TIMESTAMP> server id 1 end_log_pos 206 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 247 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 288 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 330 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 371 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 412 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 454 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 495 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 536 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 578 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 619 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 660 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 702 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 743 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 784 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 826 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Multi-table Update
+
+ROLLBACK;
+Start of Savepoint
+INSERT INTO t1 VALUES (1000);
+SAVEPOINT X;
+INSERT INTO t1 VALUES (2000);
+ROLLBACK TO SAVEPOINT X;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 231 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+SAVEPOINT `X`
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 272 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 308 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 391 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+ROLLBACK TO `X`
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Savepoint
+
+ROLLBACK;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result
new file mode 100644
index 00000000000..7527b4ede31
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result
@@ -0,0 +1,101 @@
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+wsrep_local_replays
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'x' WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+wsrep_local_replays
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DELETE FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result
new file mode 100644
index 00000000000..0a81812f7c0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 3;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES (6);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result
new file mode 100644
index 00000000000..ab090e5c2a7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result
@@ -0,0 +1,20 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+connection node_2;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+connection node_1;
+COMMIT;
+SET AUTOCOMMIT=ON;
+UPDATE t1 SET f1 = 2 WHERE f1 = 1;
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result
new file mode 100644
index 00000000000..bbd1f8c9585
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 100 FROM t1;
+COUNT(*) = 100
+1
+DROP TABLE t1;
+DROP TABLE ten;
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result
new file mode 100644
index 00000000000..e1a15b591ef
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 256;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=128';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2;
+Got one of the listed errors
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE ten;
+call mtr.add_suppression('WSREP: SR rollback replication failure.*');
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: SR rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
+call mtr.add_suppression('WSREP: fragment replication failed:');
+call mtr.add_suppression('WSREP: post commit failed for SR rollback');
+call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*');
+call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *');
diff --git a/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result
new file mode 100644
index 00000000000..97c32d7c00e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result
@@ -0,0 +1,22 @@
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_trx_fragment_size = 0;
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result
new file mode 100644
index 00000000000..84564cabe6b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result
@@ -0,0 +1,88 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+INSERT INTO t1 VALUES (2);
+Got one of the listed errors
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+TRUNCATE TABLE t1;
+SET SESSION wsrep_trx_fragment_size = 10;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (2);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+TRUNCATE TABLE t1;
+SET SESSION wsrep_trx_fragment_size = 200;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result
new file mode 100644
index 00000000000..25bc2e11a3e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result
@@ -0,0 +1,65 @@
+connection node_2;
+connection node_1;
+connection node_1;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+connection node_2;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+connection node_1;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+COMMIT;
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (3),(4);
+COMMIT;
+connection node_1;
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> []
+mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
+mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+connection node_2;
+SELECT COUNT(*) = 4 FROM t1;
+COUNT(*) = 4
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 <Pos> Gtid_list 2 <End_log_pos> []
+mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000001
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
+mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(2)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3
+mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4)
+mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+connection node_1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result
new file mode 100644
index 00000000000..efe056b92b4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result
@@ -0,0 +1,17 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SELECT flags FROM wsrep_schema.SR;
+flags
+64
+0
+ROLLBACK;
+INSERT INTO t1 VALUES (3),(4);
+SELECT flags FROM wsrep_schema.SR;
+flags
+64
+0
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result
new file mode 100644
index 00000000000..9e122f554b2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result
@@ -0,0 +1,8 @@
+CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result
new file mode 100644
index 00000000000..65d1a2e1ec0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1);
+SET GLOBAL wsrep_slave_threads = 2;
+SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);;
+INSERT INTO t1 SELECT * FROM t2;;
+INSERT INTO t1 VALUES (6), (7), (8), (9), (10);
+COMMIT;
+Got one of the listed errors
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result
new file mode 100644
index 00000000000..5f50f7fd9a7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result
@@ -0,0 +1,8 @@
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result
new file mode 100644
index 00000000000..fe0761d186d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result
@@ -0,0 +1,752 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result
new file mode 100644
index 00000000000..1cbd9c3d1b7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+ERROR HY000: Lost connection to MySQL server during query
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result
new file mode 100644
index 00000000000..efc86106ab1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result
@@ -0,0 +1,46 @@
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT count(*) > 0 FROM wsrep_schema.SR;
+count(*) > 0
+1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result
new file mode 100644
index 00000000000..a8cf599aacd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK TO SAVEPOINT s1;
+INSERT INTO t1 VALUES (21, 'c');
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result
new file mode 100644
index 00000000000..e92fc207895
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result
@@ -0,0 +1,17 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result
new file mode 100644
index 00000000000..29b17ea07d6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result
@@ -0,0 +1,14 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION binlog_format = STATEMENT;
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result
new file mode 100644
index 00000000000..ca749a45e9a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result
@@ -0,0 +1,27 @@
+connection node_2;
+connection node_1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+connection node_2;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SET AUTOCOMMIT=OFF;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION;
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (5);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ROLLBACK;
+connection node_1;
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result
new file mode 100644
index 00000000000..7eeb83bdc5c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);;
+COMMIT;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+Got one of the listed errors
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result
new file mode 100644
index 00000000000..a959589d241
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result
@@ -0,0 +1,27 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
+SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%';
+COUNT(*) = 13
+1
+INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz');
+COUNT(f2) = 10000
+1
+UPDATE t1 SET f2 = 'abcdefjhk';
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk');
+COUNT(f2) = 10000
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB;
+INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz');
+COUNT(f1) = 1000
+1
+UPDATE t1 SET f1 = 'abcdefjhk';
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
+COUNT(f1) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result
new file mode 100644
index 00000000000..694b51a9260
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result
@@ -0,0 +1,12 @@
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+Killing server ...
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result
new file mode 100644
index 00000000000..1287af618c1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+START TRANSACTION;
+SAVEPOINT a;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT a;
+INSERT INTO t1 values (2);
+COMMIT;
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result
new file mode 100644
index 00000000000..fa79196a910
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t2 (f2 VARCHAR(32));
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2),(1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t2 VALUES ('abc');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+ROLLBACK;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t2;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.inc b/mysql-test/suite/galera_sr/t/GCF-1008.inc
new file mode 100644
index 00000000000..69245b3a91f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1008.inc
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+
+--connection node_2a
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+--send COMMIT
+
+--connection node_2b
+--sleep 1
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+REPLACE INTO t1 VALUES (1,'y');
+
+--connection node_2b
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2a
+--source include/galera_signal_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+--connection node_2
+--reap
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.test b/mysql-test/suite/galera_sr/t/GCF-1008.test
new file mode 100644
index 00000000000..c6926840bd1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1008.test
@@ -0,0 +1,18 @@
+#
+# GCF-1008 SR trx fails to apply because previous trx is not committed yet on applier
+#
+
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/galera_have_debug_sync.inc
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--let $galera_sync_point = before_local_commit_monitor_enter
+--source GCF-1008.inc
+
+--let $galera_sync_point = before_certify_apply_monitor_enter
+--source GCF-1008.inc
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-1018.test b/mysql-test/suite/galera_sr/t/GCF-1018.test
new file mode 100644
index 00000000000..1ff8f81e824
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1018.test
@@ -0,0 +1,38 @@
+#
+# SR: Node hang with one thread waiting in InnoDB
+#
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/galera_have_debug_sync.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) VALUES ('a');
+INSERT INTO t1 (f2) VALUES ('b');
+INSERT INTO t1 (f2) VALUES ('c');
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = after_certify_apply_monitor_enter
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 64;
+--send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;
+
+--connection node_2a
+--source include/galera_wait_sync_point.inc
+
+--connection node_1
+INSERT INTO t1 (f2) VALUES ('d'),('e');
+
+--connection node_2a
+--source include/galera_signal_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+--connection node_2
+--error ER_LOCK_DEADLOCK, ER_QUERY_INTERRUPTED
+--reap
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1018B.test b/mysql-test/suite/galera_sr/t/GCF-1018B.test
new file mode 100644
index 00000000000..f11309080c0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1018B.test
@@ -0,0 +1,40 @@
+#
+# SR: Node hang with one thread waiting in InnoDB
+#
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+
+--let $count = 500
+--disable_query_log
+while ($count)
+{
+ --connection node_1
+ --send INSERT INTO t1 (f2) VALUES ('abc'),('abc');
+
+ --connection node_2
+ --send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;
+
+ --connection node_1
+ --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED
+ --reap
+
+ --connection node_2
+ --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED
+ --reap
+
+ --dec $count
+}
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1043A.test b/mysql-test/suite/galera_sr/t/GCF-1043A.test
new file mode 100644
index 00000000000..c76623742d7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1043A.test
@@ -0,0 +1,13 @@
+#
+# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 1000;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = DELETE FROM t1
+--let $query_node_1a = REPLACE INTO t1 VALUES (1,'y'),(2,'x')
+--let $query_node_2 = REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y')
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-1043B.test b/mysql-test/suite/galera_sr/t/GCF-1043B.test
new file mode 100644
index 00000000000..e3b6b7439ca
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1043B.test
@@ -0,0 +1,13 @@
+#
+# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 1000;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = DELETE FROM t1
+--let $query_node_1a = INSERT INTO t1 VALUES (1,'y'),(2,'x')
+--let $query_node_2 = UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2;
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-1051.test b/mysql-test/suite/galera_sr/t/GCF-1051.test
new file mode 100644
index 00000000000..511cae93784
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1051.test
@@ -0,0 +1,52 @@
+#
+# Test the case where SR is rolled back to savepoint that points to the
+# very beginning of the transaction. This results in regular rollback
+# rather than rollback to savepoint.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+
+#
+# Test 1: regular transaction
+#
+--connection node_1
+START TRANSACTION;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Test 2: AUTOCOMMIT OFF
+#
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (2);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-1060.test b/mysql-test/suite/galera_sr/t/GCF-1060.test
new file mode 100644
index 00000000000..714a5ef9f90
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1060.test
@@ -0,0 +1,9 @@
+--source include/galera_cluster.inc
+
+--let $count = 100;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = TRUNCATE TABLE t1
+--let $query_node_1a = INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x')
+--let $query_node_2 = INSERT INTO t1 VALUE (4, 'z');
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-437.test b/mysql-test/suite/galera_sr/t/GCF-437.test
new file mode 100644
index 00000000000..4101bac7446
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-437.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024;
+
+--error ER_BINLOG_ROW_LOGGING_FAILED
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+CALL mtr.add_suppression("InnoDB: The total blob data length*");
+CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139");
+CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1");
+CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage");
+
+DROP TABLE t1;
+DROP table ten;
diff --git a/mysql-test/suite/galera_sr/t/GCF-561.test b/mysql-test/suite/galera_sr/t/GCF-561.test
new file mode 100644
index 00000000000..e092e194c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-561.test
@@ -0,0 +1,65 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t1 DROP COLUMN f2;
+
+# SR applied before the DDL is no longer visible
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+# Transaction can not continue due to DDL, implicit ROLLBACK
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6, 6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# DDL is now in effect
+--error ER_WRONG_VALUE_COUNT_ON_ROW
+INSERT INTO t1 VALUES (6, 6);
+
+# But it should be possible to reissue the transaction
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-571.test b/mysql-test/suite/galera_sr/t/GCF-571.test
new file mode 100644
index 00000000000..3ad32493a35
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-571.test
@@ -0,0 +1,54 @@
+#
+# GCF-571 ROLLBACK TO SAVEPOINT causes all SR records to be deleted
+#
+
+--source include/galera_cluster.inc
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+SAVEPOINT A;
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+
+--connection node_1
+ROLLBACK TO SAVEPOINT A;
+
+--connection node_1a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+
+--connection node_1
+ROLLBACK;
+
+--connection node_1a
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-572.test b/mysql-test/suite/galera_sr/t/GCF-572.test
new file mode 100644
index 00000000000..8bf57a38fdd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-572.test
@@ -0,0 +1,54 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+#
+# Test 1: statement rollback is not safe
+# (some fragments were already replicated)
+#
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'node1');
+
+--connection node_1a
+INSERT INTO t1 VALUES (5, 'node2');
+
+--connection node_1
+# If we try to INSERT a duplicate key, ER_LOCK_DEADLOCK is the only possible
+# outcome at this point. Notice that ER_DUP_ENTRY is NOT an option here
+# because we were forced to rollback the whole transaction (not just the
+# statement)
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (5, 'node1');
+
+SELECT * FROM t1;
+
+#
+# Test 2: statement rollback is safe
+# (no fragments have been replicated)
+#
+
+SET SESSION wsrep_trx_fragment_size = 10000;
+
+START TRANSACTION;
+INSERT INTO t1 VALUE (10, 'node1');
+SELECT * FROM wsrep_schema.SR;
+
+--connection node_1a
+INSERT INTO t1 VALUES(15, 'node2');
+
+--connection node_1
+SELECT * FROM t1;
+# This time, only the statement is rolled back and we expect ER_DUP_ENTRY.
+--error ER_DUP_ENTRY
+INSERT INTO t1 VALUES(15, 'node1');
+
+COMMIT;
+SELECT * FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-574.test b/mysql-test/suite/galera_sr/t/GCF-574.test
new file mode 100644
index 00000000000..c9d7c405d14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-574.test
@@ -0,0 +1,27 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test CREATE TABLE ... SELECT with Streaming Replication
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) > 1 AS wsrep_last_committed_delta;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/GCF-580.test b/mysql-test/suite/galera_sr/t/GCF-580.test
new file mode 100644
index 00000000000..165b1abcc7a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-580.test
@@ -0,0 +1,27 @@
+#
+# GCF-580 wsrep_last_committed_counter increases twice for every SR fragment
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+
+--let $fragments_count = `SELECT COUNT(*) FROM wsrep_schema.SR`
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = $fragments_count AS last_committed_matches_fragment_count
+--enable_query_log
+
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-585.test b/mysql-test/suite/galera_sr/t/GCF-585.test
new file mode 100644
index 00000000000..ceb7da60df6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-585.test
@@ -0,0 +1,44 @@
+#
+# GCF-585 SR: Assertion `total_length + wsrep_get_fragment_base(thd) == saved_pos' failed in wsrep_write_cache_once after SQL error
+#
+
+--source include/galera_cluster.inc
+
+# Test case #1
+
+create table t1 (f1 integer primary key) engine=innodb;
+set autocommit=off;
+set session wsrep_trx_fragment_size=1;
+start transaction;
+insert into t1 values (1);
+# If we try to INSERT a duplicate key, ER_LOCK_DEADLOCK is the only possible
+# outcome at this point. Notice that ER_DUP_ENTRY is NOT an option here
+# because we were forced to rollback the whole transaction (not just the
+# statement)
+--error ER_LOCK_DEADLOCK
+insert into t1 values (2),(1);
+alter table t1 drop primary key;
+drop table t1;
+
+# Test case #2
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+update t1 set f1 = 100 where f1 = 10;
+
+--connection node_2
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+SET SESSION wsrep_trx_fragment_size=1;
+SET SESSION innodb_lock_wait_timeout=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--error ER_LOCK_DEADLOCK
+delete from t1 where f1 > 10;
+--error ER_LOCK_DEADLOCK
+delete from t1 where f1 > 10 and f1 < 100;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-597.test b/mysql-test/suite/galera_sr/t/GCF-597.test
new file mode 100644
index 00000000000..d3d80ffc4f8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-597.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+ROLLBACK;
+
+DROP TABLE t1;
\ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/GCF-620.test b/mysql-test/suite/galera_sr/t/GCF-620.test
new file mode 100644
index 00000000000..abfba47ee5a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-620.test
@@ -0,0 +1,22 @@
+#
+# GCF-620 SR: ROLLBACK TO SAVEPOINT causes slave crash if wsrep_trx_fragment_size does not fall on boundary
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 200;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-623.test b/mysql-test/suite/galera_sr/t/GCF-623.test
new file mode 100644
index 00000000000..daf9eccfa74
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-623.test
@@ -0,0 +1,31 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
\ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/GCF-627.test b/mysql-test/suite/galera_sr/t/GCF-627.test
new file mode 100644
index 00000000000..7c9faff78a8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-627.test
@@ -0,0 +1,30 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+
+--connection node_2
+DROP TABLE t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--error ER_NO_SUCH_TABLE
+INSERT INTO t1 VALUES (2);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/GCF-845.test b/mysql-test/suite/galera_sr/t/GCF-845.test
new file mode 100644
index 00000000000..9651bde014d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-845.test
@@ -0,0 +1,30 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (161);
+COMMIT;
+DELETE FROM t1 WHERE f1 > 13;
+--disconnect node_1a
+--sleep 2
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
+--let $assert_count = 0
+--let $assert_select = BF-BF X
+--let $assert_text = No BF-BF log line found
+--let $assert_only_after = CURRENT_TEST
+--source include/assert_grep.inc
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-851.test b/mysql-test/suite/galera_sr/t/GCF-851.test
new file mode 100644
index 00000000000..a9b7725c155
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-851.test
@@ -0,0 +1,24 @@
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+SET SESSION AUTOCOMMIT=OFF;
+
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+START TRANSACTION;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM t1;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-867.test b/mysql-test/suite/galera_sr/t/GCF-867.test
new file mode 100644
index 00000000000..73ae43237c9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-867.test
@@ -0,0 +1,42 @@
+#
+# Test many ongoing SR transactions
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
+--disable_query_log
+
+--let $connections = 120
+
+--let $count = $connections
+while ($count)
+{
+--connect $count, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION wsrep_sync_wait = 0;
+--dec $count
+}
+
+
+--let $count = $connections
+while ($count)
+{
+--connection $count
+START TRANSACTION;
+--send_eval INSERT INTO t1 VALUES ($count)
+--dec $count
+}
+
+--let $count = $connections
+while ($count)
+{
+--connection $count
+--reap
+COMMIT;
+--dec $count
+}
+
+--enable_query_log
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-889.test b/mysql-test/suite/galera_sr/t/GCF-889.test
new file mode 100644
index 00000000000..fa2a417d8ce
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-889.test
@@ -0,0 +1,28 @@
+--source include/galera_cluster.inc
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_on = ON;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+DELETE FROM t1 WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+
+INSERT INTO t1 VALUES (1);
+
+SELECT COUNT(*) = 1;
+
+--connection node_2
+SELECT COUNT(*) = 1;
+CALL mtr.add_suppression("Could not execute Delete_rows event on table");
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+
+--connection node_1
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-900.test b/mysql-test/suite/galera_sr/t/GCF-900.test
new file mode 100644
index 00000000000..3f1b53630b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-900.test
@@ -0,0 +1,28 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 128;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 0);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (2, 0);
+
+--connection node_2
+ALTER TABLE t1 DROP COLUMN f2;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connection node_1a
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (3, 0);
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/disabled.def b/mysql-test/suite/galera_sr/t/disabled.def
new file mode 100644
index 00000000000..e5511d18860
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/disabled.def
@@ -0,0 +1,4 @@
+mysql-wsrep-features#29 : binlog_format=STATEMENT not supported with SR
+GCF-574 : CTAS is not supported together with SR
+galera_sr_bf_abort : is worked on with tracker GCF-1015
+galera_sr_sbr : binlog_format=STATEMENT not supported with SR
diff --git a/mysql-test/suite/galera_sr/t/galera-features#56.test b/mysql-test/suite/galera_sr/t/galera-features#56.test
new file mode 100644
index 00000000000..0497952e355
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera-features#56.test
@@ -0,0 +1,55 @@
+##
+## This test tests parallel application of multiple auto-increment insert transactions
+##
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Create a second connection to node1 so that we can run transactions concurrently
+--let $galera_connection_name = node_1a
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+
+--connection node_2
+--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads`
+SET GLOBAL wsrep_slave_threads = 4;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--connection node_1
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_1a
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_2
+--reap
+
+SELECT COUNT(*) = 30000 FROM t1;
+SELECT COUNT(DISTINCT f1) = 30000 FROM t1;
+SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+
+--disable_query_log
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
+--enable_query_log
+
+--connection default
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc
new file mode 100644
index 00000000000..eba84eddb93
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc
@@ -0,0 +1,145 @@
+#
+# Test SR BF abort for all sync points in master side code path
+#
+# The procedure in all test cases is the following:
+# 1) Start SR transaction on node 1, do INSERT + SELECT .. FOR UPDATE
+# 2) Set up sync point on node 1 to block slave thread processing
+# in apply monitor
+# 3) Do write on node 2 which will conflict with SELECT .. FOR UPDATE
+# 4) Set up desired sync point on master side and commit
+# 5) Wait until commit reaches master side sync point, clear sync points
+# and release all sync point waiters
+# 6) COMMIT on node 1 should return deadlock error
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size
+SET AUTOCOMMIT=OFF;
+
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+
+# Set up sync point
+--connection node_1a
+--let galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+# Conflicting insert
+--connection node_2
+
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = $galera_sr_bf_abort_sync_point
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+if ($galera_sr_bf_abort_at_commit)
+{
+ --send COMMIT
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ --send INSERT INTO t1 VALUES (3)
+}
+
+--connection node_1a
+
+--let $cmp = `SELECT STRCMP('apply_monitor_slave_enter_sync', '$galera_sr_bf_abort_sync_point') = -1`
+
+if ($cmp)
+{
+ --let $galera_sync_point = apply_monitor_slave_enter_sync $galera_sr_bf_abort_sync_point
+}
+if (!$cmp)
+{
+ --let $galera_sync_point = $galera_sr_bf_abort_sync_point apply_monitor_slave_enter_sync
+}
+--source include/galera_wait_sync_point.inc
+
+# Let conflicting insert proceed, make sure it hits abort_trx_end and
+# let both threads continue.
+
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end $galera_sr_bf_abort_sync_point
+
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = $galera_sr_bf_abort_sync_point
+--source include/galera_signal_sync_point.inc
+
+# Deadlock should now be retured by node_1
+--connection node_1
+if (!$galera_sr_bf_abort_at_commit)
+{
+ --error ER_LOCK_DEADLOCK
+ --reap
+}
+if ($galera_sr_bf_abort_at_commit)
+{
+ --reap
+}
+
+ROLLBACK;
+
+# Release slave insert
+--connection node_1a
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+# Verify that nodes are consistent
+
+# End result:
+# If the statement which was BF aborted was commit,
+# node_1 must replay the transaction so that the table
+# will have rows 1, 2. If it in turn was INSERT,
+# node_1 must abort the transaction so that only
+# INSERT ... VALUES (2) survives.
+
+--connection node_1
+SELECT * FROM t1;
+if ($galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+--connection node_2
+SELECT * FROM t1;
+if ($galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Delete entery to verify that node is unblocked
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test
new file mode 100644
index 00000000000..711ef69bd14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test
@@ -0,0 +1,48 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--let $wsrep_trx_fragment_size = 1
+
+# Control connection for manipulating sync points on node 1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+--echo galera_sr_bf_abort_at_commit = 0
+--let $galera_sr_bf_abort_at_commit = 0
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_blob.test b/mysql-test/suite/galera_sr/t/galera_sr_blob.test
new file mode 100644
index 00000000000..ed314d09f5a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_blob.test
@@ -0,0 +1,38 @@
+#
+# Test that a single-blob will be replicated using SR if it is sufficiently
+# large.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+# Confirm that exactly one fragment was replicated
+
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = 1 AS wsrep_last_committed_delta;
+--enable_query_log
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT LENGTH(f1) = 65535 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test
new file mode 100644
index 00000000000..7a4e1706402
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test
@@ -0,0 +1,87 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily
+# leave the cluster.
+#
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+
+--sleep 2
+--connection node_2
+
+--error 2013,ER_UNKNOWN_COM_ERROR
+INSERT INTO t1 VALUES (6);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2a
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+
+--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2b
+--source include/galera_wait_ready.inc
+SELECT * FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Repeat transaction to confirm no locks are left from previous transaction
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for");
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test
new file mode 100644
index 00000000000..148539bf5b0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test
@@ -0,0 +1,86 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the slave (node_2) to temporarily
+# leave the cluster.
+#
+
+# Start with a clean slate
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction should be able to continue
+#
+
+--connection node_2
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_1
+# Continue generating events in the transaction
+
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+--source include/galera_wait_ready.inc
+
+# Confirm that the SR table still contains entries from ongoing transaction
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Continue and finalize transaction
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (16);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that transaction was replicated properly
+# and SR table is cleaned up afterwards.
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test
new file mode 100644
index 00000000000..9ec7143d25c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test two concurrent SR-replicated transactions
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+
+--connection node_1
+COMMIT;
+
+--connection node_1a
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 5 FROM t2;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test
new file mode 100644
index 00000000000..dd033fec9c7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# A conflict between a streaming replication fragment and a local transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+# Wait until a streaming replication fragment has arrived
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Attempt a conflicting INSERT. This will block
+--send INSERT INTO t1 VALUES(1);
+
+# Observe the block from a separate connection
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'update';
+--source include/wait_condition.inc
+
+# Commit the remote transaction, causing the local transaction to return an error
+--connection node_1
+COMMIT;
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test
new file mode 100644
index 00000000000..6675321641f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #2 begins a transaction
+# 2. Node #1 begins conflicting transaction that is SR replicated
+# 3. Node #2 attempts to commit, gets a deadlock error, even before #1 has committed
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connection node_1
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test
new file mode 100644
index 00000000000..0ea52290bb6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test
@@ -0,0 +1,46 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #1 begins a transaction that is SR replicated
+# 2. Node #2 begins a conflicting transaction, hangs
+# 3. Node #1 comits
+# 4. Node #2 gets a dup key error
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--send INSERT INTO t1 VALUES (5);
+
+--sleep 1
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test
new file mode 100644
index 00000000000..cb96fae0122
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test
@@ -0,0 +1,44 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #2 begins a transaction
+# 2. Node #1 begins conflicting transaction that is SR replicated
+# 3. Node #1 rolls back
+# 4. Node #2 can not commit because it was BF-aborted even though the SR transaction was rolled back
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test
new file mode 100644
index 00000000000..105d395df6b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test
@@ -0,0 +1,63 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events on the master:
+#
+# 1. Connection #1 begins a SR transaction
+# 2. Connection #2 issues DDL
+# 3. Connection #1 attempts to continue the transaction, gets deadlock
+# 4. Connection #1 retries the transaction and succeeds
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+# SR replication is triggered and rows have been delivered to the slave
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Check that the transaction thus aborted could be reissued
+
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES (1);
+INSERT INTO t1 (f1) VALUES (2);
+INSERT INTO t1 (f1) VALUES (3);
+INSERT INTO t1 (f1) VALUES (4);
+INSERT INTO t1 (f1) VALUES (5);
+INSERT INTO t1 (f1) VALUES (6);
+COMMIT;
+
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test
new file mode 100644
index 00000000000..a3045773387
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test
@@ -0,0 +1,43 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DROP SCHEMA DDL on a concurrent SR transaction
+# Most other DDL tests work on a table level, so this test exercises a
+# different granularity.
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+DROP SCHEMA test;
+
+--error ER_NO_SUCH_TABLE
+SELECT COUNT(*) = 0 FROM test.t1;
+
+--connection node_1
+
+# Transaction can not continue due to DDL
+--error ER_LOCK_DEADLOCK
+INSERT INTO test.t1 VALUES (6, 6);
+
+# DDL is now in effect
+--error ER_NO_SUCH_TABLE
+INSERT INTO test.t1 VALUES (6, 6);
+
+CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test
new file mode 100644
index 00000000000..e092e194c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test
@@ -0,0 +1,65 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t1 DROP COLUMN f2;
+
+# SR applied before the DDL is no longer visible
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+# Transaction can not continue due to DDL, implicit ROLLBACK
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6, 6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# DDL is now in effect
+--error ER_WRONG_VALUE_COUNT_ON_ROW
+INSERT INTO t1 VALUES (6, 6);
+
+# But it should be possible to reissue the transaction
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test
new file mode 100644
index 00000000000..49155017d3f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test
@@ -0,0 +1,53 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of unrelated DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t2 DROP COLUMN f2;
+
+# SR applied before the DDL is still visible
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+
+# Transaction can continue, even after the DDL
+--error 0
+INSERT INTO t1 VALUES (6, 6);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test
new file mode 100644
index 00000000000..45b77a99da1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test
@@ -0,0 +1,59 @@
+#
+# Test the case where a duplicate key error happens in the middle of an SR transaction
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
+CREATE UNIQUE INDEX i1 ON t1 (f1(512));
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1024;
+
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+# Deadlock error instead of dupkey since the transaction is SR and
+# statement rollback is not safe.
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+
+# Confirm that the wsrep_schema table is now empty, as it was a full transaction rollback
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that the transaction can be restarted on either node
+
+--connection node_1
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+COMMIT;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 6 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test
new file mode 100644
index 00000000000..b83deaee244
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test
@@ -0,0 +1,62 @@
+#
+# Test Foreign Key with SR
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE grandparent (
+ id INT NOT NULL PRIMARY KEY
+) ENGINE=InnoDB;
+
+CREATE TABLE parent (
+ id INT NOT NULL PRIMARY KEY,
+ grandparent_id INT,
+ FOREIGN KEY (grandparent_id)
+ REFERENCES grandparent(id)
+ ON UPDATE CASCADE
+) ENGINE=InnoDB;
+
+CREATE TABLE child (
+ id INT NOT NULL PRIMARY KEY,
+ grandparent_id INT,
+ FOREIGN KEY (grandparent_id)
+ REFERENCES parent(grandparent_id)
+ ON UPDATE CASCADE
+) ENGINE=InnoDB;
+
+INSERT INTO grandparent VALUES (1),(2),(3),(4);
+INSERT INTO parent VALUES (1,1), (2,2);
+INSERT INTO child VALUES (1,1), (2,2);
+
+# Start and SR transaction
+
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+UPDATE grandparent SET id = 5 WHERE id = 1;
+
+# No conflicting transactions are allowed to proceed on slave
+
+--connection node_2
+SET SESSION innodb_lock_wait_timeout = 1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+UPDATE grandparent SET id = 10 WHERE id = 5;
+
+--error ER_LOCK_WAIT_TIMEOUT
+DELETE FROM child;
+
+# SR transaction succesffull
+
+--connection node_1
+COMMIT;
+
+--let $diff_servers = 1 2
+--source include/diff_servers.inc
+
+DROP TABLE child;
+DROP TABLE parent;
+DROP TABLE grandparent;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt
new file mode 100644
index 00000000000..6623c33c484
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt
@@ -0,0 +1 @@
+ --log-bin --log-slave-updates --loose-galera-sr-gtid-unique
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid.test b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test
new file mode 100644
index 00000000000..56464ba6f63
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test
@@ -0,0 +1,46 @@
+#
+# Test basic Galera operation
+#
+
+--source include/have_log_bin.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_trx_fragment_size=1;
+UPDATE t1 SET f1 = 2;
+
+#--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size=0;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size=0;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+
+--disable_query_log
+#--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal;
+--enable_query_log
+
+--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 256;
+
+--connection node_2
+# Perform causal wait
+SELECT 1 FROM DUAL;
+--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 256;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test
new file mode 100644
index 00000000000..01481db5a8b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test
@@ -0,0 +1,33 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test large INSERT ... SELECT with SR
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+# Insert 10K rows.
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 99 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test
new file mode 100644
index 00000000000..2730af7f9f4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test
@@ -0,0 +1,52 @@
+#
+# Kill entire cluster during SR while pc.bootstrap is in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+# Bootstrap the cluster from scratch
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf
new file mode 100644
index 00000000000..6422d7541ba
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;pc.recovery=false'
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test
new file mode 100644
index 00000000000..dc99521f40e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test
@@ -0,0 +1,53 @@
+#
+# Kill entire cluster during SR while pc.recovery is NOT in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $start_mysqld_params = "--wsrep-new-cluster"
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--let $start_mysqld_params = ""
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test
new file mode 100644
index 00000000000..e6b1a9c5d27
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test
@@ -0,0 +1,54 @@
+#
+# Kill entire cluster during SR while pc.recovery is in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+# Bootstrap the cluster from scratch
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test
new file mode 100644
index 00000000000..03d09f33fab
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test KILL CONNECTION on a transaction that has already replicated some data via SR
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+# Confirm that the transaction is SR-replicated
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Kill the transaction by killing the entire connection
+
+--connection node_1
+--let $connection_id = `SELECT CONNECTION_ID()`
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--disable_query_log
+--eval KILL CONNECTION $connection_id
+--enable_query_log
+
+# Confirm that the disconnection caused the updates made so far to be removed
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+# Confirm that the transaction can be reissued in its entirety on the slave without a conflict
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1a
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test
new file mode 100644
index 00000000000..c7f10ed570d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test
@@ -0,0 +1,53 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+#
+# Test KILL QUERY on a statement that has already replicated some data via SR
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $connection_id = `SELECT CONNECTION_ID()`
+--send INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;
+
+# Wait for some SR to arrive on the slave.
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT TABLE_ROWS > 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--echo Killing query ...
+--disable_query_log
+--eval KILL QUERY $connection_id
+--enable_query_log
+
+--connection node_1
+--error ER_QUERY_INTERRUPTED
+--reap
+
+# Confirm that the kill caused the updates made so far to be removed
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+# Confirm that the transaction can be reissued in its entirety on the slave without a conflict
+
+INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
+SELECT COUNT(*) = 1000 FROM t1;
+
+--connection node_1a
+SELECT COUNT(*) = 1000 FROM t1;
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf
new file mode 100644
index 00000000000..290d8fe196e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;pc.weight=2'
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test
new file mode 100644
index 00000000000..9abce126d44
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test
@@ -0,0 +1,80 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in
+# progress but before a fragment has already been applied on the slave. It
+# is expected that after the slave restarts, the cluster will continue to
+# be consistent.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Block node #2's applier before table t1's inserts have come into play
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--sleep 2
+
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--sleep 5
+SELECT COUNT(*) = 15 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt
new file mode 100644
index 00000000000..132c6aed246
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=1G --binlog-row-event-max-size=100M
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test
new file mode 100644
index 00000000000..ca54f9e6851
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test
@@ -0,0 +1,58 @@
+#
+# Test the replication and subsequent cleanup of a few, very large fragments
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 50000 FROM t1;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2';
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1';
+
+DROP TABLE ten;
+DROP TABLE t1;
+
+CALL mtr.add_suppression('InnoDB: Resizing redo log from');
+CALL mtr.add_suppression('InnoDB: Starting to delete and rewrite log files');
+CALL mtr.add_suppression('InnoDB: New log files created, LSN=');
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test
new file mode 100644
index 00000000000..b430ace5d69
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test Streaming Replication + LOAD DATA
+#
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 512;
+
+# Create a file for LOAD DATA with 20K entries
+--perl
+open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die;
+foreach my $i (1..20000) {
+ print FILE "$i\n";
+}
+EOF
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Record wsrep_last_committed as it was before LOAD DATA
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+--disable_query_log
+--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1;
+--enable_query_log
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SELECT COUNT(*) = 20000 FROM t1;
+# LOAD-ing 20K rows causes 3 commits to be registered
+--disable_query_log
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 3 AS wsrep_last_committed_diff;
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test
new file mode 100644
index 00000000000..40e63e7c67f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test
@@ -0,0 +1,50 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+#
+# Test Streaming Replication and LOAD DATA splitting operating at the same time
+#
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting`
+
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_load_data_splitting = TRUE;
+
+
+# Create a file for LOAD DATA with 95K entries
+--perl
+open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die;
+foreach my $i (1..95000) {
+ print FILE "$i\n";
+}
+EOF
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Record wsrep_last_committed as it was before LOAD DATA
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+--disable_query_log
+--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1;
+--enable_query_log
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SELECT COUNT(*) = 95000 FROM t1;
+
+# LOAD-ing 95K rows causes 10 'commits' to be registered
+--disable_query_log
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 10 AS wsrep_last_committed_diff;
+--enable_query_log
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig;
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt
new file mode 100644
index 00000000000..03fcb5d040d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt
@@ -0,0 +1 @@
+--log-slave-updates --log-bin
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test
new file mode 100644
index 00000000000..7dfa7850c15
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test
@@ -0,0 +1,70 @@
+#
+# Interleave SR and non-SR transactions and confirm that the binlog is in correct order
+#
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB;
+
+--source include/galera_cluster.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t3 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t4 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (2);
+COMMIT;
+
+--connection node_1a
+INSERT INTO t2 VALUES (2);
+COMMIT;
+
+--connection node_2
+INSERT INTO t3 VALUES (2);
+COMMIT;
+--connection node_2a
+INSERT INTO t4 VALUES (2);
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM t4;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t4;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test
new file mode 100644
index 00000000000..b3bac7df059
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test
@@ -0,0 +1,53 @@
+#
+# Test the replication and subsequent cleanup of a large number of small transaction fragments
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 100000 FROM t1;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2';
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1';
+
+DROP TABLE ten;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_myisam.test b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test
new file mode 100644
index 00000000000..b037f817610
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test
@@ -0,0 +1,29 @@
+#
+# Test that the basic MyISAM replication works even with SR enabled
+# We basically check that the data arrived on the slave and that there
+# were no assertions.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM;
+
+--let $wsrep_replicate_myisam_orig = `SELECT @@wsrep_replicate_myisam`
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET GLOBAL wsrep_replicate_myisam = TRUE;
+
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT LENGTH(f1) = 65535 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig;
+--enable_query_log
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf
new file mode 100644
index 00000000000..574ae28b54a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf
@@ -0,0 +1,11 @@
+!include ../galera_2nodes.cnf
+
+# We do not set mysqldump-related SST options here because doing so on startup
+# causes the first MTR connection to be forefully dropped by Galera, which in turn confuses MTR
+
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true'
+
+[mysqld.2]
+wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test
new file mode 100644
index 00000000000..88249c22f7a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test
@@ -0,0 +1,79 @@
+#
+# Test mysqldump SST on slave if SR transaction is in progress
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+
+--source suite/galera/include/galera_sst_set_mysqldump.inc
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1000;
+START TRANSACTION;
+# Insert 1000 rows
+INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+
+# Update 1000 rows
+UPDATE t1 SET f2 = REPEAT('y', 255);
+
+# Wait for SR replication to kick in
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+# Restart node #2
+
+--connection node_2
+--let $MYSQLD2_DATADIR = `SELECT @@datadir`
+
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+
+# Force SST
+--remove_file $MYSQLD2_DATADIR/grastate.dat
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--echo Starting server ...
+--let $start_mysqld_params = --wsrep_sst_auth=sst:sst --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Check that node #2 is caught up with the SR transaction that is still in progress
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Finalize transaction
+--connection node_1
+UPDATE t1 SET f2 = REPEAT('z', 255);
+COMMIT;
+
+# Confirm proper replication of entire transaction to node #2
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 1000 FROM t1;
+SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255);
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+--connection node_1
+# galera_sst_restore.inc uses DROP USER internally which is incompatible
+# with SR, need to disable SR before that.
+SET SESSION wsrep_trx_fragment_size=0;
+--source suite/galera/include/galera_sst_restore.inc
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test
new file mode 100644
index 00000000000..83a7acbe3e0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test SR with parallel apply
+#
+
+--connection node_2
+--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads`
+SET GLOBAL wsrep_slave_threads = 5;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+--send INSERT INTO t1 (f2) VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+--send INSERT INTO t1 (f2) VALUES (2);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 2;
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+COMMIT;
+
+--connection node_1a
+--reap
+ROLLBACK;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
+--enable_query_log
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test
new file mode 100644
index 00000000000..33a318f8ae3
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test
@@ -0,0 +1,76 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that ROLLBACK works correctly with streaming replication
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK;
+
+#
+# After ROLLBACK, the table on node #2 should be empty
+#
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+#
+# It should be possible to re-insert the values we just rolled back
+#
+
+--connection node_1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 9 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test
new file mode 100644
index 00000000000..c6c443a0828
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test
@@ -0,0 +1,55 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that a SR transaction that was just ROLLBACKed on one node can be
+# run against another node without any conflicts
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK;
+
+#
+# After ROLLBACK, the table on node #2 should be empty
+#
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+#
+# It should be possible to reissue the same transaction against node #2
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test
new file mode 100644
index 00000000000..93ff7a948c4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test
@@ -0,0 +1,51 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that ROLLBACK TO SAVEPOINT works correctly with streaming replication
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 5 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK TO SAVEPOINT s1;
+
+INSERT INTO t1 VALUES (21, 'c');
+INSERT INTO t1 VALUES (22, 'c');
+INSERT INTO t1 VALUES (23, 'c');
+INSERT INTO t1 VALUES (24, 'c');
+INSERT INTO t1 VALUES (25, 'c');
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c';
+
+--connection node_1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test
new file mode 100644
index 00000000000..74350faf5a2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test
@@ -0,0 +1,61 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the case where a statement is rolled back due to an error while Streaming Replication
+# is in effect. We construct an INSERT ... SELECT statement that will fail with a duplicate
+# key error towards the end of the statement, after a portion has already been replicated via SR.
+#
+
+--disable_query_log
+--let $auto_increment_offset_orig = `SELECT @@auto_increment_offset`
+SET GLOBAL auto_increment_offset=1;
+--enable_query_log
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+ALTER TABLE t1 CHANGE f1 f1 INTEGER;
+ALTER TABLE t1 DROP PRIMARY KEY;
+
+# This poison value is used to cause the INSERT ... SELECT below to fail
+INSERT INTO t1 VALUES (1, 'abc');
+
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--error ER_DUP_ENTRY
+INSERT INTO t2 SELECT * FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t2;
+--source include/wait_condition.inc
+
+# Cluster continues to operate after the implicit ROLLBACK;
+--connection node_1
+INSERT INTO t2 VALUES (1, 'abc');
+
+--connection node_2
+INSERT INTO t2 VALUES (2, 'abc');
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_1
+
+--disable_query_log
+--eval SET GLOBAL auto_increment_offset=$auto_increment_offset_orig;
+--enable_query_log
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_sbr.test b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test
new file mode 100644
index 00000000000..a24a520af60
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test
@@ -0,0 +1,31 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that SR does not assert in the presence of statement-based replication events
+#
+
+--connection node_1
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION BINLOG_FORMAT='STATEMENT';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test
new file mode 100644
index 00000000000..721f1dec06d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test
@@ -0,0 +1,45 @@
+#
+# Shut down master (node #2) while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1),(2),(3);
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+# Confirm that SR table on slave is empty
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+--source include/start_mysqld.inc
+
+# SR table on master should be empty too
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that the INSERT can be re-issued
+INSERT INTO t1 VALUES (1),(2),(3);
+
+--connection node_1
+SELECT COUNT(*) = 3 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test
new file mode 100644
index 00000000000..53f6fd7885c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test
@@ -0,0 +1,63 @@
+#
+# Shut down slave (node #2) while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+
+# We start two transactions on the master so that we can commit one while the slave
+# is down and commit the other after the slave has rejoined
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13);
+
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (21),(22),(23);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+# Commit one transaction while the slave is down
+--connection node_1a
+INSERT INTO t1 VALUES (14),(15),(16);
+COMMIT;
+
+# Restart slave
+--connection node_2
+--source include/start_mysqld.inc
+
+# Confirm SR table on slave has entries
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16);
+
+# Commit the second transaction on master after the slave has rejoined
+--connection node_1b
+INSERT INTO t1 VALUES (24),(25),(26);
+COMMIT;
+
+# Confirm that SR table on slave is empty
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 12 FROM t1;
+
+# SR table on master should be empty too
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf
new file mode 100644
index 00000000000..c8e17436e71
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf
@@ -0,0 +1,6 @@
+!include ../galera_2nodes.cnf
+[mysqld.1]
+wsrep_provider_options='base_port=(a)mysqld.1.#galera_port;gcache.size=16K'
+[mysqld.2]
+wsrep_provider_options='base_port=(a)mysqld.2.#galera_port;gcache.size=16K'
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test
new file mode 100644
index 00000000000..403b44286d9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# A simple test with a very low value for gcache.size - 16K
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test
new file mode 100644
index 00000000000..92d29fe4ca2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test
@@ -0,0 +1,49 @@
+#
+# This test dumps the contents of the SR table under various circumstances
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--echo
+--echo Start of Simple Insert
+INSERT INTO t1 VALUES (4);
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Simple Insert
+--echo
+ROLLBACK;
+
+--echo Start of Multi-row Update
+UPDATE t1 SET f1 = f1 + 10;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Multi-row Update
+--echo
+ROLLBACK;
+
+--echo Start of Multi-table Update
+UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Multi-table Update
+--echo
+ROLLBACK;
+
+--echo Start of Savepoint
+INSERT INTO t1 VALUES (1000);
+SAVEPOINT X;
+INSERT INTO t1 VALUES (2000);
+ROLLBACK TO SAVEPOINT X;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Savepoint
+--echo
+ROLLBACK;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test
new file mode 100644
index 00000000000..ca20dcdde24
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test
@@ -0,0 +1,260 @@
+#
+# This test tests the operation of SR transaction replay. If a
+# potentially conflicting remote transaction arrives at
+# just the right time during the commit of a local transaction,
+# the local transaction will be aborted and replayed.
+#
+# This test is divided in two sections:
+# 1) Test the scenario where the last fragment does not have write set
+# payload, just commit flag is replicated
+# 2) Test the scenario where the last fragment has write set payload
+# and commit flag
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+# Control connection for manipulating galera sync points
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+
+#########################################################################
+#
+# 1) Replay without commit fragment write set payload
+#
+#########################################################################
+
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+#
+# Block the commit from node_2
+#
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Issue conflicting UPDATE from node_2 and wait until it hits the
+# apply monitor (but does not apply yet)
+#
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Set a new sync point to block in local monitor on node_1 commit
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Send the commit on node_1
+#
+--connection node_1
+--send COMMIT
+
+#
+# Wait until commit reaches sync point
+#
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release conflicting slave transaction and wait until it has BF
+# aborted pending COMMIT
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release both threads, local thread will now replay
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+#
+# Commit must succeed
+#
+--connection node_1
+--reap
+
+
+#
+# Check the outcome and that wsrep schema SR table is empty
+#
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# wsrep_local_replays has increased by 1
+#
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DELETE FROM t1;
+
+#########################################################################
+#
+# 2) Replay with commit fragment write set payload
+#
+#########################################################################
+
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+#
+# Do first update SR on
+#
+UPDATE t1 SET f2 = 'x' WHERE f1 = 1;
+
+#
+# Disable SR for following statements
+#
+SET SESSION wsrep_trx_fragment_size = 0;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+#
+# Block the commit from node_2
+#
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Issue conflicting UPDATE from node_2 and wait until it hits the
+# apply monitor (but does not apply yet)
+#
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Set a new sync point to block in local monitor on node_1 commit
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Send the commit on node_1
+#
+--connection node_1
+--send COMMIT
+
+#
+# Wait until commit reaches sync point
+#
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release conflicting slave transaction and wait until it has BF
+# aborted pending COMMIT
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release both threads, local thread will now replay
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+#
+# Commit must succeed
+#
+--connection node_1
+--reap
+
+
+#
+# Check the outcome and that wsrep schema SR table is empty
+#
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# wsrep_local_replays has increased by 1
+#
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 2 AS wsrep_local_replays;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DELETE FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test
new file mode 100644
index 00000000000..390d4c73ac1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test
@@ -0,0 +1,47 @@
+#
+# Test wsrep_fragment_unit = statements
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 3;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+
+--connection node_1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+# The table count on the slave should jump from 0
+--connection node_2
+--sleep 1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+# to 3
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+
+# and then to to 6
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 6 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt
new file mode 100644
index 00000000000..0b5f8bf7104
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt
@@ -0,0 +1 @@
+--log-bin-use-v1-row-events=1 --wsrep-trx-fragment-size=1
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test
new file mode 100644
index 00000000000..d3d4d2d0c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test
@@ -0,0 +1,27 @@
+#
+# Test that Galera SR continues to run even with --log-bin-use-v1-row-events=1
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+COMMIT;
+
+SET AUTOCOMMIT=ON;
+UPDATE t1 SET f1 = 2 WHERE f1 = 1;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test
new file mode 100644
index 00000000000..98f6e796ef6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test
@@ -0,0 +1,70 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that SR transaction is cumulatively allowed to grow beyond repl.max_ws_size
+# if individual fragements are below that size
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096';
+
+#
+# Create a transaction larger than repl.max_ws_size
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+
+#
+# We expect that the transaction can proceed successfully
+#
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+# Commit succeeds
+COMMIT;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 100 FROM t1;
+
+#
+# Cleanup
+#
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test
new file mode 100644
index 00000000000..2b9bc4819b8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test
@@ -0,0 +1,62 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that if wsrep_trx_fragment_size > repl.max_ws_size, no SR takes place and
+# the transaction is properly aborted.
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+
+SET SESSION wsrep_trx_fragment_size = 256;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=128';
+
+#
+# Create a transaction larger than repl.max_ws_size
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--error ER_ERROR_DURING_COMMIT,ER_ERROR_ON_WRITE,ER_BINLOG_ROW_LOGGING_FAILED
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2;
+
+#
+# We expect that the transaction can not complete successfully
+#
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--sleep 2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 0 FROM t1;
+
+#
+# Cleanup
+#
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_trx_fragment_size = $wsrep_trx_fragment_size_orig;
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+call mtr.add_suppression('WSREP: SR rollback replication failure.*');
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: SR rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
+call mtr.add_suppression('WSREP: fragment replication failed:');
+call mtr.add_suppression('WSREP: post commit failed for SR rollback');
+call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*');
+call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *');
diff --git a/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test
new file mode 100644
index 00000000000..8b8d7197c1c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test
@@ -0,0 +1,37 @@
+#
+# Test option wsrep_ignore_apply_errors
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Delete row that does not exist using SR transaction
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_trx_fragment_size = 0;
+DROP TABLE t1;
+
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test
new file mode 100644
index 00000000000..45c2b9514df
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test
@@ -0,0 +1,161 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #1 begins a transaction
+# 2. Node #2 performs a conflicting insert
+# 3. Node #1 attempts to SR-replicate a conflicting transaction
+#
+
+# to sync node_1 appliers
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+#
+# processlist is good to see manually that applier reached sync point
+# but is not deterministic in testing, commenting out
+# SHOW PROCESSLIST;
+--connection node_1a
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+#
+# TODO: check here that applier is parked in the sync point
+#
+SELECT COUNT(*) = 0 FROM t1;
+INSERT INTO t1 VALUES (1);
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK,ER_QUERY_INTERRUPTED
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Similar test with BYTES unit
+#
+--connection node_1
+TRUNCATE TABLE t1;
+
+SET SESSION wsrep_trx_fragment_size = 10;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_1a
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+--send INSERT INTO t1 VALUES (1)
+#
+# WHY sleep here?
+# without this sleep, applier would be released with following signal
+# and applier would have chance to BF abort the SR trx.
+# We don't want this to happen, but instead let the SR trx to replicate
+# and notice the certification failure.
+# TODO: sleep is not good, this should be refactored somehow to guarantee
+# correct order for cert failure vs BF abort
+#
+--sleep 2
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+INSERT INTO t1 VALUES (2);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+#
+# One more test with BYTES unit, but now fragment size is adjusted so
+# that second insert should trigger fragment replication.
+# Currently 200 bytes is good choice here, but this may change with
+# future MySQL versions.
+# => If this test fails after some MySQL merge, check if frgament size
+# needs to be tuned to spot at second insert statement.
+#
+--connection node_1
+TRUNCATE TABLE t1;
+
+SET SESSION wsrep_trx_fragment_size = 200;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+
+INSERT INTO t1 VALUES (1);
+
+--send INSERT INTO t1 VALUES (2)
+#
+# WHY sleep here?
+# See above comment, same reason here
+#
+--sleep 2
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt
new file mode 100644
index 00000000000..03fcb5d040d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt
@@ -0,0 +1 @@
+--log-slave-updates --log-bin
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test
new file mode 100644
index 00000000000..06e56d3c9cd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test
@@ -0,0 +1,41 @@
+# SR transactions are not binlogged #136
+
+--source include/galera_cluster.inc
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+COMMIT;
+
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (3),(4);
+COMMIT;
+
+--connection node_1
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+
+--connection node_2
+# Wait for all updates to arrive before dumping binlog
+SELECT COUNT(*) = 4 FROM t1;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test
new file mode 100644
index 00000000000..2e67e730f79
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test
@@ -0,0 +1,25 @@
+# SR: two identical transactions have different value for the WSREP_FLAG_PA_UNSAFE flag
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+
+--connection node_2
+SELECT flags FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+INSERT INTO t1 VALUES (3),(4);
+
+--connection node_2
+SELECT flags FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test
new file mode 100644
index 00000000000..deeb890fa0b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+DROP TABLE t1;
+
+--connection node_2
+--source include/galera_wait_ready.inc
+
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test
new file mode 100644
index 00000000000..5210b9ce99e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test
@@ -0,0 +1,60 @@
+# statement rollback for SR transaction causes slave crash for inconsistency
+
+# We test the following:
+# 1. Create a transaction that is blocked by an SR transaction
+# 2. Force the SR transaction to have a statement rollback
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1);
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 2;
+SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb';
+
+# Begin SR transaction
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+# Begin non-SR transaction that will block waiting for the SR transaction
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--send INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+# Cause the SR transaction to fail with a duplicate key error
+--connection node_1
+--send INSERT INTO t1 SELECT * FROM t2;
+
+# Continue and commit the non-SR transaction.
+--connection node_1a
+--reap
+INSERT INTO t1 VALUES (6), (7), (8), (9), (10);
+COMMIT;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK,ER_DUP_ENTRY
+--reap
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+
+SELECT COUNT(*) = 10 FROM t1;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test
new file mode 100644
index 00000000000..4aaff058b30
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test
@@ -0,0 +1,17 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc
new file mode 100644
index 00000000000..29755ab6c2e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc
@@ -0,0 +1,104 @@
+# --source include/galera_cluster.inc
+# --source include/have_debug_sync.inc
+
+#
+# This test attempts to catch a race condition between autocommit
+# transaction and transaction which is rolling back due to
+# deadlock.
+#
+# Test outline:
+# * Trx 1a makes updates
+# * SR trx 1b writes a row 3, then makes updates
+# * AC trx 1c will attempt to write row 3 and will wait for lock
+# held by 1b
+# * Sync point is set for 1b to delay SR rollback
+# * SR trx 1b makes an update which makes it conflict with trx 1a
+# * Slave shows BF - BF conflict and fails in applying write event
+
+--connection node_1
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+
+# --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+# --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+# --connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--connection node_1a
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+
+
+--connection node_1b
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+
+--connection node_2
+SELECT * FROM t1;
+
+# Will block, waiting for 1b
+--connection node_1c
+SET AUTOCOMMIT=ON;
+--send INSERT INTO t1 VALUES (3, 'c')
+
+--connection node_2
+SELECT * FROM t1;
+
+# Will block, waiting for 1b
+--connection node_1a
+--send UPDATE t1 SET f2 = 'a' WHERE f1 = 2
+
+# Will deadlock
+--connection node_1b
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+--send UPDATE t1 SET f2 = 'b' WHERE f1 = 1
+
+# Wait until 1b hits rollback
+--connection node_1
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+
+# UPDATE 12.06.2016: as of recent wsrep API changes, rollbacking thread no
+# longer queues ROLLBACKs and blocks on ROLLBACK replication before performing
+# the actual rollback. As a result this test is moot as both node_1a and node_1c
+# connections are hanging now until sync point is released. Thus sync point
+# release had to be moved above to release the connections. However it is not
+# impossible that further changes in the code may reintroduce the race, so
+# leaving the test as close to original as possible.
+#
+# --connection node_1a
+# --reap
+# COMMIT;
+#
+# --connection node_1c
+# --reap
+#
+# UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+
+--connection node_1
+SET DEBUG_SYNC = 'now SIGNAL continue';
+
+--connection node_1c
+--reap
+
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+
+--connection node_1a
+--reap
+COMMIT;
+
+--connection node_1b
+--error ER_LOCK_DEADLOCK
+--reap
+
+--connection node_1
+SELECT * FROM t1;
+--connection node_2
+SELECT * FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test
new file mode 100644
index 00000000000..85d501288b0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test
@@ -0,0 +1,41 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+#
+# This test attempts to catch a race condition between autocommit
+# transaction and transaction which is rolling back due to
+# deadlock.
+#
+# Since it is trying to catch a race condition which may not reliably
+# occur, several runs are necessary for certainty. Hence the body of
+# the test was placed into the .inc file and sourced several times below
+#
+# Test outline:
+# * Trx 1a makes updates
+# * SR trx 1b writes a row 3, then makes updates
+# * AC trx 1c will attempt to write row 3 and will wait for lock
+# held by 1b
+# * Sync point is set for 1b to delay SR rollback
+# * SR trx 1b makes an update which makes it conflict with trx 1a
+# * Slave shows BF - BF conflict and fails in applying write event
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test
new file mode 100644
index 00000000000..99bbf505bf6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test
@@ -0,0 +1,63 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily
+# leave the cluster.
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connection node_2a
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_2
+# Changing wsrep_cluster_address causes the server to drop all other
+# connections. Expect CR_SERVER_LOST error
+--error 2013
+INSERT INTO t1 VALUES (6);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2a
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+DROP TABLE t1;
+
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test
new file mode 100644
index 00000000000..8c3dfb8b801
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test
@@ -0,0 +1,86 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running
+# SR transaction. We use SET GLOBAL wsrep_cluster_address = '' to cause the
+# slave (node_2) to temporarily leave the cluster.
+#
+
+# Start with a clean slate
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction should be able to continue
+#
+
+--connection node_2
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_1
+# Continue generating events in the transaction
+
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+--source include/galera_wait_ready.inc
+
+# Confirm that the SR table still contains entries from ongoing transaction
+SELECT count(*) > 0 FROM wsrep_schema.SR;
+
+# Continue and finalize transaction
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that transaction was replicated properly
+# and SR table is cleaned up afterwards.
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test
new file mode 100644
index 00000000000..544109dadee
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test
@@ -0,0 +1,47 @@
+# Assertion `total_length + thd->wsrep_fragment_base == saved_pos' failed in wsrep_write_cache_inc() with ROLLBACK TO SAVEPOINT and SR
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK TO SAVEPOINT s1;
+
+INSERT INTO t1 VALUES (21, 'c');
+
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 6 FROM t1;
+
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test
new file mode 100644
index 00000000000..f9c09391f8f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--sleep 2
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test
new file mode 100644
index 00000000000..2349fe9979f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test
@@ -0,0 +1,23 @@
+#
+# mysql-wsrep-features#29 Unwarranted deadlock error with SR and a single-node cluster
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION binlog_format = STATEMENT;
+
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt
new file mode 100644
index 00000000000..a6ef074a120
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt
@@ -0,0 +1 @@
+--innodb-lock-wait-timeout=1
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test
new file mode 100644
index 00000000000..72c7a7b5e82
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test
@@ -0,0 +1,44 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# mysql-wsrep-features#32 Assertion `meta->gtid.seqno == wsrep_thd_trx_seqno(thd)' failed in wsrep_commit_cb with SR
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+SET AUTOCOMMIT=OFF;
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (6);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+
+--connection node_1
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test
new file mode 100644
index 00000000000..ec78747949f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test
@@ -0,0 +1,46 @@
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Block node #2's applier so that it is able to issue a conflicting INSERT before
+# node #1 INSERTs have been applied on it.
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+SELECT COUNT(*) = 0 FROM t1;
+SET SESSION wsrep_sync_wait = 0;
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+--send INSERT INTO t1 VALUES (1);
+
+--connection node_1
+COMMIT;
+
+--connection node_2a
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+
+--connection node_2
+--error ER_DUP_ENTRY,ER_LOCK_DEADLOCK
+--reap
+ROLLBACK;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test
new file mode 100644
index 00000000000..55210386044
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test
@@ -0,0 +1,63 @@
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# InnoDB FULLTEXT indexes
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+#
+# Fulltext index creation causes the creation of multiple system tables
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
+
+--connection node_2
+SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%';
+
+#
+# Fulltext insertion causes a flurry of updates on those system tables
+#
+
+--connection node_1
+# Insert 10K rows
+INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz');
+
+UPDATE t1 SET f2 = 'abcdefjhk';
+
+--connection node_1
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk');
+
+--connection node_2
+
+DROP TABLE t1;
+
+#
+# Same on a table with no PK
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB;
+
+--connection node_2
+# We insert only 1K rows here, because updates without a PK are very slow
+INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
+
+--connection node_1
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz');
+
+UPDATE t1 SET f1 = 'abcdefjhk';
+
+--connection node_2
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test
new file mode 100644
index 00000000000..cbecf40fadf
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test
@@ -0,0 +1,44 @@
+#
+# mysql-wsrep-features#9 Hang in galera::ReplicatorSMM::cert with Streaming Replication
+# when running the galera_kill_ddl.test test
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+
+# Enable the master to continue running during the split-brain situation that
+# occurs when the slave is killed
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_2
+--source include/kill_galera.inc
+
+--connection node_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/galera_wait_ready.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test
new file mode 100644
index 00000000000..ba82473ae79
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# This test sets a SAVEPOINT at the very beginning
+# of the transaction. When ROLLBACK TO SAVEPOINT is
+# issued, mysql performs a full rollback on SEs that
+# where not part of the transaction.
+# Test that SR transactions are rolled back, and
+# cleaned up properly in this case.
+#
+
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+
+START TRANSACTION;
+
+SAVEPOINT a;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT a;
+
+INSERT INTO t1 values (2);
+COMMIT;
+
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test
new file mode 100644
index 00000000000..c773b310183
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test
@@ -0,0 +1,45 @@
+# mysql-wsrep-features#96 - "Sanity check failed" with SR and statement rolled back due to error
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+--connection node_1
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t2 (f2 VARCHAR(32));
+
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+# This statement causes full transaction rollback
+# rather than just statement rollback, as it is run under SR
+
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (2),(1);
+INSERT INTO t2 VALUES ('abc');
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 1 FROM t2;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM t2;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE t2;
+
+
+
+
diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
index 47fc8e8b840..6ec5a72db25 100644
--- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
@@ -118,7 +118,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -310,7 +310,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -336,7 +336,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a2
test/child a3
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -373,7 +373,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -410,7 +410,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a2
test/child a3
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
diff --git a/mysql-test/suite/innodb/t/galera.skip b/mysql-test/suite/innodb/t/galera.skip
new file mode 100644
index 00000000000..1991ce10cc4
--- /dev/null
+++ b/mysql-test/suite/innodb/t/galera.skip
@@ -0,0 +1,53 @@
+innodb : deadlock, failure in UPDATE IGNORE, lp1372296
+innodb_ctype_ldml : Test contains statements unsafe to replicate in statement-based replication
+innodb-autoinc : deadlock, failure in REPLACE, lp1372296
+innodb_mysql : deadlock due to DDL
+innodb_buffer_pool_load : Test contains statements unsafe to replicate in statement-based replication
+innodb-autoinc-56228 : deadlock, lp1372301
+innodb_lock_wait_timeout_1 : Test contains statements unsafe to replicate in statement-based replication
+innodb-consistent : Test contains statements unsafe to replicate in statement-based replication
+innodb-semi-consistent : Test contains statements unsafe to replicate in statement-based replication
+innodb-index : DDL concurrent with transaction
+innodb-lock : deadlock on INSERT IGNORE, lp1372296
+innodb-status-output : Test performs server restart
+innodb-wl5522 : Test contains statements unsafe to replicate in statement-based replication
+innodb-wl6445 : Test performs server restart
+innodb_bug40360 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug40565 : Galera git bug #137 - Invalid deadlock on UPDATE to NULL without a PK
+innodb_bug42419 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug49164 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug45357 : impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging
+innodb_bug52663 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug59733 : Test contains statements unsafe to replicate in statement-based replication
+innodb_gis : Test contains statements unsafe to replicate in statement-based replication
+innodb_prefix_index_restart_server : crash, lp1372288
+innodb_stats_external_pages : Test contains statements unsafe to replicate in statement-based replication
+innodb-2byte-collation : Unsafe statement written to the binary log
+innodb-change-buffer-recovery : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug53756 : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT
+innodb-alter-autoinc : AUTO_INCREMENT differences
+innodb_bug13635833 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug13867871 : mysql-wsrep#3 - innodb_bug13867871 test fails with wsrep loaded
+innodb_bug14006907 : DDL lock wait timeout
+innodb_bug38231 : Deadlock on UNLOCK TABLE
+innodb_bug-13628249 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-wl6445-1 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-wl6445-2 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb_bug12400341 : Test does not account for applier threads when performing SHOW PROCESSLIST
+innodb-blob : 'Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging'
+innodb_corrupt_bit : 'Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'
+innodb-index-online : ALTER succeeds as it is given a higher priority
+innodb-table-online : ALTER succeeds as it is given a higher priority
+innodb-index-online-purge : ALTER succeeds as it is given a higher priority
+innodb-wl5522-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.
+innodb_stats_table_flag_auto_recalc : Performs multiple restarts in a row which causes '1047: Unknown command' errors
+innodb-lock-inherit-read_commited : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT
+innodb-index-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT
+flush-hang : Unsafe statement written to the binary log
+innodb_deadlock_with_autoinc : Test uses autoinc_lock_mode = 0
+innodb_stats_del_mark : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.
+ibuf_not_empty : InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb_force_recovery : InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-system-table-view : Result depends on whether galera is loaded or not
+innodb-wl5980-linux : Fails because portability_wl5980_linux.zip does not contain wsrep_schema
+innodb-multiple-tablespaces : No changes to SR table are allowed if innodb-force-recovery > 0
\ No newline at end of file
diff --git a/mysql-test/suite/innodb/t/innodb-index-online-fk.test b/mysql-test/suite/innodb/t/innodb-index-online-fk.test
index 5c8954064ce..dd185a9843a 100644
--- a/mysql-test/suite/innodb/t/innodb-index-online-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-index-online-fk.test
@@ -105,7 +105,7 @@ SELECT * FROM information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
# this should succeed, since we disabled the foreign key check
INSERT INTO child VALUES(5,4);
@@ -287,7 +287,7 @@ SET DEBUG_DBUG = @saved_debug_dbug;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
# This should be successful. It will also check any left over
# from previous failed operation (if dictionary entries not cleaned,
@@ -300,7 +300,7 @@ ALGORITHM = INPLACE;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
@@ -317,7 +317,7 @@ ALGORITHM = INPLACE;
SELECT * from information_schema.INNODB_SYS_FOREIGN;
SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
@@ -333,7 +333,7 @@ ALGORITHM = INPLACE;
SELECT * from information_schema.INNODB_SYS_FOREIGN;
SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
diff --git a/packaging/deb-in/CMakeLists.txt b/packaging/deb-in/CMakeLists.txt
new file mode 100644
index 00000000000..aa14eb42425
--- /dev/null
+++ b/packaging/deb-in/CMakeLists.txt
@@ -0,0 +1,357 @@
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ RETURN()
+ENDIF()
+IF (NOT DEFINED DEB_CODENAME)
+ execute_process(
+ COMMAND lsb_release -cs
+ OUTPUT_VARIABLE DEB_CODENAME
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ SET (DEB_CODENAME ${DEB_CODENAME} CACHE STRING "")
+ENDIF()
+IF (DEFINED WITH_NDBCLUSTER_STORAGE_ENGINE)
+ SET (DEB_BASE_PRODUCT "cluster-")
+ SET (DEB_BASE_PRODUCTC "Cluster ")
+ SET (DEB_BASE_VERSION ${NDBVERSION})
+ SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-community-server, mysql-commercial-server")
+ SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-community-client, mysql-commercial-client")
+ELSE()
+ SET (DEB_BASE_PRODUCT "")
+ SET (DEB_BASE_PRODUCTC "")
+ SET (DEB_BASE_VERSION ${VERSION})
+ SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-cluster-community-server, mysql-cluster-commercial-server")
+ SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-cluster-community-client, mysql-cluster-commercial-client")
+ENDIF()
+
+SET (DEB_BASE_VERSION "${DEB_BASE_VERSION}-${WSREP_VERSION}")
+
+# Commercial or community
+IF (DEB_PRODUCT STREQUAL "commercial")
+ message (FATAL_ERROR "mysql-wsrep is GPL only, no commercial builds")
+ SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Commercial Server ${MYSQL_BASE_VERSION}")
+ SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}commercial")
+ SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Commercial")
+ SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}community")
+ SET (DEB_LICENSENAME "Advanced")
+ SET (DEB_INSTALL_LICENSEFILE "LICENSE.mysql")
+ SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+commercial.1")
+ SET (DEB_PLUGIN_SETPERMISSION "")
+ SET (DEB_MAN_SETPERMISSION "")
+ # List of plugins that are only in commercial packages
+ # Plugins that are in both community and commercial should NOT be added here
+ SET (DEB_INCLUDE_BINARIES_EXTRA
+"
+debian/extra/audit_log-plugin
+debian/extra/authentication_pam-plugin
+debian/extra/firewall-plugin
+debian/extra/openssl_udf-plugin
+debian/extra/thread_pool-plugin
+")
+ SET (DEB_INSTALL_SERVER_PLUGINS
+"
+usr/lib/mysql/plugin/audit_log.so
+usr/lib/mysql/plugin/authentication_pam.so
+usr/lib/mysql/plugin/openssl_udf.so
+usr/lib/mysql/plugin/thread_pool.so
+usr/lib/mysql/plugin/firewall.so
+usr/lib/mysql/plugin/debug/audit_log.so
+usr/lib/mysql/plugin/debug/authentication_pam.so
+usr/lib/mysql/plugin/debug/keyring_okv.so
+usr/lib/mysql/plugin/debug/openssl_udf.so
+usr/lib/mysql/plugin/debug/thread_pool.so
+usr/lib/mysql/plugin/debug/firewall.so
+")
+ SET (DEB_REMOVEPATTERN "gpl.in")
+ELSE()
+ SET (DEB_PRODUCT "${DEB_BASE_PRODUCT}community")
+ SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Server ${MYSQL_BASE_VERSION}")
+ SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}community")
+ SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Community")
+ SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}commercial")
+ SET (DEB_LICENSENAME "GPL")
+ SET (DEB_INSTALL_LICENSEFILE "COPYING")
+ SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+1")
+ SET (DEB_REMOVEPATTERN "com.in")
+ SET (DEB_PLUGIN_SETPERMISSION "usr/bin/mysql_setpermission")
+ SET (DEB_MAN_SETPERMISSION "usr/share/man/man1/mysql_setpermission.1")
+ENDIF()
+
+# mysql-wsrep !
+SET (DEB_PRODUCTNAME "wsrep")
+SET (DEB_PRODUCTNAMEC "Wsrep")
+SET (DEB_PRODUCTSERIES "-5.6")
+SET (DEB_WSREP_README "README-wsrep")
+
+
+SET (FILES_STARTUP_SYSV
+"
+etc/init.d/mysql
+usr/bin/mysqld_safe
+")
+SET (FILES_STARTUP_UPSTART
+"
+Not Yet Implememted: Upstart File List
+")
+
+# Platform specifics. The differences are generally only distro version
+# and whether or not Systemd and/or apparmor are available
+IF (DEB_CODENAME STREQUAL "wheezy")
+ SET (DEB_PLATFORMRELEASE "debian7")
+ # Following the Oracle example, we package for Debian 7
+ # using only SysV init and no Apparmor.
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "jessie")
+ SET (DEB_PLATFORMRELEASE "debian8")
+ # Improving on Oracle, we would prefer to package for Debian 8
+ # using both SysV init and Systemd, but still no Apparmor.
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_SYSTEMD_SERVICE_NAME "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "")
+ # Debian 8 comes with both SysV init and Systemd,
+ # but "scripts/CMakeLists.txt" enforces an either-or.
+ SET (DEB_STARTUP "SYSV")
+ # For now, we go with Systemd only.
+ELSEIF(DEB_CODENAME STREQUAL "stretch")
+ SET (DEB_PLATFORMRELEASE "debian9")
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_INIT_APPARMOR "")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "precise")
+ SET (DEB_PLATFORMRELEASE "ubuntu12.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "trusty")
+ SET (DEB_PLATFORMRELEASE "ubuntu14.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "wily")
+ SET (DEB_PLATFORMRELEASE "ubuntu15.10")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-community-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "mysql")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_SERVICE_SERVER_EXECPOST
+ "ExecStartPost=/usr/share/mysql/mysql-systemd-start post")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSTEMD")
+ELSEIF(DEB_CODENAME STREQUAL "xenial")
+ SET (DEB_PLATFORMRELEASE "ubuntu16.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "yakkety")
+ SET (DEB_PLATFORMRELEASE "ubuntu16.10")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "mysql")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_SERVICE_SERVER_EXECPOST
+ "ExecStartPost=/usr/share/mysql/mysql-systemd-start post")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSTEMD")
+ELSEIF(DEB_CODENAME STREQUAL "zesty")
+ SET (DEB_PLATFORMRELEASE "ubuntu17.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ELSE()
+ MESSAGE(STATUS
+ "Skipping deb packaging on unsupported platform ${DEB_CODENAME}.")
+ RETURN()
+ENDIF()
+
+# All files are configured and copied to the debian/ directory, which is used
+# by debuild to make the packages
+# 5.7.11 builds out-of-source. Hack: have duplicate debian/
+SET (DEB_ROOT ${CMAKE_SOURCE_DIR}/packaging/deb-in)
+FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/debian)
+FILE(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/debian)
+FILE(GLOB_RECURSE SOURCEFILES RELATIVE "${DEB_ROOT}" "${DEB_ROOT}/*")
+# Skip the copyright file from the "other" product type
+LIST(REMOVE_ITEM SOURCEFILES "copyright.${DEB_REMOVEPATTERN}")
+LIST(REMOVE_ITEM SOURCEFILES "CMakeLists.txt")
+# Combine the list of all startup files to be included,
+# skip Debian magical init files unless needed
+IF(DEB_PRODUCTNAME STREQUAL "wsrep")
+ SET(COMMON_WSREP_CONFLICTS "mysql-common (>= 5.7)")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.install.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.dirs.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postinst.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postrm.in")
+ENDIF()
+IF(DEB_STARTUP MATCHES ".*SYSV.*")
+ SET (DEB_FILES_STARTUP ${FILES_STARTUP_SYSV})
+ELSE()
+ LIST(REMOVE_ITEM SOURCEFILES
+ "mysql-packagesource-server-SERIES.mysql.init.in")
+ENDIF()
+IF(DEB_STARTUP MATCHES ".*SYSTEMD.*")
+ SET (DEB_FILES_STARTUP
+ ${DEB_FILES_STARTUP}
+ ${FILES_STARTUP_SYSTEMD})
+ELSE()
+ LIST(REMOVE_ITEM SOURCEFILES
+ "mysql-packagesource-server-SERIES.mysql.service.in")
+ENDIF()
+# Don't install systemd file on systems without systemd
+IF(DEB_INSTALL_SERVER_SYSTEMD STREQUAL "")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-packagesource-server.mysql.service.in")
+ENDIF()
+
+FOREACH (SOURCEFILE ${SOURCEFILES})
+ STRING(REGEX REPLACE "-packagesource-" "-${DEB_PRODUCTNAME}-"
+ TMPFILE ${SOURCEFILE})
+ STRING(REGEX REPLACE "-SERIES" "${DEB_PRODUCTSERIES}" TMPFILE ${TMPFILE})
+ # Strip away the input file endings from the destination filenames
+ STRING(REGEX REPLACE ".in$" "" TMPFILE ${TMPFILE})
+ STRING(REGEX REPLACE ".gpl$" "" TMPFILE ${TMPFILE})
+ STRING(REGEX REPLACE ".com$" "" DESTFILE ${TMPFILE})
+ CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}"
+ "${CMAKE_BINARY_DIR}/debian/${DESTFILE}" @ONLY)
+ CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}"
+ "${CMAKE_SOURCE_DIR}/debian/${DESTFILE}" @ONLY)
+ENDFOREACH()
+EXECUTE_PROCESS(
+ COMMAND chmod +x ${CMAKE_BINARY_DIR}/debian/rules
+)
+IF(DEB_PRODUCTNAME STREQUAL "wsrep")
+FILE(APPEND "${CMAKE_BINARY_DIR}/debian/control" "
+Package: mysql-common
+Architecture: any
+Pre-depends: debconf (>= 0.2.17),
+ \${misc:Pre-Depends}
+Multi-Arch: foreign
+Depends: \${misc:Depends},
+ \${shlibs:Depends},
+ mysql-wsrep-common
+Description: MySQL Common
+ The MySQL(TM) software delivers a very fast, multi-threaded, multi-user,
+ and robust SQL (Structured Query Language) database server. MySQL Server
+ is intended for mission-critical, heavy-load production systems as well
+ as for embedding into mass-deployed software. MySQL is a trademark of
+ Oracle. This package contains common files needed by MySQL client
+ library and the MySQL database server.
+ This package is a dummy replacement for the case when using mysql WSREP
+ implementation to satisfy dependencies of other packages
+ like libmysqlclient18. It depends on any mysql-wsrep-common
+")
+ENDIF()
diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc
index 428bcc5dcfc..ab871e81ed6 100644
--- a/plugin/wsrep_info/plugin.cc
+++ b/plugin/wsrep_info/plugin.cc
@@ -202,9 +202,11 @@ static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond)
->store(view.state_id.seqno, 0);
table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0);
+#ifdef OLD_MARIADB
const char *gap= (view.state_gap == true) ? "YES" : "NO";
table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap),
system_charset_info);
+#endif
table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0);
if (schema_table_store_record(thd, table))
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 5797bdc68d7..5f09ac3c235 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -265,7 +265,16 @@ wsrep_recover_position() {
wsrep_start_position_opt="--wsrep_start_position=$start_pos"
fi
- [ $ret -eq 0 ] && rm $wr_logfile
+ if [ $ret -eq 0 ] ; then
+ local wr_logfile_permanent="$DATADIR/wsrep_recovery.ok"
+ else
+ local wr_logfile_permanent="$DATADIR/wsrep_recovery.fail"
+ fi
+ touch $wr_logfile_permanent
+ [ "$euid" = "0" ] && chown $user $wr_logfile_permanent
+ chmod 600 $wr_logfile_permanent
+ cat "$wr_logfile" >> $wr_logfile_permanent
+ rm -f "$wr_logfile"
return $ret
}
diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh
index faa3f10639b..10663216ca5 100644
--- a/scripts/wsrep_sst_mysqldump.sh
+++ b/scripts/wsrep_sst_mysqldump.sh
@@ -25,6 +25,7 @@ EINVAL=22
local_ip()
{
[ "$1" = "127.0.0.1" ] && return 0
+ [ "$1" = "127.0.0.2" ] && return 0
[ "$1" = "localhost" ] && return 0
[ "$1" = "[::1]" ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0
diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh
index 2de384806b2..485ee9c2dd2 100644
--- a/scripts/wsrep_sst_xtrabackup-v2.sh
+++ b/scripts/wsrep_sst_xtrabackup-v2.sh
@@ -647,7 +647,7 @@ wait_for_listen()
local HOST=$1
local PORT=$2
local MODULE=$3
- local LSOF_OUT
+ #local LSOF_OUT
for i in {1..300}
do
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index e3eac1963dc..538af496739 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -16,21 +16,28 @@
IF(WITH_WSREP AND NOT EMBEDDED_LIBRARY)
- SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep)
SET(WSREP_SOURCES
+ wsrep_client_service.cc
+ wsrep_high_priority_service.cc
+ wsrep_server_service.cc
+ wsrep_storage_service.cc
+ wsrep_server_state.cc
+ wsrep_utils.cc
+ wsrep_xid.cc
wsrep_check_opts.cc
- wsrep_hton.cc
- wsrep_mysqld.cc
+ wsrep_mysqld.cc
wsrep_notify.cc
wsrep_sst.cc
- wsrep_utils.cc
wsrep_var.cc
wsrep_binlog.cc
wsrep_applier.cc
wsrep_thd.cc
- wsrep_xid.cc
+ wsrep_thd_pool.cc
+ wsrep_schema.cc
+ wsrep_plugin.cc
+ service_wsrep.cc
)
- SET(WSREP_LIB wsrep)
+ SET(WSREP_LIB wsrep-lib wsrep_api_v26)
ELSE()
SET(WSREP_SOURCES wsrep_dummy.cc)
ENDIF()
@@ -42,7 +49,6 @@ ${PCRE_INCLUDES}
${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/sql
-${WSREP_INCLUDES}
)
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index a6803982171..4cb703f51ca 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -32,7 +32,10 @@
#include "event_db_repository.h"
#include "sp_head.h"
#include "sql_show.h" // append_definer, append_identifier
-
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#include "wsrep_trans_observer.h"
+#endif /* WITH_WSREP */
/**
@addtogroup Event_Scheduler
@{
@@ -1343,6 +1346,10 @@ Event_job_data::execute(THD *thd, bool drop)
thd->reset_for_next_command();
+#ifdef WITH_WSREP
+ wsrep_open(thd);
+ wsrep_before_command(thd);
+#endif /* WITH_WSREP */
/*
MySQL parser currently assumes that current database is either
present in THD or all names in all statements are fully specified.
@@ -1517,6 +1524,10 @@ Event_job_data::execute(THD *thd, bool drop)
if (save_sctx)
event_sctx.restore_security_context(thd, save_sctx);
#endif
+#ifdef WITH_WSREP
+ wsrep_after_command_ignore_result(thd);
+ wsrep_close(thd);
+#endif /* WITH_WSREP */
thd->lex->unit.cleanup();
thd->end_statement();
thd->cleanup_after_query();
diff --git a/sql/events.cc b/sql/events.cc
index 567baa5f90b..9d315ab8c08 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -341,7 +341,6 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
DBUG_RETURN(TRUE);
-
if (check_db_dir_existence(parse_data->dbname.str))
{
my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index f5302119187..e7236032259 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -405,6 +405,13 @@ const char *ha_partition::table_type() const
// we can do this since we only support a single engine type
return m_file[0]->table_type();
}
+#ifdef WITH_WSREP
+int ha_partition::wsrep_db_type() const
+{
+ // we can do this since we only support a single engine type
+ return ha_legacy_type(m_file[0]->ht);
+}
+#endif /* WITH_WSREP */
/*
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 8a374fe87b7..aec4d9031ab 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1507,5 +1507,8 @@ class ha_partition :public handler
friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
+#ifdef WITH_WSREP
+ virtual int wsrep_db_type() const;
+#endif /* WITH_WSREP */
};
#endif /* HA_PARTITION_INCLUDED */
diff --git a/sql/handler.cc b/sql/handler.cc
index 20d42fbc7a2..19d31b32381 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -53,9 +53,14 @@
#endif
#include "semisync_master.h"
-#include "wsrep_mysqld.h"
+#include "mysql/service_wsrep.h"
#include "wsrep.h"
+#include "wsrep_mysqld.h"
+#include "wsrep_binlog.h"
#include "wsrep_xid.h"
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
+#include "log.h"
/*
While we have legacy_db_type, we have this array to
@@ -251,6 +256,9 @@ handlerton *ha_checktype(THD *thd, handlerton *hton, bool no_substitute)
if (no_substitute)
return NULL;
+#ifdef WITH_WSREP
+ (void)wsrep_after_rollback(thd, false);
+#endif /* WITH_WSREP */
return ha_default_handlerton(thd);
} /* ha_checktype */
@@ -1163,17 +1171,30 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
static int prepare_or_error(handlerton *ht, THD *thd, bool all)
{
+ #ifdef WITH_WSREP
+ if (WSREP(thd) && ht->db_type == DB_TYPE_INNODB &&
+ wsrep_before_prepare(thd, all))
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ return(1);
+ }
+#endif /* WITH_WSREP */
+
int err= ht->prepare(ht, thd, all);
status_var_increment(thd->status_var.ha_prepare_count);
if (err)
{
- /* avoid sending error, if we're going to replay the transaction */
-#ifdef WITH_WSREP
- if (ht != wsrep_hton ||
- err == EMSGSIZE || thd->wsrep_conflict_state != MUST_REPLAY)
-#endif
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
}
+#ifdef WITH_WSREP
+ if (WSREP(thd) && ht->db_type == DB_TYPE_INNODB &&
+ wsrep_after_prepare(thd, all))
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ err= 1;
+ }
+#endif /* WITH_WSREP */
+
return err;
}
@@ -1357,8 +1378,11 @@ int ha_commit_trans(THD *thd, bool all)
DBUG_RETURN(2);
}
+#ifdef WITH_WSREP
+ bool trans_was_empty= true;
+#endif /* WITH_WSREP */
#ifdef WITH_ARIA_STORAGE_ENGINE
- ha_maria::implicit_commit(thd, TRUE);
+ ha_maria::implicit_commit(thd, TRUE);
#endif
if (!ha_info)
@@ -1368,6 +1392,13 @@ int ha_commit_trans(THD *thd, bool all)
*/
if (is_real_trans)
thd->transaction.cleanup();
+#ifdef WITH_WSREP
+ if (WSREP(thd) && all && !error && trans_was_empty)
+ {
+ WSREP_DEBUG("was empty handler");
+ wsrep_commit_empty(thd, all);
+ }
+#endif /* WITH_WSREP */
DBUG_RETURN(0);
}
@@ -1378,6 +1409,7 @@ int ha_commit_trans(THD *thd, bool all)
thd->stmt_map.close_transient_cursors();
uint rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
+ trans->rw_ha_count= rw_ha_count;
/* rw_trans is TRUE when we in a transaction changing data */
bool rw_trans= is_real_trans &&
(rw_ha_count > (thd->is_current_stmt_binlog_disabled()?0U:1U));
@@ -1451,6 +1483,12 @@ int ha_commit_trans(THD *thd, bool all)
}
}
#endif
+#ifdef WITH_WSREP
+ if (rw_ha_count)
+ {
+ trans_was_empty= false;
+ }
+#endif /* WITH_WSREP */
if (trans->no_2pc || (rw_ha_count <= 1))
{
@@ -1489,7 +1527,7 @@ int ha_commit_trans(THD *thd, bool all)
if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid))
{
// xid was rewritten by wsrep
- xid= wsrep_xid_seqno(thd->transaction.xid_state.xid);
+ xid= wsrep_xid_seqno(thd->transaction.xid_state.xid).get();
}
#endif /* WITH_WSREP */
@@ -1498,18 +1536,33 @@ int ha_commit_trans(THD *thd, bool all)
error= commit_one_phase_2(thd, all, trans, is_real_trans);
goto done;
}
-
+
DEBUG_SYNC(thd, "ha_commit_trans_before_log_and_order");
cookie= tc_log->log_and_order(thd, xid, all, need_prepare_ordered,
need_commit_ordered);
if (!cookie)
+ {
+ WSREP_DEBUG("log_and_order has failed %lu %d", thd->thread_id, cookie);
goto err;
+ }
DEBUG_SYNC(thd, "ha_commit_trans_after_log_and_order");
DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_SUICIDE(););
error= commit_one_phase_2(thd, all, trans, is_real_trans) ? 2 : 0;
-
+#ifdef WITH_WSREP
+ if (error)
+ {
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort)
+ {
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ (void)tc_log->unlog(cookie, xid);
+ goto wsrep_err;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+#endif /* WITH_WSREP */
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
if (tc_log->unlog(cookie, xid))
{
@@ -1517,7 +1570,7 @@ int ha_commit_trans(THD *thd, bool all)
goto end;
}
-done:
+ done:
DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
mysql_mutex_assert_not_owner(&LOCK_prepare_ordered);
@@ -1531,7 +1584,20 @@ int ha_commit_trans(THD *thd, bool all)
goto end;
/* Come here if error and we need to rollback. */
-err:
+#ifdef WITH_WSREP
+ wsrep_err:
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort)
+ {
+ WSREP_DEBUG("BF abort has happened after prepare & certify");
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ ha_rollback_trans(thd, TRUE);
+ }
+ else
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+
+#endif /* WITH_WSREP */
+ err:
error= 1; /* Transaction was rolled back */
/*
In parallel replication, rollback is delayed, as there is extra replication
@@ -1540,7 +1606,10 @@ int ha_commit_trans(THD *thd, bool all)
*/
if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec))
ha_rollback_trans(thd, all);
-
+ else
+ {
+ WSREP_DEBUG("rollback skipped %d %d",thd->rgi_slave, thd->rgi_slave->is_parallel_exec);
+ }
end:
if (rw_trans && mdl_request.ticket)
{
@@ -1552,6 +1621,13 @@ int ha_commit_trans(THD *thd, bool all)
*/
thd->mdl_context.release_lock(mdl_request.ticket);
}
+#ifdef WITH_WSREP
+ if (WSREP(thd) && all && !error && trans_was_empty)
+ {
+ wsrep_commit_empty(thd, all);
+ }
+#endif /* WITH_WSREP */
+
DBUG_RETURN(error);
}
@@ -1626,6 +1702,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans)
}
trans->ha_list= 0;
trans->no_2pc=0;
+ trans->rw_ha_count= 0;
if (all)
{
#ifdef HAVE_QUERY_CACHE
@@ -1674,7 +1751,6 @@ int ha_rollback_trans(THD *thd, bool all)
*/
DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
trans == &thd->transaction.stmt);
-
#ifdef HAVE_REPLICATION
if (is_real_trans)
{
@@ -1709,6 +1785,9 @@ int ha_rollback_trans(THD *thd, bool all)
DBUG_RETURN(1);
}
+#ifdef WITH_WSREP
+ (void) wsrep_before_rollback(thd, all);
+#endif // WITH_WSREP
if (ha_info)
{
/* Close all cursors that can not survive ROLLBACK */
@@ -1724,9 +1803,9 @@ int ha_rollback_trans(THD *thd, bool all)
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
#ifdef WITH_WSREP
- WSREP_WARN("handlerton rollback failed, thd %llu %lld conf %d SQL %s",
- thd->thread_id, thd->query_id, thd->wsrep_conflict_state,
- thd->query());
+ WSREP_WARN("handlerton rollback failed, thd %lld %lld conf %d SQL %s",
+ thd->thread_id, thd->query_id, thd->wsrep_trx().state(),
+ thd->query());
#endif /* WITH_WSREP */
}
status_var_increment(thd->status_var.ha_rollback_count);
@@ -1735,6 +1814,7 @@ int ha_rollback_trans(THD *thd, bool all)
}
trans->ha_list= 0;
trans->no_2pc=0;
+ trans->rw_ha_count= 0;
}
/*
@@ -1745,6 +1825,15 @@ int ha_rollback_trans(THD *thd, bool all)
thd->transaction.xid_state.xa_state != XA_NOTR)
thd->transaction.xid_state.rm_error= thd->get_stmt_da()->sql_errno();
+#ifdef WITH_WSREP
+ if (thd->is_error())
+ {
+ WSREP_DEBUG("ha_rollback_trans(%lld, %s) rolled back: %s: %s; is_real %d",
+ thd->thread_id, all?"TRUE":"FALSE", WSREP_QUERY(thd),
+ thd->get_stmt_da()->message(), is_real_trans);
+ }
+ (void) wsrep_after_rollback(thd, all);
+#endif
/* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
{
@@ -1918,7 +2007,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
for (int i=0; i < got; i ++)
{
my_xid x= IF_WSREP(WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ?
- wsrep_xid_seqno(info->list[i]) :
+ (wsrep_xid_seqno(info->list[i])).get() :
info->list[i].get_my_xid(),
info->list[i].get_my_xid());
if (!x) // not "mine" - that is generated by external TM
@@ -2269,6 +2358,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
DBUG_ENTER("ha_rollback_to_savepoint");
trans->no_2pc=0;
+ trans->rw_ha_count= 0;
/*
rolling back to savepoint in all storage engines that were part of the
transaction when the savepoint was set
@@ -2297,11 +2387,26 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
{
int err;
handlerton *ht= ha_info->ht();
+#ifdef WITH_WSREP
+ if (ht->db_type == DB_TYPE_INNODB)
+ {
+ WSREP_DEBUG("ha_rollback_to_savepoint: run before_rollbackha_rollback_trans hook");
+ (void) wsrep_before_rollback(thd, !thd->in_sub_stmt);
+
+ }
+#endif // WITH_WSREP
if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
{ // cannot happen
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
}
+#ifdef WITH_WSREP
+ if (ht->db_type == DB_TYPE_INNODB)
+ {
+ WSREP_DEBUG("ha_rollback_to_savepoint: run after_rollback hook");
+ (void) wsrep_after_rollback(thd, !thd->in_sub_stmt);
+ }
+#endif // WITH_WSREP
status_var_increment(thd->status_var.ha_rollback_count);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
@@ -2318,6 +2423,16 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
*/
int ha_savepoint(THD *thd, SAVEPOINT *sv)
{
+#ifdef WITH_WSREP
+ /*
+ Register binlog hton for savepoint processing if wsrep binlog
+ emulation is on.
+ */
+ if (WSREP_EMULATE_BINLOG(thd) && wsrep_thd_is_local(thd))
+ {
+ wsrep_register_binlog_handler(thd, thd->in_multi_stmt_transaction_mode());
+ }
+#endif /* WITH_WSREP */
int error=0;
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
&thd->transaction.all);
@@ -5933,6 +6048,12 @@ bool handler::check_table_binlog_row_based(bool binlog_row)
return false;
if (unlikely((table->in_use->variables.sql_log_bin_off)))
return 0; /* Called by partitioning engine */
+#ifdef WITH_WSREP
+ if (!table->in_use->variables.sql_log_bin)
+ return 0; /* wsrep patch sets sql_log_bin directly to silence
+ binlogging
+ */
+#endif /* WITH_WSREP */
if (unlikely((!check_table_binlog_row_based_done)))
{
check_table_binlog_row_based_done= 1;
@@ -5963,15 +6084,16 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row)
Otherwise, return 'true' if binary logging is on.
*/
IF_WSREP(((WSREP_EMULATE_BINLOG(thd) &&
- (thd->wsrep_exec_mode != REPL_RECV)) ||
+ wsrep_thd_is_local(thd)) ||
((WSREP(thd) ||
(thd->variables.option_bits & OPTION_BIN_LOG)) &&
mysql_bin_log.is_open())),
- (thd->variables.option_bits & OPTION_BIN_LOG) &&
- mysql_bin_log.is_open()));
+ (thd->variables.option_bits & OPTION_BIN_LOG) &&
+ mysql_bin_log.is_open()));
}
+
/** @brief
Write table maps for all (manually or automatically) locked tables
to the binary log. Also, if binlog_annotate_row_events is ON,
@@ -6062,6 +6184,16 @@ static int binlog_log_row_internal(TABLE* table,
bool error= 0;
THD *const thd= table->in_use;
+#ifdef WITH_WSREP
+ /* only InnoDB tables will be replicated through binlog emulation */
+ if (WSREP_EMULATE_BINLOG(thd) &&
+ table->file->ht->db_type != DB_TYPE_INNODB &&
+ !(table->file->ht->db_type == DB_TYPE_PARTITION_DB &&
+ (((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB)))
+ {
+ return 0;
+ }
+#endif /* WITH_WSREP */
/*
If there are no table maps written to the binary log, this is
the first row handled in this statement. In that case, we need
@@ -6096,20 +6228,6 @@ int binlog_log_row(TABLE* table, const uchar *before_record,
table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
(thd->wsrep_ignore_table == true))
return 0;
-
- /* enforce wsrep_max_ws_rows */
- if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE)
- {
- thd->wsrep_affected_rows++;
- if (wsrep_max_ws_rows &&
- thd->wsrep_exec_mode != REPL_RECV &&
- thd->wsrep_affected_rows > wsrep_max_ws_rows)
- {
- trans_rollback_stmt(thd) || trans_rollback(thd);
- my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
- return ER_ERROR_DURING_COMMIT;
- }
- }
#endif
if (!table->file->check_table_binlog_row_based(1))
@@ -6221,6 +6339,27 @@ int handler::ha_reset()
DBUG_RETURN(reset());
}
+#ifdef WITH_WSREP
+static int wsrep_after_row(THD *thd)
+{
+ DBUG_ENTER("wsrep_after_row");
+ /* enforce wsrep_max_ws_rows */
+ thd->wsrep_affected_rows++;
+ if (wsrep_max_ws_rows &&
+ wsrep_thd_is_local(thd) &&
+ thd->wsrep_affected_rows > wsrep_max_ws_rows)
+ {
+ trans_rollback_stmt(thd) || trans_rollback(thd);
+ my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
+ DBUG_RETURN(ER_ERROR_DURING_COMMIT);
+ }
+ else if (wsrep_after_row(thd, false))
+ {
+ DBUG_RETURN(ER_LOCK_DEADLOCK);
+ }
+ DBUG_RETURN(0);
+}
+#endif /* WITH_WSREP */
int handler::ha_write_row(uchar *buf)
{
@@ -6243,7 +6382,16 @@ int handler::ha_write_row(uchar *buf)
{
rows_changed++;
error= binlog_log_row(table, 0, buf, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ DBUG_RETURN(error);
+ }
+#endif /* WITH_WSREP */
}
+
DEBUG_SYNC_C("ha_write_row_end");
DBUG_RETURN(error);
}
@@ -6275,6 +6423,14 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
{
rows_changed++;
error= binlog_log_row(table, old_data, new_data, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ return error;
+ }
+#endif /* WITH_WSREP */
}
return error;
}
@@ -6330,6 +6486,14 @@ int handler::ha_delete_row(const uchar *buf)
{
rows_changed++;
error= binlog_log_row(table, buf, 0, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ return error;
+ }
+#endif /* WITH_WSREP */
}
return error;
}
@@ -6519,7 +6683,7 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
DBUG_ENTER("ha_abort_transaction");
if (!WSREP(bf_thd) &&
!(bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU &&
- bf_thd->wsrep_exec_mode == TOTAL_ORDER)) {
+ wsrep_thd_is_toi(bf_thd))) {
DBUG_RETURN(0);
}
@@ -6535,52 +6699,16 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
DBUG_RETURN(0);
}
-
void ha_fake_trx_id(THD *thd)
{
- DBUG_ENTER("ha_fake_trx_id");
-
- bool no_fake_trx_id= true;
-
- if (!WSREP(thd))
- {
- DBUG_VOID_RETURN;
- }
-
- if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID)
+ DBUG_ENTER("ha_wsrep_fake_trx_id");
+ if (!WSREP(thd))
{
- WSREP_DEBUG("fake trx id skipped: %" PRIu64, thd->wsrep_ws_handle.trx_id);
DBUG_VOID_RETURN;
}
-
- /* Try statement transaction if standard one is not set. */
- THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all :
- &thd->transaction.stmt;
-
- Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
-
- for (; ha_info; ha_info= ha_info_next)
- {
- handlerton *hton= ha_info->ht();
- if (hton->fake_trx_id)
- {
- hton->fake_trx_id(hton, thd);
-
- /* Got a fake trx id. */
- no_fake_trx_id= false;
-
- /*
- We need transaction ID from just one storage engine providing
- fake_trx_id (which will most likely be the case).
- */
- break;
- }
- ha_info_next= ha_info->next();
- }
-
- if (unlikely(no_fake_trx_id))
- WSREP_WARN("Cannot get fake transaction ID from storage engine.");
-
+#ifdef OUT
+ (void *)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->query_id);
+#endif
DBUG_VOID_RETURN;
}
#endif /* WITH_WSREP */
diff --git a/sql/handler.h b/sql/handler.h
index 362c6784377..78936b2bbd4 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1661,6 +1661,9 @@ struct THD_TRANS
{
/* true is not all entries in the ht[] support 2pc */
bool no_2pc;
+#ifdef WITH_WSREP
+ int rw_ha_count;
+#endif /* WITH_WSREP */
/* storage engines that registered in this transaction */
Ha_trx_info *ha_list;
/*
@@ -1695,6 +1698,7 @@ struct THD_TRANS
void reset() {
no_2pc= FALSE;
+ rw_ha_count= 0;
modified_non_trans_table= FALSE;
m_unsafe_rollback_flags= 0;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 87bf69f3c96..a4c3de5f8fb 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -3193,6 +3193,45 @@ class Create_func_within : public Create_func_arg2
};
#endif
+#ifdef WITH_WSREP
+class Create_func_wsrep_last_written_gtid : public Create_func_arg0
+{
+public:
+ virtual Item *create_builder(THD *thd);
+
+ static Create_func_wsrep_last_written_gtid s_singleton;
+
+protected:
+ Create_func_wsrep_last_written_gtid() {}
+ virtual ~Create_func_wsrep_last_written_gtid() {}
+};
+
+
+class Create_func_wsrep_last_seen_gtid : public Create_func_arg0
+{
+public:
+ virtual Item *create_builder(THD *thd);
+
+ static Create_func_wsrep_last_seen_gtid s_singleton;
+
+protected:
+ Create_func_wsrep_last_seen_gtid() {}
+ virtual ~Create_func_wsrep_last_seen_gtid() {}
+};
+
+
+class Create_func_wsrep_sync_wait_upto : public Create_native_func
+{
+public:
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
+
+ static Create_func_wsrep_sync_wait_upto s_singleton;
+
+protected:
+ Create_func_wsrep_sync_wait_upto() {}
+ virtual ~Create_func_wsrep_sync_wait_upto() {}
+};
+#endif /* WITH_WSREP */
#ifdef HAVE_SPATIAL
class Create_func_x : public Create_func_arg1
@@ -6905,6 +6944,63 @@ Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
}
#endif
+#ifdef WITH_WSREP
+Create_func_wsrep_last_written_gtid
+Create_func_wsrep_last_written_gtid::s_singleton;
+
+Item*
+Create_func_wsrep_last_written_gtid::create_builder(THD *thd)
+{
+ current_thd->lex->safe_to_cache_query= 0;
+ return new (thd->mem_root) Item_func_wsrep_last_written_gtid(thd);
+}
+
+
+Create_func_wsrep_last_seen_gtid
+Create_func_wsrep_last_seen_gtid::s_singleton;
+
+Item*
+Create_func_wsrep_last_seen_gtid::create_builder(THD *thd)
+{
+ current_thd->lex->safe_to_cache_query= 0;
+ return new (thd->mem_root) Item_func_wsrep_last_seen_gtid(thd);
+}
+
+
+Create_func_wsrep_sync_wait_upto
+Create_func_wsrep_sync_wait_upto::s_singleton;
+
+Item*
+Create_func_wsrep_sync_wait_upto::create_native(THD *thd,
+ LEX_CSTRING *name,
+ List<Item> *item_list)
+{
+ Item *func= NULL;
+ int arg_count= 0;
+ Item *param_1, *param_2;
+
+ if (item_list != NULL)
+ arg_count= item_list->elements;
+
+ switch (arg_count)
+ {
+ case 1:
+ param_1= item_list->pop();
+ func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1);
+ break;
+ case 2:
+ param_1= item_list->pop();
+ param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1, param_2);
+ break;
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ break;
+ }
+ current_thd->lex->safe_to_cache_query= 0;
+ return func;
+}
+#endif /* WITH_WSREP */
#ifdef HAVE_SPATIAL
Create_func_x Create_func_x::s_singleton;
@@ -7347,6 +7443,11 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)},
{ { STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)},
{ { STRING_WITH_LEN("WITHIN") }, GEOM_BUILDER(Create_func_within)},
+#ifdef WITH_WSREP
+ { { STRING_WITH_LEN("WSREP_LAST_WRITTEN_GTID") }, BUILDER(Create_func_wsrep_last_written_gtid)},
+ { { STRING_WITH_LEN("WSREP_LAST_SEEN_GTID") }, BUILDER(Create_func_wsrep_last_seen_gtid)},
+ { { STRING_WITH_LEN("WSREP_SYNC_WAIT_UPTO_GTID") }, BUILDER(Create_func_wsrep_sync_wait_upto)},
+#endif /* WITH_WSREP */
{ { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)},
{ { STRING_WITH_LEN("Y") }, GEOM_BUILDER(Create_func_y)},
{ { STRING_WITH_LEN("YEARWEEK") }, BUILDER(Create_func_year_week)},
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ea6a39ab150..df3c30209e0 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -59,6 +59,9 @@
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
#endif
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP */
bool check_reserved_words(const LEX_CSTRING *name)
{
@@ -2495,7 +2498,7 @@ void Item_func_rand::seed_random(Item *arg)
THD *thd= current_thd;
if (WSREP(thd))
{
- if (thd->wsrep_exec_mode==REPL_RECV)
+ if (wsrep_thd_is_applying(current_thd))
tmp= thd->wsrep_rand;
else
tmp= thd->wsrep_rand= (uint32) arg->val_int();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6c82c580858..5d65637c134 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -5264,3 +5264,102 @@ 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"
+
+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()))
+ {
+ my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len());
+ null_value= true;
+ return NULL;
+ }
+
+ ssize_t gtid_len= gtid_print_to_c_str(gtid, (char*)gtid_str.ptr(),
+ wsrep::gtid_c_str_len());
+ if (gtid_len < 0)
+ {
+ my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
+ "wsrep_gtid_print failed");
+ null_value= true;
+ return NULL;
+ }
+ gtid_str.length(gtid_len);
+ return >id_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()))
+ {
+ my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len());
+ null_value= true;
+ return NULL;
+ }
+ ssize_t gtid_len= wsrep::gtid_print_to_c_str(gtid, (char*)gtid_str.ptr(),
+ wsrep::gtid_c_str_len());
+ if (gtid_len < 0)
+ {
+ my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
+ "wsrep_gtid_print failed");
+ null_value= true;
+ return NULL;
+ }
+ gtid_str.length(gtid_len);
+ return >id_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();
+ }
+
+ wsrep_gtid_t gtid;
+ int gtid_len= wsrep_gtid_scan(gtid_str->ptr(), gtid_str->length(), >id);
+ if (gtid_len < 0)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
+ return 0LL;
+ }
+
+ if (gtid.seqno == WSREP_SEQNO_UNDEFINED &&
+ wsrep_uuid_compare(>id.uuid, &WSREP_UUID_UNDEFINED) == 0)
+ {
+ return 1LL;
+ }
+
+ enum wsrep::provider::status status=
+ wsrep_sync_wait_upto(current_thd, >id, timeout);
+
+ if (status)
+ {
+ int err;
+ switch (status) {
+ case wsrep::provider::error_transaction_missing:
+ err= ER_WRONG_ARGUMENTS;
+ break;
+ default:
+ err= ER_LOCK_WAIT_TIMEOUT;
+ }
+ my_error(err, MYF(0), func_name());
+ return 0LL;
+ }
+ return 1LL;
+}
+#endif /* WITH_WSREP */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 762a3c2559e..5b6a08d4285 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1804,5 +1804,56 @@ class Item_temptable_rowid :public Item_str_func
Item *get_copy(THD *thd)
{ return get_item_copy<Item_temptable_rowid>(thd, this); }
};
+#ifdef WITH_WSREP
+
+#include "../wsrep/wsrep_api.h"
+
+class Item_func_wsrep_last_written_gtid: public Item_str_ascii_func
+{
+ String gtid_str;
+public:
+ Item_func_wsrep_last_written_gtid(THD *thd): Item_str_ascii_func(thd) {}
+ const char *func_name() const { return "wsrep_last_written_gtid"; }
+ String *val_str_ascii(String *);
+ bool fix_length_and_dec()
+ {
+ max_length = WSREP_GTID_STR_LEN;
+ maybe_null = true;
+ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_last_written_gtid>(thd, this); }
+};
+
+class Item_func_wsrep_last_seen_gtid: public Item_str_ascii_func
+{
+ String gtid_str;
+public:
+ Item_func_wsrep_last_seen_gtid(THD *thd): Item_str_ascii_func(thd) {}
+ const char *func_name() const { return "wsrep_last_seen_gtid"; }
+ String *val_str_ascii(String *);
+ bool fix_length_and_dec()
+ {
+ max_length = WSREP_GTID_STR_LEN;
+ maybe_null = true;
+ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_last_seen_gtid>(thd, this); }
+};
+
+class Item_func_wsrep_sync_wait_upto: public Item_int_func
+{
+ String value;
+public:
+ Item_func_wsrep_sync_wait_upto(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_wsrep_sync_wait_upto(THD *thd, Item *a, Item* b): Item_int_func(thd, a, b) {}
+ const Type_handler *type_handler() const { return &type_handler_string; }
+ const char *func_name() const { return "wsrep_sync_wait_upto_gtid"; }
+ longlong val_int();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_sync_wait_upto>(thd, this); }
+};
+#endif /* WITH_WSREP */
#endif /* ITEM_STRFUNC_INCLUDED */
diff --git a/sql/lock.cc b/sql/lock.cc
index 17629f17291..5c0c39cc068 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1084,21 +1084,16 @@ void Global_read_lock::unlock_global_read_lock(THD *thd)
thd->mdl_context.release_lock(m_mdl_blocks_commits_lock);
m_mdl_blocks_commits_lock= NULL;
#ifdef WITH_WSREP
- if (WSREP(thd) || wsrep_node_is_donor())
+ Wsrep_server_state& server_state= Wsrep_server_state::instance();
+ if (server_state.state() == Wsrep_server_state::s_donor)
{
+ /* TODO: maybe redundant here?: */
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
- wsrep->resume(wsrep);
- /* resync here only if we did implicit desync earlier */
- if (!wsrep_desync && wsrep_node_is_synced())
- {
- int ret = wsrep->resync(wsrep);
- if (ret != WSREP_OK)
- {
- WSREP_WARN("resync failed %d for FTWRL: db: %s, query: %s",
- ret, thd->get_db(), thd->query());
- DBUG_VOID_RETURN;
- }
- }
+ server_state.resume();
+ }
+ else if (WSREP(thd))
+ {
+ server_state.resume_and_resync();
}
#endif /* WITH_WSREP */
}
@@ -1134,9 +1129,6 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
make_global_read_lock_block_commit(), do nothing.
*/
- if (m_state != GRL_ACQUIRED)
- DBUG_RETURN(0);
-
#ifdef WITH_WSREP
if (WSREP(thd) && m_mdl_blocks_commits_lock)
{
@@ -1146,6 +1138,10 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
}
#endif /* WITH_WSREP */
+ if (m_state != GRL_ACQUIRED)
+ DBUG_RETURN(0);
+
+
mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request,
@@ -1156,60 +1152,32 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT;
#ifdef WITH_WSREP
+
/* Native threads should bail out before wsrep oprations to follow.
- Donor servicing thread is an exception, it should pause provider but not desync,
- as it is already desynced in donor state
+ Donor servicing thread is an exception, it should pause provider
+ but not desync, as it is already desynced in donor state
*/
- if (!WSREP(thd) && !wsrep_node_is_donor())
+ Wsrep_server_state& server_state= Wsrep_server_state::instance();
+ if (!WSREP(thd) && server_state.state() != Wsrep_server_state::s_donor)
{
DBUG_RETURN(FALSE);
}
- /* if already desynced or donor, avoid double desyncing
- if not in PC and synced, desyncing is not possible either
- */
- if (wsrep_desync || !wsrep_node_is_synced())
+ wsrep::seqno paused_seqno;
+ if (server_state.state() == Wsrep_server_state::s_donor)
{
- WSREP_DEBUG("desync set upfont, skipping implicit desync for FTWRL: %d",
- wsrep_desync);
+ paused_seqno= server_state.pause();
}
else
{
- int rcode;
- WSREP_DEBUG("running implicit desync for node");
- rcode = wsrep->desync(wsrep);
- if (rcode != WSREP_OK)
- {
- WSREP_WARN("FTWRL desync failed %d for schema: %s, query: %s",
- rcode, thd->get_db(), thd->query());
- my_message(ER_LOCK_DEADLOCK, "wsrep desync failed for FTWRL", MYF(0));
- DBUG_RETURN(TRUE);
- }
+ paused_seqno= server_state.desync_and_pause();
}
-
- long long ret = wsrep->pause(wsrep);
- if (ret >= 0)
+ WSREP_INFO("Server paused at: %lld", paused_seqno.get());
+ if (paused_seqno.get() >= 0)
{
- wsrep_locked_seqno= ret;
+ wsrep_locked_seqno= paused_seqno.get();
}
- else if (ret != -ENOSYS) /* -ENOSYS - no provider */
- {
- long long ret = wsrep->pause(wsrep);
- if (ret >= 0)
- {
- wsrep_locked_seqno= ret;
- }
- else if (ret != -ENOSYS) /* -ENOSYS - no provider */
- {
- WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
-
- DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL);
- wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
- my_error(ER_LOCK_DEADLOCK, MYF(0));
- DBUG_RETURN(TRUE);
- }
- }
-#endif /* WITH_WSREP */
+ #endif /* WITH_WSREP */
DBUG_RETURN(FALSE);
}
diff --git a/sql/log.cc b/sql/log.cc
index a56117a4ac1..c412be4bb67 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -59,6 +59,8 @@
#include "sp_rcontext.h"
#include "sp_head.h"
+#include "wsrep_trans_observer.h"
+
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_TIME_SIZE 32
@@ -1703,7 +1705,8 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
#ifdef WITH_WSREP
if (cache_mngr && !cache_mngr->trx_cache.empty()) {
- IO_CACHE* cache= get_trans_log(thd);
+ //IO_CACHE* cache= wsrep_get_trans_cache(thd);
+ IO_CACHE* cache= cache_mngr->get_binlog_cache_log(true);
uchar *buf;
size_t len=0;
wsrep_write_cache_buf(cache, &buf, &len);
@@ -2297,8 +2300,17 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
+#ifdef WITH_WSREP
+ /* for streaming replication, we must replicate savepoint rollback so that
+ slaves can maintain SR transactions
+ */
+ if (unlikely(thd->wsrep_trx().is_streaming() ||
+ (trans_has_updated_non_trans_table(thd)) ||
+ (thd->variables.option_bits & OPTION_KEEP_LOG)))
+#else
if (unlikely(trans_has_updated_non_trans_table(thd) ||
(thd->variables.option_bits & OPTION_KEEP_LOG)))
+#endif /* WITH_WSREP */
{
char buf[1024];
String log_query(buf, sizeof(buf), &my_charset_bin);
@@ -5970,7 +5982,9 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
DBUG_PRINT("enter", ("standalone: %d", standalone));
#ifdef WITH_WSREP
- if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode && !thd->variables.gtid_seq_no)
+ if (WSREP(thd) &&
+ (wsrep_thd_trx_seqno(thd) > 0) &&
+ wsrep_gtid_mode && !thd->variables.gtid_seq_no)
{
domain_id= wsrep_gtid_domain_id;
} else {
@@ -6287,7 +6301,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
*/
/* applier and replayer can skip writing binlog events */
if ((WSREP_EMULATE_BINLOG(thd) &&
- IF_WSREP(thd->wsrep_exec_mode != REPL_RECV, 0)) || is_open())
+ IF_WSREP(thd->wsrep_cs().mode() == wsrep::client_state::m_local, 0)) || is_open())
{
my_off_t UNINIT_VAR(my_org_b_tell);
#ifdef HAVE_REPLICATION
@@ -7703,7 +7717,30 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
DEBUG_SYNC(entry->thd, "commit_loop_entry_commit_ordered");
++num_commits;
if (entry->cache_mngr->using_xa && !entry->error)
+#ifdef WITH_WSREP
+ {
+ if (WSREP(entry->thd) &&
+ wsrep_before_commit(entry->thd, entry->all))
+ {
+ return (true);
+ }
+#endif /* WITH_WSREP */
run_commit_ordered(entry->thd, entry->all);
+#ifdef WITH_WSREP
+ if (WSREP(entry->thd))
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(entry->thd, entry->all, wsrep_apply_error());
+ if (!error)
+ {
+ (void) wsrep_after_commit(entry->thd, entry->all);
+ }
+ }
+ }
+#endif /* WITH_WSREP */
group_commit_entry *next= entry->next;
if (!next)
@@ -8087,7 +8124,31 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
++num_commits;
if (current->cache_mngr->using_xa && likely(!current->error) &&
DBUG_EVALUATE_IF("skip_commit_ordered", 0, 1))
+#ifdef WITH_WSREP
+ {
+ if (WSREP(current->thd) &&
+ wsrep_before_commit(current->thd, current->all))
+ {
+ DBUG_VOID_RETURN;
+ }
+#endif /* WITH_WSREP */
run_commit_ordered(current->thd, current->all);
+#ifdef WITH_WSREP
+ if (WSREP(current->thd))
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(current->thd, current->all, wsrep_apply_error());
+ //if (!error) (void) wsrep_after_commit(current->thd, current->all);
+ if (!error)
+ {
+ (void) wsrep_after_commit(current->thd, current->all);
+ }
+ }
+ }
+#endif /* WITH_WSREP */
current->thd->wakeup_subsequent_commits(current->error);
/*
@@ -8926,9 +8987,27 @@ int TC_LOG_MMAP::log_and_order(THD *thd, my_xid xid, bool all,
/* Only run commit_ordered() if log_xid was successful. */
if (cookie)
{
+#ifdef WITH_WSREP
+ if (WSREP(thd) && WSREP_EMULATE_BINLOG(thd) && wsrep_before_commit(thd, all))
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ return(0);
+ }
+#endif /* WITH_WSREP */
mysql_mutex_lock(&LOCK_commit_ordered);
run_commit_ordered(thd, all);
mysql_mutex_unlock(&LOCK_commit_ordered);
+ //if (WSREP(thd) && !thd->wsrep_apply_toi)
+#ifdef WITH_WSREP
+ if (WSREP(thd) && WSREP_EMULATE_BINLOG(thd))
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ (void) wsrep_after_commit(thd, all);
+ }
+#endif /* WITH_WSREP */
}
if (need_prepare_ordered)
@@ -9626,6 +9705,37 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
if (err)
DBUG_RETURN(0);
+#ifdef WITH_WSREP
+ /*
+ if binary logging is on and transaction happened by group commit, no need for commit hooks
+ here any more
+ */
+ if (WSREP(thd) &&
+ thd->wsrep_cs().transaction().state() != wsrep::transaction::state::s_committed &&
+ thd->wsrep_cs().mode() != wsrep::client_state::m_local &&
+ wsrep_before_commit(thd, all))
+ {
+ return(0);
+ }
+
+#endif /* WITH_WSREP */
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ thd->wsrep_cs().transaction().state() != wsrep::transaction::state::s_committed &&
+ thd->wsrep_cs().mode() != wsrep::client_state::m_local)
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(thd, all, wsrep_apply_error());
+ if (!error)
+ {
+ (void) wsrep_after_commit(thd, all);
+ }
+ }
+
+#endif /* WITH_WSREP */
bool need_unlog= cache_mngr->need_unlog;
/*
@@ -10592,7 +10702,44 @@ maria_declare_plugin(binlog)
maria_declare_plugin_end;
#ifdef WITH_WSREP
-IO_CACHE * get_trans_log(THD * thd)
+#include "wsrep_trans_observer.h"
+#include "wsrep_mysqld.h"
+
+static int wsrep_plugin_init(void *p)
+{
+ WSREP_INFO("wsrep_plugin_init()");
+ return (0);
+}
+
+static int wsrep_plugin_deinit(void *p)
+{
+ WSREP_INFO("wsrep_plugin_deinit()");
+ return (0);
+}
+
+struct Mysql_replication wsrep_plugin= {
+ MYSQL_REPLICATION_INTERFACE_VERSION
+};
+
+maria_declare_plugin(wsrep)
+{
+ MYSQL_REPLICATION_PLUGIN,
+ &wsrep_plugin,
+ "wsrep",
+ "Codership Oy",
+ "Wsrep replication plugin",
+ PLUGIN_LICENSE_GPL,
+ wsrep_plugin_init,
+ wsrep_plugin_deinit,
+ 0x0100,
+ NULL, /* Status variables */
+ NULL, /* System variables */
+ "1.0", /* Version (string) */
+ MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */
+}
+maria_declare_plugin_end;
+
+IO_CACHE *wsrep_get_trans_cache(THD * thd)
{
DBUG_ASSERT(binlog_hton->slot != HA_SLOT_UNDEF);
binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*)
@@ -10606,16 +10753,23 @@ IO_CACHE * get_trans_log(THD * thd)
}
-bool wsrep_trans_cache_is_empty(THD *thd)
+uint wsrep_get_trans_cache_position(THD *thd)
{
- binlog_cache_mngr *const cache_mngr=
- (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
- return (!cache_mngr || cache_mngr->trx_cache.empty());
+ if (binlog_hton)
+ {
+ my_off_t pos = 0;
+ binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*)
+ thd_get_ha_data(thd, binlog_hton);
+ if (cache_mngr) binlog_trans_log_savepos(thd, &pos);
+ return (pos);
+ }
+ return 0;
}
-
-void thd_binlog_trx_reset(THD * thd)
+void wsrep_thd_binlog_trx_reset(THD * thd)
{
+ DBUG_ENTER("wsrep_thd_binlog_trx_reset");
+ WSREP_DEBUG("wsrep_thd_binlog_reset");
/*
todo: fix autocommit select to not call the caller
*/
@@ -10634,6 +10788,7 @@ void thd_binlog_trx_reset(THD * thd)
}
}
thd->clear_binlog_table_maps();
+ DBUG_VOID_RETURN;
}
@@ -10646,4 +10801,87 @@ void thd_binlog_rollback_stmt(THD * thd)
if (cache_mngr)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
}
+
+int wsrep_thd_binlog_prepare(THD* thd, bool all)
+{
+ /* applier and replayer can skip binlog prepare */
+ if (WSREP_EMULATE_BINLOG(thd) &&
+ thd->wsrep_cs().mode() == wsrep::client_state::m_local)
+ return binlog_hton->prepare(binlog_hton, thd, all);
+ else
+ return ha_prepare(thd);
+}
+
+bool wsrep_stmt_rollback_is_safe(THD* thd)
+{
+ bool ret(true);
+
+ DBUG_ENTER("wsrep_binlog_stmt_rollback_is_safe");
+
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+
+ if (binlog_hton && cache_mngr)
+ {
+ binlog_cache_data * trx_cache = &cache_mngr->trx_cache;
+ if (thd->wsrep_sr().fragments_certified() > 0 &&
+ (trx_cache->get_prev_position() == MY_OFF_T_UNDEF ||
+ trx_cache->get_prev_position() < thd->wsrep_sr().bytes_certified()))
+ {
+ WSREP_DEBUG("statement rollback is not safe for streaming replication"
+ " pre-stmt_pos: %llu, frag repl pos: %lu\nThread: %lu, SQL: %s",
+ trx_cache->get_prev_position(),
+ thd->wsrep_sr().bytes_certified(),
+ thd->thread_id, thd->query());
+ ret = false;
+ }
+ }
+ DBUG_RETURN(ret);
+}
+
+void wsrep_register_binlog_handler(THD *thd, bool trx)
+{
+ DBUG_ENTER("register_binlog_handler");
+ /*
+ If this is the first call to this function while processing a statement,
+ the transactional cache does not have a savepoint defined. So, in what
+ follows:
+ . an implicit savepoint is defined;
+ . callbacks are registered;
+ . binary log is set as read/write.
+
+ The savepoint allows for truncating the trx-cache transactional changes
+ fail. Callbacks are necessary to flush caches upon committing or rolling
+ back a statement or a transaction. However, notifications do not happen
+ if the binary log is set as read/write.
+ */
+ //binlog_cache_mngr *cache_mngr= thd_get_cache_mngr(thd);
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ /* cache_mngr may be missing e.g. in mtr test ev51914.test */
+ if (cache_mngr && cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
+ {
+ /*
+ Set an implicit savepoint in order to be able to truncate a trx-cache.
+ */
+ my_off_t pos= 0;
+ binlog_trans_log_savepos(thd, &pos);
+ cache_mngr->trx_cache.set_prev_position(pos);
+
+ /*
+ Set callbacks in order to be able to call commmit or rollback.
+ */
+ if (trx)
+ trans_register_ha(thd, TRUE, binlog_hton);
+ trans_register_ha(thd, FALSE, binlog_hton);
+
+ /*
+ Set the binary log as read/write otherwise callbacks are not called.
+ */
+ thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
+ }
+ DBUG_VOID_RETURN;
+}
+
#endif /* WITH_WSREP */
diff --git a/sql/log.h b/sql/log.h
index 7dfdb36c442..1aa83eaabb1 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -96,6 +96,11 @@ extern PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
extern PSI_mutex_key key_LOCK_after_binlog_sync;
extern PSI_cond_key key_COND_prepare_ordered;
#endif
+#ifdef WITH_WSREP
+int wsrep_thd_binlog_commit(THD *thd, bool all);
+int wsrep_thd_binlog_rollback(THD *thd, bool all);
+int wsrep_thd_binlog_prepare(THD *thd, bool all);
+#endif /* WITH_WSREP */
class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
{
@@ -103,6 +108,11 @@ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
TC_LOG_DUMMY() {}
int open(const char *opt_name) { return 0; }
void close() { }
+#ifdef WITH_WSREP
+ int commit(THD *thd, bool all) {
+ return wsrep_thd_binlog_commit(thd, all);
+ }
+#endif /* WITH_WSREP */
/*
TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we
only use internal XA during commit when >= 2 XA-capable engines
@@ -1211,6 +1221,15 @@ static inline TC_LOG *get_tc_log_implementation()
return &mysql_bin_log;
return &tc_log_mmap;
}
+#ifdef WITH_WSREP
+IO_CACHE* wsrep_get_trans_cache(THD *);
+void wsrep_thd_binlog_trx_reset(THD * thd);
+#define WSREP_BINLOG_FORMAT(my_format) \
+ ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
+ wsrep_forced_binlog_format : my_format)
+#else
+#define WSREP_BINLOG_FORMAT(my_format) my_format
+#endif /* WITH_WSREP */
class Gtid_list_log_event;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 63af9015ae9..1322704999e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -44,6 +44,9 @@
#include "compat56.h"
#include "wsrep_mysqld.h"
#include "sql_insert.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif
#else
#include "mysqld_error.h"
#endif /* MYSQL_CLIENT */
@@ -5743,6 +5746,14 @@ START SLAVE; . Query: '%s'", expected_error, thd->query());
"unexpected success or fatal error"),
thd->get_db(), query_arg);
thd->is_slave_error= 1;
+#ifdef WITH_WSREP
+ if (thd->wsrep_apply_toi && wsrep_must_ignore_error(thd))
+ {
+ thd->clear_error(1);
+ thd->killed= NOT_KILLED;
+ thd->wsrep_has_ignored_error= true;
+ }
+#endif /* WITH_WSREP */
}
/*
@@ -11256,13 +11267,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
{
WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d "
"wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)",
- thd->get_stmt_da()->sql_errno(),
- thd->is_fatal_error,
- thd->wsrep_exec_mode,
- thd->wsrep_conflict_state,
- (long long)wsrep_thd_trx_seqno(thd));
+ thd->get_stmt_da()->sql_errno(),
+ thd->is_fatal_error,
+ thd->wsrep_cs().mode(),
+ thd->wsrep_trx().state(),
+ (long long)wsrep_thd_trx_seqno(thd));
}
-#endif
+#endif /* WITH_WSREP */
if ((thd->is_slave_error || thd->is_fatal_error) &&
!is_parallel_retry_error(rgi, actual_error))
{
@@ -11399,10 +11410,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
#ifdef HAVE_QUERY_CACHE
#ifdef WITH_WSREP
/*
- Moved invalidation right before the call to rows_event_stmt_cleanup(),
- to avoid query cache being polluted with stale entries.
+ Moved invalidation right before the call to rows_event_stmt_cleanup(),
+ to avoid query cache being polluted with stale entries,
*/
- if (! (WSREP(thd) && (thd->wsrep_exec_mode == REPL_RECV)))
+ if (! (WSREP(thd) && wsrep_thd_is_applying(thd)))
{
#endif /* WITH_WSREP */
query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
@@ -11515,6 +11526,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
bool ignored_error= (idempotent_error == 0 ?
ignored_error_code(actual_error) : 0);
+#ifdef WITH_WSREP
+ if (WSREP(thd) && wsrep_ignored_error_code(this, actual_error))
+ {
+ idempotent_error= true;
+ thd->wsrep_has_ignored_error= true;
+ }
+#endif /* WITH_WSREP */
if (idempotent_error || ignored_error)
{
if (global_system_variables.log_warnings)
@@ -11602,7 +11620,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
restore_empty_query_table_list(thd->lex);
#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE)
- if (WSREP(thd) && thd->wsrep_exec_mode == REPL_RECV)
+ if (WSREP(thd) && wsrep_thd_is_applying(thd))
{
query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
}
diff --git a/sql/mdl.cc b/sql/mdl.cc
index f03fc89fcc1..fd419a68e3a 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -24,9 +24,12 @@
#include <mysql/plugin.h>
#include <mysql/service_thd_wait.h>
#include <mysql/psi/mysql_stage.h>
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#include "debug_sync.h"
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
-
+#endif /* WITH_WSREP */
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
@@ -1073,7 +1076,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK);
while (!m_wait_status && !owner->is_killed() &&
wait_result != ETIMEDOUT && wait_result != ETIME)
- {
+ {
#ifdef WITH_WSREP
// Allow tests to block the applier thread using the DBUG facilities
DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait",
@@ -1084,7 +1087,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()),
STRING_WITH_LEN(act)));
};);
- if (wsrep_thd_is_BF(owner->get_thd(), false))
+ if (wsrep_thd_is_BF((void*)owner->get_thd(), false))
{
wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status);
}
@@ -1158,19 +1161,19 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) &&
- wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false))
+ wsrep_thd_is_BF((void*)ticket->get_ctx()->get_thd(), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted);
DBUG_ASSERT(WSREP_ON);
- MDL_ticket *waiting, *granted;
+ MDL_ticket *waiting;
MDL_ticket *prev=NULL;
bool added= false;
while ((waiting= itw++) && !added)
{
- if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true))
+ if (!wsrep_thd_is_BF((void*)waiting->get_ctx()->get_thd(), true))
{
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
thd_get_thread_id(waiting->get_ctx()->get_thd()),
@@ -1185,18 +1188,6 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
/* Otherwise, insert the ticket at the back of the waiting list. */
if (!added) m_list.push_back(ticket);
- while ((granted= itg++))
- {
- if (granted->get_ctx() != ticket->get_ctx() &&
- granted->is_incompatible_when_granted(ticket->get_type()))
- {
- if (!wsrep_grant_mdl_exception(ticket->get_ctx(), granted,
- &ticket->get_lock()->key))
- {
- WSREP_DEBUG("MDL victim killed at add_ticket");
- }
- }
- }
}
else
#endif /* WITH_WSREP */
@@ -1558,7 +1549,6 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
bool can_grant= FALSE;
bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
- bool wsrep_can_grant= TRUE;
/*
New lock request can be satisfied iff:
@@ -1571,10 +1561,20 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
{
if (! (m_granted.bitmap() & granted_incompat_map))
can_grant= TRUE;
+#ifdef WITH_WSREP
+ else if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()),false) &&
+ key.mdl_namespace() == MDL_key::GLOBAL)
+ {
+ WSREP_DEBUG("global lock granted for BF: %lld %s",
+ wsrep_thd_thread_id((const void*)requestor_ctx->get_thd()),
+ wsrep_thd_query(requestor_ctx->get_thd()));
+ can_grant= TRUE;
+ }
else
{
Ticket_iterator it(m_granted);
MDL_ticket *ticket;
+ bool wsrep_can_grant= TRUE;
/* Check that the incompatible lock belongs to some other context. */
while ((ticket= it++))
@@ -1582,16 +1582,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
if (ticket->get_ctx() != requestor_ctx &&
ticket->is_incompatible_when_granted(type_arg))
{
-#ifdef WITH_WSREP
- if (wsrep_thd_is_BF(requestor_ctx->get_thd(),false) &&
- key.mdl_namespace() == MDL_key::GLOBAL)
- {
- WSREP_DEBUG("global lock granted for BF: %lu %s",
- thd_get_thread_id(requestor_ctx->get_thd()),
- wsrep_thd_query(requestor_ctx->get_thd()));
- can_grant = true;
- }
- else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key))
+ if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key))
{
wsrep_can_grant= FALSE;
if (wsrep_log_conflicts)
@@ -1603,21 +1594,33 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
"abort" );
}
}
- else
- can_grant= TRUE;
- /* Continue loop */
+ }
+ }
+ if (wsrep_can_grant)
+ can_grant= TRUE;
+ }
#else
+ else
+ {
+ Ticket_iterator it(m_granted);
+ MDL_ticket *ticket;
+
+ /* Check that the incompatible lock belongs to some other context. */
+ while ((ticket= it++))
+ {
+ if (ticket->get_ctx() != requestor_ctx &&
+ ticket->is_incompatible_when_granted(type_arg))
break;
-#endif /* WITH_WSREP */
- }
}
- if ((ticket == NULL) && wsrep_can_grant)
- can_grant= TRUE; /* Incompatible locks are our own. */
+ if (ticket == NULL) /* Incompatible locks are our own. */
+ can_grant= TRUE;
}
+#endif /* WITH_WSREP */
}
+#ifdef WITH_WSREP
else
{
- if (wsrep_thd_is_BF(requestor_ctx->get_thd(), false) &&
+ if (wsrep_thd_is_BF((void*)requestor_ctx->get_thd(), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",
@@ -1626,6 +1629,8 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
can_grant = true;
}
}
+#endif /* WITH_WSREP */
+
return can_grant;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 76455177a6e..0758603a810 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -70,10 +70,13 @@
#include "scheduler.h"
#include <waiting_threads.h>
#include "debug_sync.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
#include "wsrep_mysqld.h"
#include "wsrep_var.h"
#include "wsrep_thd.h"
#include "wsrep_sst.h"
+#endif /* WITH_WSREP */
#include "proxy_protocol.h"
#include "sql_callback.h"
@@ -1554,7 +1557,6 @@ ATTRIBUTE_NORETURN static void mysqld_exit(int exit_code);
static void delete_pid_file(myf flags);
static void end_ssl();
-
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
** Code to end mysqld
@@ -1656,11 +1658,12 @@ static void close_connections(void)
#ifdef WITH_WSREP
/* skip wsrep system threads as well */
- if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier))
+ if (WSREP(tmp) && (wsrep_thd_is_applying(tmp) || tmp->wsrep_applier))
continue;
#endif
tmp->set_killed(KILL_SERVER_HARD);
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data);
mysql_mutex_lock(&tmp->LOCK_thd_kill);
if (tmp->mysys_var)
{
@@ -1685,6 +1688,7 @@ static void close_connections(void)
mysql_mutex_unlock(&tmp->mysys_var->mutex);
}
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
+ if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data);
}
mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
@@ -1747,7 +1751,7 @@ static void close_connections(void)
* The code here makes sure mysqld will not hang during shutdown
* even if wsrep provider has problems in shutting down.
*/
- if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV)
+ if (WSREP(tmp) && wsrep_thd_is_applying(tmp))
{
sql_print_information("closing wsrep system thread");
tmp->set_killed(KILL_CONNECTION);
@@ -1770,6 +1774,13 @@ static void close_connections(void)
mysql_mutex_unlock(&LOCK_thread_count);
}
end_slave();
+#ifdef WITH_WSREP
+ if (wsrep_inited == 1)
+ {
+ wsrep_deinit();
+ wsrep_deinit_server();
+ }
+#endif
/* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
mysql_mutex_lock(&LOCK_thread_count);
@@ -1927,14 +1938,18 @@ static void kill_server(int sig)
/* Stop wsrep threads in case they are running. */
if (wsrep_running_threads > 0)
{
- wsrep_stop_replication(NULL);
+ wsrep_shutdown_replication();
}
close_connections();
+#ifdef WITH_WSREP
if (wsrep_inited == 1)
- wsrep_deinit(true);
-
+ {
+ wsrep_deinit();
+ wsrep_deinit_server();
+ }
+#endif
if (sig != MYSQL_KILL_SIGNAL &&
sig != 0)
unireg_abort(1); /* purecov: inspected */
@@ -2016,8 +2031,7 @@ extern "C" void unireg_abort(int exit_code)
disable_log_notes= 1;
#ifdef WITH_WSREP
- /* Check if wsrep class is used. If yes, then cleanup wsrep */
- if (wsrep)
+ if (Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected)
{
/*
This is an abort situation, we cannot expect to gracefully close all
@@ -2025,7 +2039,7 @@ extern "C" void unireg_abort(int exit_code)
*/
wsrep_close_client_connections(FALSE);
shutdown_in_progress= 1;
- wsrep->disconnect(wsrep);
+ Wsrep_server_state::instance().disconnect();
WSREP_INFO("Service disconnected.");
wsrep_close_threads(NULL); /* this won't close all threads */
sleep(1); /* so give some time to exit for those which can */
@@ -2033,7 +2047,10 @@ extern "C" void unireg_abort(int exit_code)
/* In bootstrap mode we deinitialize wsrep here. */
if (opt_bootstrap && wsrep_inited)
- wsrep_deinit(true);
+ {
+ wsrep_deinit();
+ wsrep_deinit_server();
+ }
}
#endif // WITH_WSREP
@@ -2078,7 +2095,9 @@ static void mysqld_exit(int exit_code)
#ifdef SAFEMALLOC
sf_report_leaked_memory(0);
#endif
+#ifdef TODO
DBUG_SLOW_ASSERT(global_status_var.global_memory_used == 0);
+#endif
}
cleanup_tls();
DBUG_LEAVE;
@@ -2772,6 +2791,14 @@ void signal_thd_deleted()
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
}
+ else
+ {
+ /* Naah, I signal anyways */
+ WSREP_DEBUG("forced signal for COND_thread_count");
+ mysql_mutex_lock(&LOCK_thread_count);
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
+ }
}
@@ -5117,7 +5144,8 @@ static int init_server_components()
wsrep_thr_init();
#endif
- if (WSREP_ON && !wsrep_recovery && !opt_abort) /* WSREP BEFORE SE */
+ if (wsrep_init_server()) unireg_abort(1);
+ if (!wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
@@ -5827,24 +5855,12 @@ int mysqld_main(int argc, char **argv)
}
else
{
- wsrep_SE_initialized();
-
- if (wsrep_before_SE())
- {
- /*! in case of no SST wsrep waits in view handler callback */
- wsrep_SE_init_grab();
- wsrep_SE_init_done();
- /*! in case of SST wsrep waits for wsrep->sst_received */
- if (wsrep_sst_continue())
- {
- WSREP_ERROR("Failed to signal the wsrep provider to continue.");
- }
- }
- else
+ if (!wsrep_before_SE())
{
wsrep_init_startup (false);
}
+ wsrep_init_globals();
wsrep_create_appliers(wsrep_slave_threads - 1);
}
}
@@ -8158,6 +8174,20 @@ SHOW_VAR status_vars[]= {
{"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC},
#endif
#ifdef WITH_WSREP
+ {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL},
+ {"wsrep_ready", (char*) &wsrep_show_ready, SHOW_FUNC},
+ {"wsrep_cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
+ {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
+ {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},
+ {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH},
+ {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH},
+ {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC},
+ {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
+ {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
+ {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
+ {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
+ {"wsrep_thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH},
+ {"wsrep_cluster_capabilities", (char*) &wsrep_cluster_capabilities, SHOW_CHAR_PTR},
{"wsrep", (char*) &wsrep_show_status, SHOW_FUNC},
#endif
{NullS, NullS, SHOW_LONG}
@@ -9619,8 +9649,7 @@ void refresh_status(THD *thd)
/* Reset some global variables */
reset_status_vars();
#ifdef WITH_WSREP
- if (WSREP_ON)
- wsrep->stats_reset(wsrep);
+ Wsrep_server_state::instance().provider().reset_status();
#endif /* WITH_WSREP */
/* Reset the counters of all key caches (default and named). */
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 7eee9283989..9bb8a31d8c6 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -551,8 +551,24 @@ static uchar *net_store_length_fast(uchar *packet, size_t length)
void Protocol::end_statement()
{
- /* sanity check*/
- DBUG_ASSERT_IF_WSREP(!(WSREP(thd) && thd->wsrep_conflict_state == REPLAYING));
+ /*
+ Commented out: This sanity check does not hold in general.
+ Thd->LOCK_thd_data() must be unlocked before sending response
+ to client, so BF abort may sneak in here.
+ DBUG_ASSERT(!WSREP(thd) || thd->wsrep_conflict_state() == NO_CONFLICT);
+ */
+
+ /*
+ sanity check, don't send end statement while replaying
+ */
+ DBUG_ASSERT(thd->wsrep_trx().state() != wsrep::transaction::s_replaying);
+ if (WSREP(thd) && thd->wsrep_trx().state() ==
+ wsrep::transaction::s_replaying)
+ {
+ WSREP_ERROR("attempting net_end_statement while replaying");
+ return;
+ }
+
DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
bool error= FALSE;
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
new file mode 100644
index 00000000000..1b7dc53203b
--- /dev/null
+++ b/sql/service_wsrep.cc
@@ -0,0 +1,335 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include "mariadb.h"
+
+#include "mysql/service_wsrep.h"
+#include "wsrep/key.hpp"
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h"
+#include "sql_class.h"
+#include "debug_sync.h"
+
+extern "C" my_bool wsrep_global_on()
+{
+ return WSREP_ON;
+}
+
+extern "C" my_bool wsrep_on(const void *thd)
+{
+ return (int)(WSREP(((const THD*)thd)));
+}
+
+extern "C" void wsrep_thd_LOCK(const void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+}
+
+extern "C" void wsrep_thd_UNLOCK(const void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+}
+
+
+extern "C" my_bool wsrep_thd_is_wsrep_on(const void *thd)
+{
+ return ((const THD*)thd)->variables.wsrep_on;
+}
+
+extern "C" my_thread_id wsrep_thd_thread_id(const void *thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return thd->thread_id;
+}
+
+extern "C" const char* wsrep_thd_client_state_str(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return wsrep::to_c_string(thd->wsrep_cs().state());
+}
+
+extern "C" const char* wsrep_thd_client_mode_str(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return wsrep::to_c_string(thd->wsrep_cs().mode());
+}
+
+extern "C" const char* wsrep_thd_transaction_state_str(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return wsrep::to_c_string(thd->wsrep_cs().transaction().state());
+}
+
+
+extern "C" const char *wsrep_thd_query(const void *thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ return (thd) ? thd->query() : NULL;
+}
+
+extern "C" query_id_t wsrep_thd_query_id(const void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ return thd->query_id;
+}
+
+extern "C" query_id_t wsrep_thd_transaction_id(const void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ return thd->wsrep_cs().transaction().id().get();
+}
+
+extern "C" long long wsrep_thd_trx_seqno(const void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ const wsrep::client_state& cs= thd->wsrep_cs();
+ if (cs.mode() == wsrep::client_state::m_toi)
+ {
+ return cs.toi_meta().seqno().get();
+ }
+ else
+ {
+ return cs.transaction().ws_meta().seqno().get();
+ }
+}
+
+extern "C" void wsrep_thd_self_abort(void* thd_ptr)
+{
+ THD* thd= (THD*)thd_ptr;
+ thd->wsrep_cs().bf_abort(wsrep::seqno(0));
+}
+
+extern "C" my_bool wsrep_thd_is_local(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd->wsrep_cs().mode() == wsrep::client_state::m_local);
+}
+
+extern "C" my_bool wsrep_thd_is_applying(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority);
+}
+
+extern "C" my_bool wsrep_thd_is_toi(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd->wsrep_cs().mode() == wsrep::client_state::m_toi);
+}
+
+extern "C" my_bool wsrep_thd_is_local_toi(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd->wsrep_cs().mode() == wsrep::client_state::m_toi &&
+ thd->wsrep_cs().toi_mode() == wsrep::client_state::m_local);
+
+}
+
+extern "C" my_bool wsrep_thd_is_in_rsu(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd->wsrep_cs().mode() == wsrep::client_state::m_rsu);
+}
+
+extern "C" my_bool wsrep_thd_is_BF(const void *thd_ptr, my_bool sync)
+{
+ THD* thd= (THD*)thd_ptr;
+ my_bool status = FALSE;
+ if (thd_ptr)
+ {
+ if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
+ status = (wsrep_thd_is_applying(thd) || wsrep_thd_is_toi(thd));
+ if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+ return status;
+}
+
+extern "C" my_bool wsrep_thd_is_SR(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd && thd->wsrep_cs().transaction().is_streaming());
+}
+
+extern "C" void wsrep_handle_SR_rollback(void *bf_thd_ptr,
+ void *victim_thd_ptr)
+{
+ DBUG_ASSERT(victim_thd_ptr);
+ if (!victim_thd_ptr) return;
+
+ THD* bf_thd= (THD*)bf_thd_ptr;
+ THD* victim_thd= (THD*)victim_thd_ptr;
+ WSREP_DEBUG("handle rollback, for deadlock: thd %llu trx_id %lu frags %lu conf %s",
+ victim_thd->thread_id,
+ victim_thd->wsrep_trx_id(),
+ victim_thd->wsrep_sr().fragments_certified(),
+ wsrep_thd_transaction_state_str(victim_thd));
+ if (bf_thd) victim_thd->store_globals();
+ if (!bf_thd)
+ {
+ DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback");
+ }
+ if (bf_thd)
+ {
+ wsrep_bf_abort(bf_thd, victim_thd);
+ }
+ else
+ {
+ wsrep_thd_self_abort(victim_thd);
+ }
+ if (bf_thd) bf_thd->store_globals();
+}
+
+extern "C" void wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size)
+{
+ const THD *thd= (const THD*)thd_ptr;
+ DBUG_ASSERT(xid_size == sizeof(xid_t));
+ if (xid_size == sizeof(xid_t))
+ {
+ *(xid_t*) xid = thd->wsrep_xid;
+ }
+}
+
+extern "C" void wsrep_thd_awake(const void* thd_ptr, my_bool signal)
+{
+ THD* thd= (THD*)thd_ptr;
+ if (signal)
+ {
+ //mysql_mutex_lock(&thd->LOCK_thd_data);
+ thd->awake(KILL_QUERY);
+ //mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+ else
+ {
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ mysql_cond_broadcast(&COND_wsrep_replaying);
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ }
+}
+
+extern "C" my_bool wsrep_thd_bf_abort(const void* bf_thd_ptr,
+ void* victim_thd_ptr,
+ my_bool signal)
+{
+ const THD* bf_thd= (const THD*)bf_thd_ptr;
+ THD* victim_thd= (THD*)victim_thd_ptr;
+ my_bool ret= wsrep_bf_abort(bf_thd, victim_thd);
+ /*
+ Send awake signal if victim was BF aborted or does not
+ have wsrep on. Note that this should never interrupt RSU
+ as RSU has paused the provider.
+ */
+ if ((ret || !wsrep_on(victim_thd)) && signal)
+ {
+ wsrep_thd_awake((const void*)victim_thd, signal);
+ }
+ return ret;
+}
+
+extern "C" my_bool wsrep_thd_skip_locking(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return thd != NULL && thd->wsrep_skip_locking;
+}
+
+extern "C" my_bool wsrep_thd_order_before(const void *left_ptr,
+ const void *right_ptr)
+{
+ const THD* left= (const THD*)left_ptr;
+ const THD* right= (const THD*)right_ptr;
+ if (wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) {
+ WSREP_DEBUG("BF conflict, order: %lld %lld\n",
+ (long long)wsrep_thd_trx_seqno(left),
+ (long long)wsrep_thd_trx_seqno(right));
+ return TRUE;
+ }
+ WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
+ (long long)wsrep_thd_trx_seqno(left),
+ (long long)wsrep_thd_trx_seqno(right));
+ return FALSE;
+}
+
+extern "C" my_bool wsrep_thd_is_high_priority(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ return (thd != 0 && thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority);
+}
+
+extern "C" my_bool wsrep_thd_is_aborting(const void* thd_ptr)
+{
+ const THD* thd= (const THD*)thd_ptr;
+ mysql_mutex_assert_owner(&thd->LOCK_thd_data);
+ if (thd != 0)
+ {
+ const wsrep::client_state& cs(thd->wsrep_cs());
+ const enum wsrep::transaction::state tx_state(cs.transaction().state());
+ switch (tx_state)
+ {
+ case wsrep::transaction::s_must_abort:
+ return (cs.state() == wsrep::client_state::s_exec ||
+ cs.state() == wsrep::client_state::s_result);
+ case wsrep::transaction::s_aborting:
+ case wsrep::transaction::s_aborted:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+static inline enum wsrep::key::type
+map_key_type(enum Wsrep_key_type type)
+{
+ switch (type)
+ {
+ case wsrep_key_shared: return wsrep::key::shared;
+ case wsrep_key_semi_shared: return wsrep::key::semi_shared;
+ case wsrep_key_semi_exclusive: return wsrep::key::semi_exclusive;
+ case wsrep_key_exclusive: return wsrep::key::exclusive;
+ }
+ return wsrep::key::exclusive;
+}
+
+extern "C" int wsrep_thd_append_key(void* thd_ptr,
+ const struct wsrep_key* key,
+ int n_keys,
+ enum Wsrep_key_type key_type)
+{
+ THD* thd= (THD*)thd_ptr;
+ Wsrep_client_state& client_state(thd->wsrep_cs());
+ DBUG_ASSERT(client_state.transaction().active());
+ int ret= 0;
+ for (int i= 0; i < n_keys && ret == 0; ++i)
+ {
+ wsrep::key wsrep_key(map_key_type(key_type));
+ for (size_t kp= 0; kp < key[i].key_parts_num; ++kp)
+ {
+ wsrep_key.append_key_part(key[i].key_parts[kp].ptr, key[i].key_parts[kp].len);
+ }
+ ret= client_state.append_key(wsrep_key);
+ }
+ return ret;
+}
+
+extern "C" long long get_wsrep_xid_seqno(const struct xid_t* xid)
+{
+ return wsrep_xid_seqno(*xid).get();
+}
+
+extern const unsigned char* get_wsrep_xid_uuid(const struct xid_t* xid)
+{
+ return (const unsigned char*)wsrep_xid_uuid(*xid).data();
+}
diff --git a/sql/slave.cc b/sql/slave.cc
index bb1300d36e6..391d7b846f8 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -53,6 +53,10 @@
// Create_file_log_event,
// Format_description_log_event
#include "wsrep_mysqld.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#include "wsrep_trans_observer.h"
+#endif
#ifdef HAVE_REPLICATION
@@ -3917,14 +3921,20 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi,
exec_res= ev->apply_event(rgi);
#ifdef WITH_WSREP
- if (exec_res && thd->wsrep_conflict_state != NO_CONFLICT)
+ if (WSREP_ON)
+ {
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (exec_res &&
+ thd->wsrep_trx().state() != wsrep::transaction::s_executing)
{
- WSREP_DEBUG("SQL apply failed, res %d conflict state: %d",
- exec_res, thd->wsrep_conflict_state);
+ WSREP_DEBUG("SQL apply failed, res %d conflict state: %s",
+ exec_res, wsrep_thd_transaction_state_str(thd));
rli->abort_slave= 1;
rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR, rgi->gtid_info(),
"Node has dropped from cluster");
}
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
#endif
#ifndef DBUG_OFF
@@ -4217,6 +4227,13 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
}
if (ev)
{
+#ifdef WITH_WSREP
+ if (wsrep_before_statement(thd))
+ {
+ WSREP_INFO("Wsrep before statement error");
+ DBUG_RETURN(1);
+ }
+#endif /* WITH_WSREP */
int exec_res;
Log_event_type typ= ev->get_type_code();
@@ -4248,9 +4265,9 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) &&
(ev->server_id != global_system_variables.server_id ||
rli->replicate_same_server_id) &&
- rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos)
- ? rli->group_master_log_pos
- : ev->log_pos - ev->data_written))
+ rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos)
+ ? rli->group_master_log_pos
+ : ev->log_pos - ev->data_written))
{
sql_print_information("Slave SQL thread stopped because it reached its"
" UNTIL position %llu", rli->until_pos());
@@ -4261,6 +4278,9 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
rli->abort_slave= 1;
rli->stop_for_until= true;
mysql_mutex_unlock(&rli->data_lock);
+#ifdef WITH_WSREP
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
delete ev;
DBUG_RETURN(1);
}
@@ -4298,7 +4318,14 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
if (res == 0)
rli->event_relay_log_pos= rli->future_event_relay_log_pos;
if (res >= 0)
+#ifdef WITH_WSREP
+ {
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(res);
+#ifdef WITH_WSREP
+ }
+#endif /* WITH_WSREP */
/*
Else we proceed to execute the event non-parallel.
This is the case for pre-10.0 events without GTID, and for handling
@@ -4320,9 +4347,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
"aborted because of out-of-memory error");
mysql_mutex_unlock(&rli->data_lock);
delete ev;
+#ifdef WITH_WSREP
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(1);
}
-
if (opt_gtid_ignore_duplicates &&
rli->mi->using_gtid != Master_info::USE_GTID_NO)
{
@@ -4334,7 +4363,10 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
"thread aborted because of out-of-memory error");
mysql_mutex_unlock(&rli->data_lock);
delete ev;
- DBUG_RETURN(1);
+#ifdef WITH_WSREP
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
+ DBUG_RETURN(1);
}
/*
If we need to skip this event group (because the GTID was already
@@ -4362,11 +4394,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
retry.
*/
if (unlikely(exec_res == 2))
+#ifdef WITH_WSREP
+ {
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(1);
-
#ifdef WITH_WSREP
+ }
mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == NO_CONFLICT)
+ if (thd->wsrep_cs().current_error() == wsrep::e_success)
{
mysql_mutex_unlock(&thd->LOCK_thd_data);
#endif /* WITH_WSREP */
@@ -4381,8 +4417,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
We were in a transaction which has been rolled back because of a
temporary error;
let's seek back to BEGIN log event and retry it all again.
- Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
- there is no rollback since 5.0.13 (ref: manual).
+ Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
+ there is no rollback since 5.0.13 (ref: manual).
We have to not only seek but also
a) init_master_info(), to seek back to hot relay log's start
@@ -4450,7 +4486,10 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
#endif /* WITH_WSREP */
thread_safe_increment64(&rli->executed_entries);
- DBUG_RETURN(exec_res);
+#ifdef WITH_WSREP
+ wsrep_after_statement(thd);
+#endif /* WITH_WSREP */
+ DBUG_RETURN(exec_res);
}
mysql_mutex_unlock(&rli->data_lock);
rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE, NULL,
@@ -5376,12 +5415,6 @@ pthread_handler_t handle_slave_sql(void *arg)
}
#endif
-#ifdef WITH_WSREP
- thd->wsrep_exec_mode= LOCAL_STATE;
- /* synchronize with wsrep replication */
- if (WSREP_ON)
- wsrep_ready_wait();
-#endif
DBUG_PRINT("master_info",("log_file_name: %s position: %llu",
rli->group_master_log_name,
rli->group_master_log_pos));
@@ -5515,10 +5548,16 @@ pthread_handler_t handle_slave_sql(void *arg)
if (exec_relay_log_event(thd, rli, serial_rgi))
{
#ifdef WITH_WSREP
- if (thd->wsrep_conflict_state != NO_CONFLICT)
+ if (WSREP_ON)
{
- wsrep_node_dropped= TRUE;
- rli->abort_slave= TRUE;
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+
+ if (thd->wsrep_cs().current_error())
+ {
+ wsrep_node_dropped = TRUE;
+ rli->abort_slave = TRUE;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
}
#endif /* WITH_WSREP */
@@ -5551,6 +5590,10 @@ pthread_handler_t handle_slave_sql(void *arg)
"log '%s' at position %llu%s", RPL_LOG_NAME,
rli->group_master_log_pos, tmp.c_ptr_safe());
}
+#ifdef WITH_WSREP
+ wsrep_after_command_before_result(thd);
+ wsrep_after_command_after_result(thd);
+#endif /* WITH_WSREP */
err_before_start:
@@ -5662,24 +5705,23 @@ pthread_handler_t handle_slave_sql(void *arg)
trigger automatic restart of slave when node joins back to cluster.
*/
if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
- {
- if (wsrep_ready_get())
- {
- WSREP_INFO("Slave error due to node temporarily non-primary"
- "SQL slave will continue");
- wsrep_node_dropped= FALSE;
- mysql_mutex_unlock(&rli->run_lock);
- WSREP_DEBUG("wsrep_conflict_state now: %d", thd->wsrep_conflict_state);
- WSREP_INFO("slave restart: %d", thd->wsrep_conflict_state);
- thd->wsrep_conflict_state= NO_CONFLICT;
- goto wsrep_restart_point;
- } else {
- WSREP_INFO("Slave error due to node going non-primary");
- WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
- "automatically restarted when node joins back to cluster.");
- wsrep_restart_slave_activated= TRUE;
- }
- }
+ {
+ if (wsrep_ready_get())
+ {
+ WSREP_INFO("Slave error due to node temporarily non-primary"
+ "SQL slave will continue");
+ wsrep_node_dropped= FALSE;
+ mysql_mutex_unlock(&rli->run_lock);
+ goto wsrep_restart_point;
+ } else {
+ WSREP_INFO("Slave error due to node going non-primary");
+ WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
+ "automatically restarted when node joins back to cluster");
+ wsrep_restart_slave_activated= TRUE;
+ }
+ }
+ // TODO 10.4 has deleted following line:
+ //wsrep_close(thd);
#endif /* WITH_WSREP */
/*
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c86edc47bf9..b769868119e 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -44,6 +44,7 @@
#include "transaction.h" // trans_commit_stmt
#include "sql_audit.h"
#include "debug_sync.h"
+#include "wsrep_trans_observer.h"
/*
Sufficient max length of printed destinations and frame offsets (all uints).
@@ -51,7 +52,6 @@
#define SP_INSTR_UINT_MAXLEN 8
#define SP_STMT_PRINT_MAXLEN 40
-
#include <my_user.h>
extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first);
@@ -1324,6 +1324,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
sql_digest_state *parent_digest= thd->m_digest;
thd->m_digest= NULL;
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ WSREP_DEBUG("assigned new next trx ID for SP, trx id: %lu", thd->wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
err_status= i->execute(thd, &ip);
thd->m_digest= parent_digest;
@@ -3566,6 +3573,24 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp)
(char *)thd->security_ctx->host_or_ip,
3);
int res= mysql_execute_command(thd);
+#ifdef WITH_WSREP
+ if ((thd->is_fatal_error || thd->killed_errno()) &&
+ (thd->wsrep_trx().state() == wsrep::transaction::s_executing))
+ {
+ /*
+ SP was killed, and it is not due to a wsrep conflict.
+ We skip after_command hook at this point because
+ otherwise it clears the error, and cleans up the
+ whole transaction. For now we just return and finish
+ our handling once we are back to mysql_parse.
+ */
+ WSREP_DEBUG("Skipping after_command hook for killed SP");
+ }
+ else
+ {
+ (void) wsrep_after_statement(thd);
+ }
+#endif /* WITH_WSREP */
MYSQL_QUERY_EXEC_DONE(res);
*nextp= m_ip+1;
return res;
@@ -4501,8 +4526,8 @@ int
sp_instr_error::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_error::execute");
-
my_message(m_errcode, ER_THD(thd, m_errcode), MYF(0));
+ WSREP_DEBUG("sp_instr_error: %s %d", ER_THD(thd, m_errcode), thd->is_error());
*nextp= m_ip+1;
DBUG_RETURN(-1);
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index bf18581de4f..5fd0ddce1d4 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -54,6 +54,9 @@
#include "sql_array.h"
#include "sql_hset.h"
#include "password.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP */
#include "sql_plugin_compat.h"
@@ -3339,7 +3342,6 @@ bool change_password(THD *thd, LEX_USER *user)
WSREP_TO_ISOLATION_END;
thd->set_query(query_save);
- thd->wsrep_exec_mode = LOCAL_STATE;
}
#endif /* WITH_WSREP */
thd->restore_stmt_binlog_format(save_binlog_format);
@@ -3502,7 +3504,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
WSREP_TO_ISOLATION_END;
thd->set_query(query_save);
- thd->wsrep_exec_mode = LOCAL_STATE;
}
#endif /* WITH_WSREP */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 220fcf6cc34..9d2c6b81169 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -61,8 +61,12 @@
#ifdef __WIN__
#include <io.h>
#endif
+#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h"
+#endif /* WITH_WSREP */
+
bool
No_such_table_error_handler::handle_condition(THD *,
@@ -874,10 +878,19 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
The metadata lock must be released after giving back
the table to the table cache.
*/
- DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+#ifdef WITH_WSREP
+ /* if SR thread was aborted, MDL locks were released early */
+ DBUG_ASSERT(thd->variables.wsrep_trx_fragment_size > 0 ||
+ thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+ table->s->db.str,
+ table->s->table_name.str,
+ MDL_SHARED));
+#else
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
table->s->db.str,
table->s->table_name.str,
MDL_SHARED));
+#endif /* WITH_WSSREP */
table->mdl_ticket= NULL;
if (table->file)
@@ -3859,7 +3872,7 @@ lock_table_names(THD *thd, const DDL_options_st &options,
if (create_table)
#ifdef WITH_WSREP
if (thd->lex->sql_command != SQLCOM_CREATE_TABLE &&
- thd->wsrep_exec_mode != REPL_RECV)
+ !thd->wsrep_applier)
#endif
lock_wait_timeout= 0; // Don't wait for timeout
}
@@ -4281,8 +4294,8 @@ bool open_tables(THD *thd, const DDL_options_st &options,
(*start) &&
(*start)->table &&
(*start)->table->file->ht == myisam_hton &&
- wsrep_thd_exec_mode(thd) == LOCAL_STATE &&
- !is_stat_table(&(*start)->db, &(*start)->alias) &&
+ wsrep_thd_is_local(thd) &&
+ !is_stat_table(&(*start)->db, &(*start)->alias) &&
thd->get_command() != COM_STMT_PREPARE &&
((thd->lex->sql_command == SQLCOM_INSERT ||
thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
@@ -4293,7 +4306,10 @@ bool open_tables(THD *thd, const DDL_options_st &options,
thd->lex->sql_command == SQLCOM_LOAD ||
thd->lex->sql_command == SQLCOM_DELETE)))
{
- WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start));
+ wsrep_before_rollback(thd, true);
+ wsrep_after_rollback(thd, true);
+ wsrep_after_statement(thd);
+ WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start));
}
error:
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index a4ecdfb1297..a3cabaf7c5d 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -65,10 +65,15 @@
#include "sql_parse.h" // is_update_query
#include "sql_callback.h"
#include "lock.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+//#include "wsrep_client_service.h"
#include "wsrep_mysqld.h"
+#include "wsrep_binlog.h" /* wsrep_fragment_unit() */
#include "wsrep_thd.h"
#include "sql_connect.h"
#include "my_atomic.h"
+#endif /* WITH_WSREP */
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
@@ -533,6 +538,12 @@ char *thd_security_context(THD *thd,
return thd_get_error_context_description(thd, buffer, length, max_query_len);
}
#endif
+#ifdef WITH_WSREP
+extern "C" bool wsrep_consistency_check(void *thd)
+{
+ return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
+}
+#endif /* WITH_WSREP */
/**
Implementation of Drop_table_error_handler::handle_condition().
@@ -628,6 +639,27 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
derived_tables_processing(FALSE),
waiting_on_group_commit(FALSE), has_waiter(FALSE),
spcont(NULL),
+#ifdef WITH_WSREP
+ m_wsrep_mutex(LOCK_thd_data),
+ m_wsrep_cond(COND_wsrep_thd),
+ wsrep_applier(is_wsrep_applier),
+ wsrep_applier_closing(false),
+ wsrep_client_thread(false),
+ wsrep_apply_toi(false),
+ wsrep_po_handle(WSREP_PO_INITIALIZER),
+ wsrep_po_cnt(0),
+ wsrep_apply_format(0),
+ wsrep_ignore_table(false),
+
+/* wsrep-lib */
+ m_wsrep_client_service(this, m_wsrep_client_state),
+ m_wsrep_client_state(this,
+ m_wsrep_mutex,
+ m_wsrep_cond,
+ Wsrep_server_state::instance(),
+ m_wsrep_client_service,
+ wsrep::client_id(thread_id)),
+#endif /*WITH_WSREP */
m_parser_state(NULL),
#if defined(ENABLED_DEBUG_SYNC)
debug_sync_control(0),
@@ -639,17 +671,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
tdc_hash_pins(0),
xid_hash_pins(0),
m_tmp_tables_locked(false)
-#ifdef WITH_WSREP
- ,
- wsrep_applier(is_wsrep_applier),
- wsrep_applier_closing(false),
- wsrep_client_thread(false),
- wsrep_apply_toi(false),
- wsrep_po_handle(WSREP_PO_INITIALIZER),
- wsrep_po_cnt(0),
- wsrep_apply_format(0),
- wsrep_ignore_table(false)
-#endif
{
ulong tmp;
bzero(&variables, sizeof(variables));
@@ -771,8 +792,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
*scramble= '\0';
#ifdef WITH_WSREP
- wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID;
- wsrep_ws_handle.opaque = NULL;
+ mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL);
wsrep_retry_counter = 0;
wsrep_PA_safe = true;
wsrep_retry_query = NULL;
@@ -782,9 +802,14 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0;
+ wsrep_rbr_buf = NULL;
+ wsrep_nbo_ctx = NULL;
+
wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */
wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED;
wsrep_affected_rows = 0;
+ wsrep_has_ignored_error = false;
+ m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID;
wsrep_replicate_GTID = false;
wsrep_skip_wsrep_GTID = false;
#endif
@@ -1049,10 +1074,25 @@ Sql_condition* THD::raise_condition(uint sql_errno,
is_slave_error= 1; // needed to catch query errors during replication
- if (!da->is_error())
+#ifdef WITH_WSREP
+ /*
+ With wsrep we allow converting BF abort error to warning if
+ errors are ignored.
+ */
+ if (!is_fatal_error &&
+ no_errors &&
+ (wsrep_trx().bf_aborted() || wsrep_retry_counter))
{
- set_row_count_func(-1);
- da->set_error_status(sql_errno, msg, sqlstate, ucid, cond);
+ WSREP_DEBUG("BF abort error converted to warning");
+ }
+ else
+#endif /* WITH_WSREP */
+ {
+ if (!da->is_error())
+ {
+ set_row_count_func(-1);
+ da->set_error_status(sql_errno, msg, sqlstate, ucid, cond);
+ }
}
}
@@ -1220,12 +1260,10 @@ void THD::init(bool skip_lock)
first_successful_insert_id_in_prev_stmt_for_binlog= 0;
first_successful_insert_id_in_cur_stmt= 0;
#ifdef WITH_WSREP
- wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE;
- wsrep_conflict_state= NO_CONFLICT;
- wsrep_query_state= QUERY_IDLE;
+ mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL);
wsrep_last_query_id= 0;
- wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
- wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED;
+ wsrep_xid.null();
+ wsrep_skip_locking= FALSE;
wsrep_converted_lock_session= false;
wsrep_retry_counter= 0;
wsrep_rgi= NULL;
@@ -1234,10 +1272,17 @@ void THD::init(bool skip_lock)
wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0;
- wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED;
+ wsrep_rbr_buf = NULL;
+ wsrep_nbo_ctx = NULL;
wsrep_affected_rows = 0;
+ m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID;
wsrep_replicate_GTID = false;
wsrep_skip_wsrep_GTID = false;
+ if (!wsrep_applier && variables.wsrep_trx_fragment_size)
+ {
+ wsrep_cs().enable_streaming(wsrep_fragment_unit(variables.wsrep_trx_fragment_unit),
+ variables.wsrep_trx_fragment_size);
+ }
#endif /* WITH_WSREP */
if (variables.sql_log_bin)
@@ -1460,12 +1505,20 @@ void THD::cleanup(void)
DBUG_ASSERT(cleanup_done == 0);
set_killed(KILL_CONNECTION);
+ DEBUG_SYNC(this, "thd_cleanup_start");
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
if (transaction.xid_state.xa_state == XA_PREPARED)
{
#error xid_state in the cache should be replaced by the allocated value
}
#endif
+#ifdef WITH_WSREP
+ if (wsrep_cs().state() != wsrep::client_state::s_none)
+ {
+ wsrep_cs().cleanup();
+ }
+ wsrep_client_thread= false;
+#endif /* WITH_WSREP */
mysql_ha_cleanup(this);
locked_tables_list.unlock_locked_tables(this);
@@ -1582,6 +1635,10 @@ void THD::reset_for_reuse()
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
#endif
+#ifdef WITH_WSREP
+ mysql_cond_destroy(&COND_wsrep_thd);
+ wsrep_free_status(this);
+#endif /* WITH_WSREP */
}
@@ -1608,15 +1665,20 @@ THD::~THD()
THD is not deleted while they access it. The following mutex_lock
ensures that no one else is using this THD and it's now safe to delete
*/
+ if (WSREP(this)) mysql_mutex_lock(&LOCK_thd_data);
mysql_mutex_lock(&LOCK_thd_kill);
mysql_mutex_unlock(&LOCK_thd_kill);
+ if (WSREP(this)) mysql_mutex_unlock(&LOCK_thd_data);
-#ifdef WITH_WSREP
- delete wsrep_rgi;
-#endif
if (!free_connection_done)
free_connection();
+#ifdef WITH_WSREP
+ if (wsrep_rgi != NULL) {
+ delete wsrep_rgi;
+ wsrep_rgi = NULL;
+ }
+#endif
mdl_context.destroy();
free_root(&transaction.mem_root,MYF(0));
@@ -1798,6 +1860,7 @@ void THD::awake_no_mutex(killed_state state_to_set)
DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d",
this, current_thd, (int) state_to_set));
THD_CHECK_SENTRY(this);
+ if (WSREP(this)) mysql_mutex_assert_owner(&LOCK_thd_data);
mysql_mutex_assert_owner(&LOCK_thd_kill);
print_aborted_warning(3, "KILLED");
@@ -1982,14 +2045,21 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
*/
if (!thd_table->needs_reopen())
{
+#ifdef WITH_WSREP
signalled|= mysql_lock_abort_for_thread(this, thd_table);
- if (WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ if (WSREP_NNULL(this) && wsrep_thd_is_BF((const void*)this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
}
}
+ else
+ {
+#else
+ signalled|= mysql_lock_abort_for_thread(this, thd_table);
+#endif /* WITH_WSREP */
+ }
}
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
@@ -2220,12 +2290,6 @@ void THD::cleanup_after_query()
/* reset table map for multi-table update */
table_map_for_update= 0;
m_binlog_invoker= INVOKER_NONE;
-#ifdef WITH_WSREP
- if (TOTAL_ORDER == wsrep_exec_mode)
- {
- wsrep_exec_mode = LOCAL_STATE;
- }
-#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
if (rgi_slave)
@@ -2233,7 +2297,6 @@ void THD::cleanup_after_query()
#endif
#ifdef WITH_WSREP
- wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
if (!in_active_multi_stmt_transaction())
wsrep_affected_rows= 0;
#endif /* WITH_WSREP */
@@ -4973,11 +5036,13 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
extern "C" int thd_binlog_format(const MYSQL_THD thd)
{
+#ifdef WITH_WSREP
if (WSREP(thd))
{
/* for wsrep binlog format is meaningful also when binlogging is off */
- return (int) thd->wsrep_binlog_format();
+ return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format);
}
+#endif /* WITH_WSREP */
if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG))
return (int) thd->variables.binlog_format;
return BINLOG_FORMAT_UNSPEC;
@@ -5460,6 +5525,10 @@ void THD::set_query_and_id(char *query_arg, uint32 query_length_arg,
set_query_inner(query_arg, query_length_arg, cs);
mysql_mutex_unlock(&LOCK_thd_data);
query_id= new_query_id;
+#ifdef WITH_WSREP
+ set_wsrep_next_trx_id(query_id);
+ WSREP_DEBUG("assigned new next query and trx id: %lu", wsrep_next_trx_id());
+#endif /* WITH_WSREP */
}
/** Assign a new value to thd->mysys_var. */
@@ -5905,9 +5974,27 @@ int THD::decide_logging_format(TABLE_LIST *tables)
binlogging is off, or if the statement is filtered out from the
binlog by filtering rules.
*/
+#ifdef WITH_WSREP
+ if (WSREP_CLIENT_NNULL(this) && variables.wsrep_trx_fragment_size > 0)
+ {
+ if (!is_current_stmt_binlog_format_row())
+ {
+ my_message(ER_NOT_SUPPORTED_YET,
+ "Streaming replication not supported with "
+ "binlog_format=STATEMENT", MYF(0));
+ DBUG_RETURN(-1);
+ }
+ }
+
+ if ((WSREP_EMULATE_BINLOG_NNULL(this) ||
+ (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG))) &&
+ !(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
+ !binlog_filter->db_ok(db.str)))
+#else
if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) &&
!(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
!binlog_filter->db_ok(db.str)))
+#endif /* WITH_WSREP */
{
if (is_bulk_op())
@@ -6229,7 +6316,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
5. Error: Cannot modify table that uses a storage engine
limited to row-logging when binlog_format = STATEMENT
*/
- if (IF_WSREP((!WSREP(this) || wsrep_exec_mode == LOCAL_STATE),1))
+ if (IF_WSREP((!WSREP(this) ||
+ wsrep_cs().mode() == wsrep::client_state::m_local),1))
{
my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), "");
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d8f0a794222..c97c1d55c1a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -61,8 +61,18 @@ void set_thd_stage_info(void *thd,
#include "my_apc.h"
#include "rpl_gtid.h"
+
+#ifdef WITH_WSREP
+/* wsrep-lib */
+#include "wsrep_client_service.h"
+#include "wsrep_client_state.h"
+#include "wsrep_mutex.h"
+#include "wsrep_condition_variable.h"
+
#include "wsrep_mysqld.h"
+class Wsrep_applier_service;
+#endif
class Reprepare_observer;
class Relay_log_info;
struct rpl_group_info;
@@ -706,10 +716,12 @@ typedef struct system_variables
my_bool wsrep_on;
my_bool wsrep_causal_reads;
+ uint wsrep_sync_wait;
+ ulong wsrep_retry_autocommit;
+ ulong wsrep_trx_fragment_size;
+ ulong wsrep_trx_fragment_unit;
+ ulong wsrep_OSU_method;
my_bool wsrep_dirty_reads;
- uint wsrep_sync_wait;
- ulong wsrep_retry_autocommit;
- ulong wsrep_OSU_method;
double long_query_time_double, max_statement_time_double;
my_bool pseudo_slave_mode;
@@ -3208,7 +3220,6 @@ class THD :public Statement,
mysql_bin_log.start_union_events() call.
*/
bool unioned_events_trans;
-
/*
'queries' (actually SP statements) that run under inside this binlog
union have thd->query_id >= first_query_id.
@@ -3216,7 +3227,6 @@ class THD :public Statement,
query_id_t first_query_id;
} binlog_evt_union;
- mysql_cond_t COND_wsrep_thd;
/**
Internal parser state.
Note that since the parser is not re-entrant, we keep only one parser
@@ -3299,9 +3309,15 @@ class THD :public Statement,
void awake_no_mutex(killed_state state_to_set);
void awake(killed_state state_to_set)
{
+ /*
+ mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires
+ to grab LOCK_thd_data here
+ */
+ mysql_mutex_lock(&LOCK_thd_data);
mysql_mutex_lock(&LOCK_thd_kill);
awake_no_mutex(state_to_set);
mysql_mutex_unlock(&LOCK_thd_kill);
+ mysql_mutex_unlock(&LOCK_thd_data);
}
/** Disconnect the associated communication endpoint. */
@@ -4480,6 +4496,13 @@ class THD :public Statement,
void set_query_id(query_id_t new_query_id)
{
query_id= new_query_id;
+#ifdef WITH_WSREP
+ if (WSREP(this))
+ {
+ set_wsrep_next_trx_id(query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
}
void set_open_tables(TABLE *open_tables_arg)
{
@@ -4739,48 +4762,112 @@ class THD :public Statement,
}
#ifdef WITH_WSREP
- const bool wsrep_applier; /* dedicated slave applier thread */
+ bool wsrep_applier; /* dedicated slave applier thread */
bool wsrep_applier_closing; /* applier marked to close */
bool wsrep_client_thread; /* to identify client threads*/
- bool wsrep_PA_safe;
- bool wsrep_converted_lock_session;
- bool wsrep_apply_toi; /* applier processing in TOI */
- enum wsrep_exec_mode wsrep_exec_mode;
query_id_t wsrep_last_query_id;
- enum wsrep_query_state wsrep_query_state;
- enum wsrep_conflict_state wsrep_conflict_state;
- wsrep_trx_meta_t wsrep_trx_meta;
+ XID wsrep_xid;
+
+ /** This flag denotes that record locking should be skipped during INSERT
+ and gap locking during SELECT. Only used by the streaming replication thread
+ that only modifies the wsrep_schema.SR table. */
+ my_bool wsrep_skip_locking;
+
+ mysql_cond_t COND_wsrep_thd;
+
+ // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75
uint32 wsrep_rand;
- Relay_log_info *wsrep_rli;
rpl_group_info *wsrep_rgi;
- wsrep_ws_handle_t wsrep_ws_handle;
+ bool wsrep_converted_lock_session;
+ char wsrep_info[128]; /* string for dynamic proc info */
ulong wsrep_retry_counter; // of autocommit
- char *wsrep_retry_query;
+ bool wsrep_PA_safe;
+ char* wsrep_retry_query;
size_t wsrep_retry_query_len;
enum enum_server_command wsrep_retry_command;
- enum wsrep_consistency_check_mode
+ enum wsrep_consistency_check_mode
wsrep_consistency_check;
+ std::vector<wsrep::provider::status_variable> wsrep_status_vars;
int wsrep_mysql_replicated;
- const char *wsrep_TOI_pre_query; /* a query to apply before
- the actual TOI query */
+ const char* wsrep_TOI_pre_query; /* a query to apply before
+ the actual TOI query */
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 */
+#endif /* GTID_SUPPORT */
void *wsrep_apply_format;
- char wsrep_info[128]; /* string for dynamic proc info */
+ bool wsrep_apply_toi; /* applier processing in TOI */
+ uchar* wsrep_rbr_buf;
+ Wsrep_nbo_ctx* wsrep_nbo_ctx; // Context for non-blocking operations
+ wsrep_gtid_t wsrep_sync_wait_gtid;
+ // wsrep_gtid_t wsrep_last_written_gtid;
+ ulong wsrep_affected_rows;
+ bool wsrep_has_ignored_error;
+ bool wsrep_replicate_GTID;
+ bool wsrep_skip_wsrep_GTID;
+
/*
When enabled, do not replicate/binlog updates from the current table that's
being processed. At the moment, it is used to keep mysql.gtid_slave_pos
table updates from being replicated to other nodes via galera replication.
*/
bool wsrep_ignore_table;
- wsrep_gtid_t wsrep_sync_wait_gtid;
- ulong wsrep_affected_rows;
- bool wsrep_replicate_GTID;
- bool wsrep_skip_wsrep_GTID;
+
+
+ /*
+ Transaction id:
+ * m_wsrep_next_trx_id is assigned on the first query after
+ wsrep_next_trx_id() return WSREP_UNDEFINED_TRX_ID
+ * Each storage engine must assign value of wsrep_next_trx_id()
+ when the transaction starts.
+ * Effective transaction id is returned via wsrep_trx_id()
+ */
+ /*
+ Return effective transaction id
+ */
+ wsrep_trx_id_t wsrep_trx_id() const
+ {
+ return m_wsrep_client_state.transaction().id().get();
+ }
+
+
+ /*
+ Set next trx id
+ */
+ void set_wsrep_next_trx_id(query_id_t query_id)
+ {
+ m_wsrep_next_trx_id = (wsrep_trx_id_t) query_id;
+ }
+ /*
+ Return next trx id
+ */
+ wsrep_trx_id_t wsrep_next_trx_id() const
+ {
+ return m_wsrep_next_trx_id;
+ }
+
+private:
+ wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */
+ /* wsrep-lib */
+ Wsrep_mutex m_wsrep_mutex;
+ Wsrep_condition_variable m_wsrep_cond;
+ Wsrep_client_service m_wsrep_client_service;
+ Wsrep_client_state m_wsrep_client_state;
+
+public:
+ Wsrep_client_state& wsrep_cs() { return m_wsrep_client_state; }
+ const Wsrep_client_state& wsrep_cs() const { return m_wsrep_client_state; }
+ const wsrep::transaction& wsrep_trx() const
+ { return m_wsrep_client_state.transaction(); }
+ const wsrep::streaming_context& wsrep_sr() const
+ { return m_wsrep_client_state.transaction().streaming_context(); }
+ /* Pointer to applier service for streaming THDs. This is needed to
+ be able to delete applier service object in case of background
+ rollback. */
+ Wsrep_applier_service* wsrep_applier_service;
#endif /* WITH_WSREP */
/* Handling of timeouts for commands */
@@ -6271,7 +6358,7 @@ class select_dumpvar :public select_result_interceptor {
be rolled back or that do not expect any previously metadata
locked tables.
*/
-#define CF_IMPLICT_COMMIT_BEGIN (1U << 6)
+#define CF_IMPLICIT_COMMIT_BEGIN (1U << 6)
/**
Implicitly commit after the SQL statement.
@@ -6289,7 +6376,7 @@ class select_dumpvar :public select_result_interceptor {
before and after every DDL statement and any statement that
modifies our currently non-transactional system tables.
*/
-#define CF_AUTO_COMMIT_TRANS (CF_IMPLICT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END)
+#define CF_AUTO_COMMIT_TRANS (CF_IMPLICIT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END)
/**
Diagnostic statement.
@@ -6333,6 +6420,13 @@ class select_dumpvar :public select_result_interceptor {
*/
#define CF_DISALLOW_IN_RO_TRANS (1U << 15)
+#ifdef WITH_WSREP
+/**
+ DDL statement that may be subject to error filtering.
+*/
+#define CF_WSREP_MAY_IGNORE_ERRORS (1U << 24)
+#endif /* WITH_WSREP */
+
/**
Statement that need the binlog format to be unchanged.
*/
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index b48070b9c8f..90cb7e9d76f 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -37,7 +37,11 @@
// reset_host_errors
#include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL
#include "sql_callback.h"
+
+#ifdef WITH_WSREP
+#include "wsrep_trans_observer.h" /* wsrep open/close */
#include "wsrep_mysqld.h"
+#endif /* WITH_WSREP */
#include "proxy_protocol.h"
HASH global_user_stats, global_client_stats, global_table_stats;
@@ -1177,17 +1181,6 @@ bool login_connection(THD *thd)
void end_connection(THD *thd)
{
NET *net= &thd->net;
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id);
- if (rcode) {
- WSREP_WARN("wsrep failed to free connection context: %lld code: %d",
- (longlong) thd->thread_id, rcode);
- }
- }
- thd->wsrep_client_thread= 0;
-#endif
plugin_thdvar_cleanup(thd);
if (thd->user_connect)
@@ -1322,7 +1315,7 @@ bool thd_prepare_connection(THD *thd)
prepare_new_connection_state(thd);
#ifdef WITH_WSREP
- thd->wsrep_client_thread= 1;
+ thd->wsrep_client_thread= true;
#endif /* WITH_WSREP */
return FALSE;
}
@@ -1384,7 +1377,6 @@ void do_handle_one_connection(CONNECT *connect)
thd->thread_stack= (char*) &thd;
if (setup_connection_thread_globals(thd))
return;
-
for (;;)
{
bool create_user= TRUE;
@@ -1395,6 +1387,9 @@ void do_handle_one_connection(CONNECT *connect)
create_user= FALSE;
goto end_thread;
}
+#ifdef WITH_WSREP
+ wsrep_open(thd);
+#endif /* WITH_WSREP */
while (thd_is_connection_alive(thd))
{
@@ -1405,13 +1400,9 @@ void do_handle_one_connection(CONNECT *connect)
end_connection(thd);
#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXITING;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif
+ wsrep_close(thd);
+#endif /* WITH_WSREP */
+
end_thread:
close_connection(thd);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 51acf10a98a..ff4ebc8d986 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -82,6 +82,11 @@
#include "debug_sync.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#include "wsrep_trans_observer.h" /* wsrep_start_transction() */
+#endif /* WITH_WSREP */
+
#ifndef EMBEDDED_LIBRARY
static bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
TABLE_LIST *table_list);
@@ -3902,10 +3907,13 @@ bool select_insert::prepare_eof()
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
trans_table, table->file->table_type()));
- error= (IF_WSREP((thd->wsrep_conflict_state == MUST_ABORT ||
- thd->wsrep_conflict_state == CERT_FAILURE) ? -1 :, )
- (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
- table->file->ha_end_bulk_insert() : 0));
+#ifdef WITH_WSREP
+ error= (thd->wsrep_cs().current_error()) ? -1 :
+ (thd->locked_tables_mode <= LTM_LOCK_TABLES) ?
+#else
+ error= (thd->locked_tables_mode <= LTM_LOCK_TABLES) ?
+#endif /* WITH_WSREP */
+ table->file->ha_end_bulk_insert() : 0;
if (likely(!error) && unlikely(thd->is_error()))
error= thd->get_stmt_da()->sql_errno();
@@ -4504,9 +4512,10 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
/* suppress_use */ FALSE,
errcode);
}
-
- ha_fake_trx_id(thd);
-
+#ifdef WITH_WSREP
+ // ha_wsrep_fake_trx_id(thd);
+ wsrep_start_transaction(thd, thd->wsrep_next_trx_id());
+#endif
return result;
}
@@ -4564,54 +4573,59 @@ bool select_create::send_eof()
if (!table->s->tmp_table)
{
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
- /*
- append table level exclusive key for CTAS
- */
- wsrep_key_arr_t key_arr= {0, 0};
- wsrep_prepare_keys_for_isolation(thd,
- create_table->db.str,
- create_table->table_name.str,
- table_list,
- &key_arr);
- int rcode = wsrep->append_key(
- wsrep,
- &thd->wsrep_ws_handle,
- key_arr.keys, //&wkey,
- key_arr.keys_len,
- WSREP_KEY_EXCLUSIVE,
- false);
- wsrep_keys_free(&key_arr);
- if (rcode) {
- DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
- WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
- (wsrep_thd_query(thd)) ?
- wsrep_thd_query(thd) : "void", rcode);
- return true;
- }
- /* If commit fails, we should be able to reset the OK status. */
- thd->get_stmt_da()->set_overwrite_status(TRUE);
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_start_transaction(thd, thd->wsrep_next_trx_id());
+ }
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ WSREP_DEBUG("CTAS key append for trx: %lu thd %lu query %lld ",
+ thd->wsrep_trx_id(), thd->thread_id, thd->query_id);
+
+ /*
+ append table level exclusive key for CTAS
+ */
+ wsrep_key_arr_t key_arr= {0, 0};
+ wsrep_prepare_keys_for_isolation(thd,
+ create_table->db.str,
+ create_table->table_name.str,
+ table_list,
+ &key_arr);
+ int rcode= wsrep_thd_append_key(thd, key_arr.keys, key_arr.keys_len,
+ wsrep_key_exclusive);
+ wsrep_keys_free(&key_arr);
+ if (rcode)
+ {
+ DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
+ WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void", rcode);
+ DBUG_RETURN(true);
+ }
+ /* If commit fails, we should be able to reset the OK status. */
+ thd->get_stmt_da()->set_overwrite_status(true);
}
#endif /* WITH_WSREP */
trans_commit_stmt(thd);
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
trans_commit_implicit(thd);
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
thd->get_stmt_da()->set_overwrite_status(FALSE);
mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state != NO_CONFLICT)
+ if (thd->wsrep_trx().state() != wsrep::transaction::s_executing)
{
- WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s",
- (longlong) thd->thread_id, thd->wsrep_conflict_state,
- thd->query());
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- abort_result_set();
- DBUG_RETURN(true);
+ WSREP_DEBUG("select_create commit failed, thd: %lu err: %s %s",
+ thd->thread_id, wsrep_thd_transaction_state_str(thd),
+ WSREP_QUERY(thd));
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ abort_result_set();
+ DBUG_RETURN(true);
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
+ thd->wsrep_cs().after_statement();
}
#endif /* WITH_WSREP */
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 4a5aedcfbd0..2cb9b0e2115 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -32,6 +32,9 @@
#include "sql_cte.h"
#include "sql_signal.h"
#include "sql_partition.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP*/
void LEX::parse_error(uint err_number)
@@ -1828,7 +1831,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
else
{
#ifdef WITH_WSREP
- if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
+ if (WSREP(thd) && version == 99997 && wsrep_thd_is_local(thd))
{
WSREP_DEBUG("consistency check: %s", thd->query());
thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index dd6e723c953..c2d4de0e081 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -42,6 +42,8 @@
#include "sql_derived.h"
#include "sql_show.h"
+#include "wsrep_mysqld.h"
+
extern "C" int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t Count);
class XML_TAG {
@@ -106,7 +108,7 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table,
{
DBUG_ENTER("wsrep_load_data_split");
- if (!wsrep_load_data_splitting || !wsrep_on(thd)
+ if (!wsrep_load_data_splitting || !WSREP(thd)
|| !info.records || (info.records % 10000)
|| !thd->transaction.stmt.ha_list
|| thd->transaction.stmt.ha_list->ht() != binlog_hton
@@ -119,10 +121,15 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table,
if (hton->db_type != DB_TYPE_INNODB)
DBUG_RETURN(false);
WSREP_DEBUG("intermediate transaction commit in LOAD DATA");
+#ifdef OUT /* this is old mariadb implementation... */
if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true);
if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true);
wsrep_post_commit(thd, true);
hton->commit(hton, thd, true);
+#else
+ /* ...which is replaced by this */
+ wsrep_tc_log_commit(thd);
+#endif
table->file->extra(HA_EXTRA_FAKE_START_STMT);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index aa669f42c6f..71bdec30a08 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -109,10 +109,12 @@
#include "../storage/maria/ha_maria.h"
#endif
+#include "mysql/service_wsrep.h"
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
-static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
+static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state,
bool is_com_multi,
bool is_next_command);
@@ -880,6 +882,16 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_REVOKE_ALL]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_INSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
+#ifdef WITH_WSREP
+ /*
+ Statements for which some errors are ignored when
+ wsrep_ignore_apply_errors = WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL
+ */
+ sql_command_flags[SQLCOM_DROP_DB]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_DROP_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_DROP_INDEX]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS;
+#endif /* WITH_WSREP */
}
bool sqlcom_can_generate_row_events(const THD *thd)
@@ -1177,6 +1189,7 @@ static enum enum_server_command fetch_command(THD *thd, char *packet)
#ifdef WITH_WSREP
static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
{
+ bool accessible_tables = true;
for (const TABLE_LIST *table= tables; table; table= table->next_global)
{
TABLE_CATEGORY c;
@@ -1185,7 +1198,7 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE)
return false;
}
- return true;
+ return accessible_tables;
}
#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
@@ -1215,19 +1228,6 @@ bool do_command(THD *thd)
enum enum_server_command command;
DBUG_ENTER("do_command");
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_IDLE;
- if (thd->wsrep_conflict_state==MUST_ABORT)
- {
- wsrep_client_rollback(thd);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
-
/*
indicator of uninitialized lex => normal flow of errors handling
(see my_message_sql)
@@ -1268,29 +1268,6 @@ bool do_command(THD *thd)
DEBUG_SYNC(thd, "before_do_command_net_read");
packet_length= my_net_read_packet(net, 1);
-#ifdef WITH_WSREP
- if (WSREP(thd)) {
- mysql_mutex_lock(&thd->LOCK_thd_data);
-
- /* these THD's are aborted or are aborting during being idle */
- if (thd->wsrep_conflict_state == ABORTING)
- {
- while (thd->wsrep_conflict_state == ABORTING) {
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- my_sleep(1000);
- mysql_mutex_lock(&thd->LOCK_thd_data);
- }
- thd->store_globals();
- }
- else if (thd->wsrep_conflict_state == ABORTED)
- {
- thd->store_globals();
- }
-
- thd->wsrep_query_state= QUERY_EXEC;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
if (unlikely(packet_length == packet_error))
{
@@ -1298,20 +1275,6 @@ bool do_command(THD *thd)
net->error,
vio_description(net->vio)));
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == MUST_ABORT)
- {
- DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu",
- (ulong) thd->real_id));
- wsrep_client_rollback(thd);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
-
/* Instrument this broken statement as "statement/com/error" */
thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
com_statement_info[COM_END].
@@ -1365,10 +1328,11 @@ bool do_command(THD *thd)
if (WSREP(thd))
{
/*
- Bail out if DB snapshot has not been installed.
- */
- if (!thd->wsrep_applier &&
- (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) &&
+ * bail out if DB snapshot has not been installed. We however,
+ * allow queries "SET" and "SHOW", they are trapped later in execute_command
+ */
+ if (!(thd->wsrep_applier) &&
+ (!wsrep_ready_get() || wsrep_reject_queries != WSREP_REJECT_NONE) &&
(server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0)
{
my_message(ER_UNKNOWN_COM_ERROR,
@@ -1384,7 +1348,7 @@ bool do_command(THD *thd)
goto out;
}
}
-#endif
+#endif /* WITH_WSREP */
/* Restore read timeout value */
my_net_set_read_timeout(net, thd->variables.net_read_timeout);
@@ -1393,37 +1357,6 @@ bool do_command(THD *thd)
DBUG_ASSERT(!thd->apc_target.is_enabled());
return_value= dispatch_command(command, thd, packet+1,
(uint) (packet_length-1), FALSE, FALSE);
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
- {
- WSREP_DEBUG("Retry autocommit for: %s\n", thd->wsrep_retry_query);
- CHARSET_INFO *current_charset = thd->variables.character_set_client;
- if (!is_supported_parser_charset(current_charset))
- {
- /* Do not use non-supported parser character sets */
- WSREP_WARN("Current client character set is non-supported parser "
- "character set: %s", current_charset->csname);
- thd->variables.character_set_client = &my_charset_latin1;
- WSREP_WARN("For retry temporally setting character set to : %s",
- my_charset_latin1.csname);
- }
- thd->clear_error();
- return_value= dispatch_command(command, thd, thd->wsrep_retry_query,
- thd->wsrep_retry_query_len, FALSE, FALSE);
- thd->variables.character_set_client = current_charset;
- }
-
- if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING)
- {
- my_free(thd->wsrep_retry_query);
- thd->wsrep_retry_query = NULL;
- thd->wsrep_retry_query_len = 0;
- thd->wsrep_retry_command = COM_CONNECT;
- }
- }
-#endif /* WITH_WSREP */
DBUG_ASSERT(!thd->apc_target.is_enabled());
out:
@@ -1496,6 +1429,36 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
DBUG_RETURN(FALSE);
}
+#ifdef WITH_WSREP
+static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables)
+{
+ int opt_readonly_saved = opt_readonly;
+ ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL);
+
+ opt_readonly = 0;
+ thd->security_ctx->master_access &= ~SUPER_ACL;
+
+ my_bool ret = !deny_updates_if_read_only_option(thd, all_tables);
+
+ opt_readonly = opt_readonly_saved;
+ thd->security_ctx->master_access |= flag_saved;
+
+ return ret;
+}
+
+static void wsrep_copy_query(THD *thd)
+{
+ thd->wsrep_retry_command = thd->get_command();
+ thd->wsrep_retry_query_len = thd->query_length();
+ if (thd->wsrep_retry_query) {
+ my_free(thd->wsrep_retry_query);
+ }
+ thd->wsrep_retry_query = (char *)my_malloc(
+ thd->wsrep_retry_query_len + 1, MYF(0));
+ strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len);
+ thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0';
+}
+#endif /* WITH_WSREP */
/**
check COM_MULTI packet
@@ -1579,38 +1542,28 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
compile_time_assert(COM_END == 255);
#ifdef WITH_WSREP
- if (WSREP(thd))
+ int err= wsrep_before_command(thd);
+ /*
+ Aborted by background rollbacker thread. Jump straight to dispatch_end
+ label where the error handling is performed.
+ */
+ if (err)
{
- if (!thd->in_multi_stmt_transaction_mode())
- {
- thd->wsrep_PA_safe= true;
- }
-
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXEC;
- if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
- {
- thd->wsrep_conflict_state= NO_CONFLICT;
- }
- if (thd->wsrep_conflict_state== MUST_ABORT)
- {
- wsrep_client_rollback(thd);
- }
+ thd->store_globals();
+ WSREP_LOG_THD(thd, "enter found BF aborted");
+ DBUG_ASSERT(!thd->mdl_context.has_locks());
+ DBUG_ASSERT(!thd->get_stmt_da()->is_set());
/* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */
- if (thd->wsrep_conflict_state == ABORTED &&
- command != COM_STMT_CLOSE && command != COM_QUIT)
+ if (command != COM_STMT_CLOSE &&
+ command != COM_QUIT)
{
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
- MYF(0));
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
WSREP_DEBUG("Deadlock error for: %s", thd->query());
thd->reset_killed();
thd->mysys_var->abort = 0;
- thd->wsrep_conflict_state = NO_CONFLICT;
thd->wsrep_retry_counter = 0;
goto dispatch_end;
}
- mysql_mutex_unlock(&thd->LOCK_thd_data);
}
#endif /* WITH_WSREP */
#if defined(ENABLED_PROFILING)
@@ -1659,6 +1612,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*/
thd->set_query_id(get_query_id());
}
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", thd->wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
statistic_increment(thd->status_var.questions, &LOCK_status);
@@ -1843,8 +1803,27 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
if (WSREP_ON)
- wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state,
- is_com_multi, is_next_command);
+ {
+ if (wsrep_mysql_parse(thd, thd->query(), thd->query_length(),
+ &parser_state,
+ is_com_multi, is_next_command))
+ {
+ WSREP_DEBUG("Deadlock error for: %s", thd->query());
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ thd->killed = NOT_KILLED;
+ thd->mysys_var->abort = 0;
+ thd->wsrep_retry_counter = 0;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+#ifdef WSREP_TODO
+ /*
+ Increment threads running to compensate dec_thread_running() called
+ after dispatch_end label.
+ */
+ inc_thread_running();
+#endif /* WSREP_TODO */
+ goto dispatch_end;
+ }
+ }
else
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state,
is_com_multi, is_next_command);
@@ -1933,8 +1912,28 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
parser_state.reset(beginning_of_next_stmt, length);
if (WSREP_ON)
- wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state,
- is_com_multi, is_next_command);
+ {
+ if (wsrep_mysql_parse(thd, beginning_of_next_stmt,
+ length, &parser_state,
+ is_com_multi, is_next_command))
+ {
+ WSREP_DEBUG("Deadlock error for: %s", thd->query());
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ thd->killed = NOT_KILLED;
+ thd->mysys_var->abort = 0;
+ thd->wsrep_retry_counter = 0;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+#ifdef WSREP_TODO
+ /*
+ Increment threads running to compensate dec_thread_running() called
+ after dispatch_end label.
+ */
+ inc_thread_running();
+#endif /* WSREP_TODO */
+
+ goto dispatch_end;
+ }
+ }
else
mysql_parse(thd, beginning_of_next_stmt, length, &parser_state,
is_com_multi, is_next_command);
@@ -2372,7 +2371,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifdef WITH_WSREP
dispatch_end:
-
+ /*
+ BF aborted before sending response back to client
+ */
+ wsrep_after_command_before_result(thd);
+ if (wsrep_current_error(thd) &&
+ !(command == COM_STMT_PREPARE ||
+ command == COM_STMT_FETCH ||
+ command == COM_STMT_SEND_LONG_DATA ||
+ command == COM_STMT_CLOSE
+ ))
+ {
+ /* todo: Pass wsrep client state current error to override */
+ wsrep_override_error(thd, wsrep_current_error(thd),
+ wsrep_current_error_status(thd));
+ WSREP_LOG_THD(thd, "leave");
+ }
if (WSREP(thd))
{
/*
@@ -2383,8 +2397,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|| thd->get_stmt_da()->is_disabled());
/* wsrep BF abort in query exec phase */
mysql_mutex_lock(&thd->LOCK_thd_data);
- do_end_of_statement= thd->wsrep_conflict_state != REPLAYING &&
- thd->wsrep_conflict_state != RETRY_AUTOCOMMIT;
+ do_end_of_statement=
+ thd->wsrep_trx().state() != wsrep::transaction::s_replaying;
+#ifdef TODO
+ thd->wsrep_conflict_state != REPLAYING &&
+ thd->wsrep_conflict_state != RETRY_AUTOCOMMIT;
+#endif
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
@@ -2407,9 +2425,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
query_cache_end_of_result(thd);
}
}
- if (drop_more_results)
- thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
-
+
if (likely(!thd->is_error() && !thd->killed_errno()))
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
@@ -2457,6 +2473,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Check that some variables are reset properly */
DBUG_ASSERT(thd->abort_on_warning == 0);
thd->lex->restore_set_statement_var();
+#ifdef WITH_WSREP
+ wsrep_after_command_after_result(thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(error);
}
@@ -3418,7 +3437,7 @@ mysql_execute_command(THD *thd)
} /* endif unlikely slave */
#endif
#ifdef WITH_WSREP
- if (wsrep && WSREP(thd))
+ if (WSREP(thd))
{
/*
change LOCK TABLE WRITE to transaction
@@ -3448,8 +3467,8 @@ mysql_execute_command(THD *thd)
* allow SET and SHOW queries and reads from information schema
* and dirty reads (if configured)
*/
- if (!thd->wsrep_applier &&
- !(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) &&
+ if (!(thd->wsrep_applier) &&
+ !(wsrep_ready_get() && wsrep_reject_queries == WSREP_REJECT_NONE) &&
!(thd->variables.wsrep_dirty_reads &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) &&
!wsrep_tables_accessible_when_detached(all_tables) &&
@@ -3614,7 +3633,7 @@ mysql_execute_command(THD *thd)
not run in it's own transaction it may simply never appear on
the slave in case the outside transaction rolls back.
*/
- if (stmt_causes_implicit_commit(thd, CF_IMPLICT_COMMIT_BEGIN))
+ if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN))
{
/*
Note that this should never happen inside of stored functions
@@ -3637,6 +3656,13 @@ mysql_execute_command(THD *thd)
}
}
thd->transaction.stmt.mark_trans_did_ddl();
+#ifdef WITH_WSREP
+ /* Clean up the previous transaction on implicit commit */
+ if (wsrep_thd_is_local(thd) && wsrep_after_statement(thd))
+ {
+ goto error;
+ }
+#endif /* WITH_WSREP */
}
#ifndef DBUG_OFF
@@ -3685,6 +3711,37 @@ mysql_execute_command(THD *thd)
/* Start timeouts */
thd->set_query_timer();
+#ifdef WITH_WSREP
+ /*
+ THD is executing non-blocking operation. Set mark that the
+ execution has made it to actual command execution.
+ */
+ if (thd->wsrep_nbo_ctx) {
+ DBUG_ASSERT(thd->wsrep_nbo_ctx->executing() == false);
+ thd->wsrep_nbo_ctx->set_executing(true);
+ }
+
+ /*
+ Always start a new transaction for a wsrep THD unless the
+ current command is DDL or explicit BEGIN. This will guarantee that
+ the THD is BF abortable even if it does not generate any
+ changes and takes only read locks. If the statement does not
+ start a multi STMT transaction, the wsrep_transaction is
+ committed as empty at the end of this function.
+
+ Transaction is started for BEGIN in trans_begin(), for DDL the
+ implicit commit took care of committing previous transaction
+ above and a new transaction should not be started.
+ */
+ if (WSREP(thd) &&
+ wsrep_thd_is_local(thd) &&
+ lex->sql_command != SQLCOM_BEGIN &&
+ !(sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS))
+ {
+ wsrep_start_trx_if_not_started(thd);
+ }
+#endif /* WITH_WSREP */
+
switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS:
@@ -3746,12 +3803,16 @@ mysql_execute_command(THD *thd)
case SQLCOM_SELECT:
{
#ifdef WITH_WSREP
- if (lex->sql_command == SQLCOM_SELECT)
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ)
- else
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW)
+ if (lex->sql_command == SQLCOM_SELECT)
+ {
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ);
+ }
+ else
+ {
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
+ }
#endif /* WITH_WSREP */
-
+
thd->status_var.last_query_cost= 0.0;
/*
@@ -4554,9 +4615,7 @@ mysql_execute_command(THD *thd)
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
ha_rows found= 0, updated= 0;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if (update_precheck(thd, all_tables))
break;
@@ -4705,9 +4764,7 @@ mysql_execute_command(THD *thd)
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
/*
Since INSERT DELAYED doesn't support temporary tables, we could
@@ -4765,9 +4822,7 @@ mysql_execute_command(THD *thd)
select_insert *sel_result;
bool explain= MY_TEST(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= insert_precheck(thd, all_tables)))
break;
@@ -4887,9 +4942,7 @@ mysql_execute_command(THD *thd)
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
select_result *sel_result=lex->result;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= delete_precheck(thd, all_tables)))
break;
@@ -4949,9 +5002,7 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
multi_delete *result;
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= multi_delete_precheck(thd, all_tables)))
break;
@@ -5767,6 +5818,7 @@ mysql_execute_command(THD *thd)
thd->mdl_context.release_transactional_locks();
WSREP_DEBUG("BEGIN failed, MDL released: %lld",
(longlong) thd->thread_id);
+ WSREP_DEBUG("stmt_da, sql_errno: %d", (thd->get_stmt_da()->is_error()) ? thd->get_stmt_da()->sql_errno() : 0);
goto error;
}
my_ok(thd);
@@ -5806,20 +5858,7 @@ mysql_execute_command(THD *thd)
thd->set_killed(KILL_CONNECTION);
thd->print_aborted_warning(3, "RELEASE");
}
-#ifdef WITH_WSREP
- if (WSREP(thd)) {
-
- if (thd->wsrep_conflict_state == NO_CONFLICT ||
- thd->wsrep_conflict_state == REPLAYING)
- {
- my_ok(thd);
- }
- } else {
-#endif /* WITH_WSREP */
- my_ok(thd);
-#ifdef WITH_WSREP
- }
-#endif /* WITH_WSREP */
+ my_ok(thd);
break;
}
case SQLCOM_ROLLBACK:
@@ -5855,17 +5894,7 @@ mysql_execute_command(THD *thd)
/* Disconnect the current client connection. */
if (tx_release)
thd->set_killed(KILL_CONNECTION);
-#ifdef WITH_WSREP
- if (WSREP(thd)) {
- if (thd->wsrep_conflict_state == NO_CONFLICT) {
- my_ok(thd);
- }
- } else {
-#endif /* WITH_WSREP */
- my_ok(thd);
-#ifdef WITH_WSREP
- }
-#endif /* WITH_WSREP */
+ my_ok(thd);
break;
}
case SQLCOM_RELEASE_SAVEPOINT:
@@ -6309,6 +6338,17 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
thd->in_multi_stmt_transaction_mode());
+#ifdef WITH_WSREP
+ /*
+ Thread was executing non-blocking operation. Total order isolation
+ has been released after locking table names. We need to grab
+ total order isolation section here again to commit/binlog in order.
+ */
+ if (thd->wsrep_nbo_ctx)
+ {
+ wsrep_end_nbo_lock(thd, first_table);
+ }
+#endif /* WITH_WSREP */
lex->unit.cleanup();
@@ -6335,25 +6375,6 @@ mysql_execute_command(THD *thd)
THD_STAGE_INFO(thd, stage_rollback);
trans_rollback_stmt(thd);
}
-#ifdef WITH_WSREP
- if (thd->spcont &&
- (thd->wsrep_conflict_state == MUST_ABORT ||
- thd->wsrep_conflict_state == ABORTED ||
- thd->wsrep_conflict_state == CERT_FAILURE))
- {
- /*
- The error was cleared, but THD was aborted by wsrep and
- wsrep_conflict_state is still set accordingly. This
- situation is expected if we are running a stored procedure
- that declares a handler that catches ER_LOCK_DEADLOCK error.
- In which case the error may have been cleared in method
- sp_rcontext::handle_sql_condition().
- */
- trans_rollback_stmt(thd);
- thd->wsrep_conflict_state= NO_CONFLICT;
- thd->killed= NOT_KILLED;
- }
-#endif /* WITH_WSREP */
else
{
/* If commit fails, we should be able to reset the OK status. */
@@ -6369,9 +6390,6 @@ mysql_execute_command(THD *thd)
/* Free tables. Set stage 'closing tables' */
close_thread_tables(thd);
-#ifdef WITH_WSREP
- thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
-#endif /* WITH_WSREP */
#ifndef DBUG_OFF
@@ -6433,9 +6451,10 @@ mysql_execute_command(THD *thd)
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
- WSREP_TO_ISOLATION_END;
-
#ifdef WITH_WSREP
+ thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
+
+ WSREP_TO_ISOLATION_END;
/*
Force release of transactional locks if not in active MST and wsrep is on.
*/
@@ -6448,11 +6467,31 @@ mysql_execute_command(THD *thd)
(longlong) thd->thread_id);
thd->mdl_context.release_transactional_locks();
}
+
+ /*
+ Current command did not start multi STMT transaction and the command
+ did not cause commit to happen (e.g. read only). Commit the wsrep
+ transaction as empty.
+ */
+ if (!thd->in_active_multi_stmt_transaction() &&
+ thd->wsrep_trx().active() &&
+ thd->wsrep_trx().state() == wsrep::transaction::s_executing)
+ {
+ wsrep_commit_empty(thd, true);
+ }
+
+
+ /*
+ Non-blocking operation finished execution.
+ */
+ if (thd->wsrep_nbo_ctx) thd->wsrep_nbo_ctx->set_executing(false);
+
+ /* assume PA safety for next transaction */
+ thd->wsrep_PA_safe= true;
#endif /* WITH_WSREP */
DBUG_RETURN(res || thd->is_error());
-}
-
+ }
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
{
@@ -6572,12 +6611,12 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
return res;
}
-
static bool execute_show_status(THD *thd, TABLE_LIST *all_tables)
{
bool res;
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
@@ -6596,6 +6635,8 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables)
offsetof(STATUS_VAR, last_cleared_system_status_var));
mysql_mutex_unlock(&LOCK_status);
return res;
+ error:
+ return true;
}
@@ -7617,6 +7658,7 @@ void THD::reset_for_next_command(bool do_clear_error)
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
#ifdef WITH_WSREP
+ THD *thd= this;
/*
Autoinc variables should be adjusted only for locally executed
transactions. Appliers and replayers are either processing ROW
@@ -7625,8 +7667,8 @@ void THD::reset_for_next_command(bool do_clear_error)
use autoinc values passed in binlog events, not the values forced by
the cluster.
*/
- if (WSREP(this) && wsrep_exec_mode == LOCAL_STATE &&
- !slave_thread && wsrep_auto_increment_control)
+ if (WSREP(thd) && wsrep_thd_is_local(thd) &&
+ !thd->slave_thread && wsrep_auto_increment_control)
{
variables.auto_increment_offset=
global_system_variables.auto_increment_offset;
@@ -7843,144 +7885,157 @@ void mysql_init_multi_delete(LEX *lex)
lex->query_tables_last= &lex->query_tables;
}
-static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
+#ifdef WITH_WSREP
+static void wsrep_prepare_for_autocommit_retry(THD* thd,
+ char* rawbuf,
+ uint length,
+ Parser_state* parser_state)
+{
+ thd->clear_error();
+ close_thread_tables(thd);
+ thd->wsrep_retry_counter++; // grow
+ wsrep_copy_query(thd);
+ thd->set_time();
+ parser_state->reset(rawbuf, length);
+
+ /* PSI end */
+ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->m_statement_psi= NULL;
+ thd->m_digest= NULL;
+
+ /* DTRACE end */
+ if (MYSQL_QUERY_DONE_ENABLED())
+ {
+ MYSQL_QUERY_DONE(thd->is_error());
+ }
+
+ /* SHOW PROFILE end */
+#if defined(ENABLED_PROFILING)
+ thd->profiling.finish_current_query();
+#endif
+
+ /* SHOW PROFILE begin */
+#if defined(ENABLED_PROFILING)
+ thd->profiling.start_new_query("continuing");
+ thd->profiling.set_query_source(rawbuf, length);
+#endif
+
+ /* DTRACE begin */
+ MYSQL_QUERY_START(rawbuf, thd->thread_id,
+ (char *) (thd->db ? thd->db.str : ""),
+ &thd->security_ctx->priv_user[0],
+ (char *) thd->security_ctx->host_or_ip);
+
+ /* Performance Schema Interface instrumentation, begin */
+ thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
+ com_statement_info[thd->get_command()].m_key);
+ MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(),
+ thd->query_length());
+
+ DBUG_ASSERT(thd->wsrep_trx().active() == false);
+ thd->wsrep_cs().reset_error();
+ thd->set_query_id(next_query_id());
+}
+
+static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state,
bool is_com_multi,
bool is_next_command)
{
-#ifdef WITH_WSREP
bool is_autocommit=
!thd->in_multi_stmt_transaction_mode() &&
- thd->wsrep_conflict_state == NO_CONFLICT &&
- !thd->wsrep_applier;
-
+ wsrep_read_only_option(thd, thd->lex->query_tables);
+ bool retry_autocommit;
do
{
- if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
- {
- thd->wsrep_conflict_state= NO_CONFLICT;
- /* Performance Schema Interface instrumentation, begin */
- thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
- com_statement_info[thd->get_command()].m_key);
- MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(),
- thd->query_length());
-
- DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit",
- {
- const char act[]=
- "now "
- "SIGNAL wsrep_retry_autocommit_reached "
- "WAIT_FOR wsrep_retry_autocommit_continue";
- DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
- });
+ retry_autocommit= false;
+ DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit",
+ {
+ const char act[]=
+ "now "
+ "SIGNAL wsrep_retry_autocommit_reached "
+ "WAIT_FOR wsrep_retry_autocommit_continue";
+ DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
+ });
WSREP_DEBUG("Retry autocommit query: %s", thd->query());
- }
-
- mysql_parse(thd, rawbuf, length, parser_state, is_com_multi,
- is_next_command);
+ mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, is_next_command);
- if (WSREP(thd)) {
- /* wsrep BF abort in query exec phase */
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == MUST_ABORT) {
- wsrep_client_rollback(thd);
- WSREP_DEBUG("abort in exec query state, avoiding autocommit");
- }
+ /*
+ Convert all ER_QUERY_INTERRUPTED errors to ER_LOCK_DEADLOCK
+ if the transaction was BF aborted. This can happen when the
+ transaction is being BF aborted via thd->awake() while it is
+ still executing.
- if (thd->wsrep_conflict_state == MUST_REPLAY)
- {
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- if (thd->lex->explain)
- delete_explain_query(thd->lex);
- mysql_mutex_lock(&thd->LOCK_thd_data);
+ Note that this must be done before wsrep_after_statement() call
+ since it clears the transaction for autocommit queries.
+ */
+ if (((thd->get_stmt_da()->is_error() &&
+ thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED) ||
+ !thd->get_stmt_da()->is_set()) &&
+ thd->wsrep_trx().bf_aborted())
+ {
+ WSREP_DEBUG("overriding error: %d with DEADLOCK",
+ (thd->get_stmt_da()->is_error()) ?
+ thd->get_stmt_da()->sql_errno() : 0);
- wsrep_replay_transaction(thd);
- }
+ thd->killed = NOT_KILLED;
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ }
- /* setting error code for BF aborted trxs */
- if (thd->wsrep_conflict_state == ABORTED ||
- thd->wsrep_conflict_state == CERT_FAILURE)
+ if (wsrep_after_statement(thd) && is_autocommit)
+ {
+ thd->reset_for_next_command();
+ thd->killed= NOT_KILLED;
+ if (is_autocommit &&
+ thd->lex->sql_command != SQLCOM_SELECT &&
+ thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)
{
- thd->reset_for_next_command();
- if (is_autocommit &&
- thd->lex->sql_command != SQLCOM_SELECT &&
- (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit))
- {
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- WSREP_DEBUG("wsrep retrying AC query: %s",
- (thd->query()) ? thd->query() : "void");
-
- /* Performance Schema Interface instrumentation, end */
- MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
- thd->m_statement_psi= NULL;
- thd->m_digest= NULL;
- // Released thd->LOCK_thd_data above as below could end up
- // close_thread_tables()/close_open_tables()/close_thread_table()/mysql_mutex_lock(&thd->LOCK_thd_data)
- close_thread_tables(thd);
-
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_conflict_state= RETRY_AUTOCOMMIT;
- thd->wsrep_retry_counter++; // grow
- wsrep_copy_query(thd);
- thd->set_time();
- parser_state->reset(rawbuf, length);
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
- else
- {
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- // This does dirty read to wsrep variables but it is only a debug code
- WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s",
- (thd->wsrep_conflict_state == ABORTED) ?
- "BF Aborted" : "cert failure",
- (longlong) thd->thread_id, is_autocommit,
- thd->wsrep_retry_counter,
- thd->variables.wsrep_retry_autocommit, thd->query());
- my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
- MYF(0));
-
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_conflict_state= NO_CONFLICT;
- if (thd->wsrep_conflict_state != REPLAYING)
- thd->wsrep_retry_counter= 0; // reset
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-
- thd->reset_killed();
+ WSREP_DEBUG("wsrep retrying AC query: %lu %s",
+ thd->wsrep_retry_counter, WSREP_QUERY(thd));
+ wsrep_prepare_for_autocommit_retry(thd, rawbuf, length, parser_state);
+ if (thd->lex->explain)
+ delete_explain_query(thd->lex);
+ retry_autocommit= true;
}
else
{
- set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s",
+ wsrep_thd_transaction_state_str(thd),
+ thd->thread_id,
+ is_autocommit,
+ thd->wsrep_retry_counter,
+ thd->variables.wsrep_retry_autocommit,
+ WSREP_QUERY(thd));
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
+ thd->killed= NOT_KILLED;
+ thd->wsrep_retry_counter= 0; // reset
}
}
-
- /* If retry is requested clean up explain structure */
- if ((thd->wsrep_conflict_state == RETRY_AUTOCOMMIT ||
- thd->wsrep_conflict_state == MUST_REPLAY )
- && thd->lex->explain)
+ else
{
- delete_explain_query(thd->lex);
+ set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok
}
-
- } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT);
+ } while (retry_autocommit);
if (thd->wsrep_retry_query)
{
- WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s",
- thd->wsrep_conflict_state,
- thd->get_stmt_da()->is_sent(),
+ WSREP_DEBUG("releasing retry_query: "
+ "conf %s sent %d kill %d errno %d SQL %s",
+ wsrep_thd_transaction_state_str(thd),
+ thd->get_stmt_da()->is_sent(),
thd->killed,
- thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
+ thd->get_stmt_da()->is_error() ?
+ thd->get_stmt_da()->sql_errno() : 0,
thd->wsrep_retry_query);
my_free(thd->wsrep_retry_query);
thd->wsrep_retry_query = NULL;
thd->wsrep_retry_query_len = 0;
thd->wsrep_retry_command = COM_CONNECT;
}
-#endif /* WITH_WSREP */
+ return false;
}
+#endif /* WITH_WSREP */
/*
@@ -8932,6 +8987,7 @@ THD *find_thread_by_id(longlong id, bool query_id)
continue;
if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id))
{
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data);
mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
break;
}
@@ -8960,7 +9016,8 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD);
DBUG_ENTER("kill_one_thread");
DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal));
-
+ WSREP_DEBUG("kill_one_thread %lu", thd->thread_id);
+#ifdef WITH_WSREP
if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY)))
{
/*
@@ -8986,15 +9043,22 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
- !wsrep_thd_is_BF(tmp, false))
+ !wsrep_thd_is_BF((void *)tmp, false) && !tmp->wsrep_applier)
+#else
+ if ((thd->security_ctx->master_access & SUPER_ACL) ||
+ thd->security_ctx->user_matches(tmp->security_ctx))
+#endif /* WITH_WSREP */
{
+ //if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data);
tmp->awake_no_mutex(kill_signal);
+ //if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data);
error=0;
}
else
error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR :
ER_KILL_DENIED_ERROR);
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
+ if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data);
}
DBUG_PRINT("exit", ("%d", error));
DBUG_RETURN(error);
@@ -9052,7 +9116,10 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
DBUG_RETURN(ER_KILL_DENIED_ERROR);
}
if (!threads_to_kill.push_back(tmp, thd->mem_root))
+ {
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data);
mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
+ }
}
}
mysql_mutex_unlock(&LOCK_thread_count);
@@ -9074,6 +9141,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
*/
next_ptr= it2++;
mysql_mutex_unlock(&ptr->LOCK_thd_kill);
+ if (WSREP(ptr)) mysql_mutex_unlock(&ptr->LOCK_thd_data);
(*rows)++;
} while ((ptr= next_ptr));
}
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 1027872898a..ef8f2a11ee0 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -18,6 +18,10 @@
#include "sql_acl.h" /* GLOBAL_ACLS */
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP */
+
class Comp_creator;
class Item;
class Object_creation_ctx;
@@ -37,6 +41,8 @@ int test_if_data_home_dir(const char *dir);
int error_if_data_home_dir(const char *path, const char *what);
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags);
+bool stmt_causes_implicit_commit(const THD *thd, uint mask);
+
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
int mysql_multi_update_prepare(THD *thd);
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 8c231d9b8f7..8f48a6d1b7f 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2281,6 +2281,10 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name)
}
}
return 0;
+#ifdef WITH_WSREP
+ error:
+#endif /* WITH_WSREP */
+ return 1;
}
@@ -2299,6 +2303,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
@@ -2832,7 +2837,6 @@ sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
plugin_ref plugin;
DBUG_ENTER("find_sys_var_ex");
DBUG_PRINT("enter", ("var '%.*s'", (int)length, str));
-
if (!locked)
mysql_mutex_lock(&LOCK_plugin);
mysql_prlock_rdlock(&LOCK_system_variables_hash);
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index 8de53aa2161..3749a6b6101 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -142,7 +142,6 @@ static struct thd_error_context_service_st thd_error_context_handler= {
};
static struct wsrep_service_st wsrep_handler = {
- get_wsrep,
get_wsrep_certify_nonPK,
get_wsrep_debug,
get_wsrep_drupal_282555_workaround,
@@ -150,38 +149,23 @@ static struct wsrep_service_st wsrep_handler = {
get_wsrep_load_data_splitting,
get_wsrep_log_conflicts,
get_wsrep_protocol_version,
- wsrep_aborting_thd_contains,
- wsrep_aborting_thd_enqueue,
wsrep_consistency_check,
wsrep_is_wsrep_xid,
- wsrep_xid_seqno,
- wsrep_xid_uuid,
- wsrep_lock_rollback,
+ get_wsrep_xid_seqno,
+ get_wsrep_xid_uuid,
wsrep_on,
- wsrep_post_commit,
- wsrep_prepare_key,
- wsrep_run_wsrep_commit,
+ wsrep_prepare_key_for_innodb,
wsrep_thd_LOCK,
wsrep_thd_UNLOCK,
wsrep_thd_awake,
- wsrep_thd_conflict_state,
- wsrep_thd_conflict_state_str,
- wsrep_thd_exec_mode,
- wsrep_thd_exec_mode_str,
- wsrep_thd_get_conflict_state,
- wsrep_thd_is_BF,
- wsrep_thd_is_wsrep,
+ wsrep_thd_thread_id,
+ wsrep_thd_is_wsrep_on,
wsrep_thd_query,
- wsrep_thd_query_state,
- wsrep_thd_query_state_str,
- wsrep_thd_retry_counter,
- wsrep_thd_set_conflict_state,
wsrep_thd_ignore_table,
wsrep_thd_trx_seqno,
- wsrep_thd_ws_handle,
- wsrep_trx_is_aborting,
+ wsrep_thd_is_aborting,
wsrep_trx_order_before,
- wsrep_unlock_rollback,
+ wsrep_thd_xid,
wsrep_set_data_home_dir
};
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 09d31470a00..c50ae14025d 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4206,30 +4206,6 @@ Prepared_statement::execute_loop(String *expanded_query,
error= execute(expanded_query, open_cursor) || thd->is_error();
thd->m_reprepare_observer= NULL;
-#ifdef WITH_WSREP
-
- if (WSREP_ON)
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- switch (thd->wsrep_conflict_state)
- {
- case CERT_FAILURE:
- WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d",
- (longlong) thd->thread_id,
- thd->get_stmt_da()->sql_errno() );
- thd->wsrep_conflict_state = NO_CONFLICT;
- break;
-
- case MUST_REPLAY:
- (void) wsrep_replay_transaction(thd);
- break;
-
- default:
- break;
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
if (unlikely(error) &&
(sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) &&
@@ -4402,30 +4378,6 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
error= execute(expanded_query, open_cursor) || thd->is_error();
thd->m_reprepare_observer= NULL;
-#ifdef WITH_WSREP
-
- if (WSREP_ON)
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- switch (thd->wsrep_conflict_state)
- {
- case CERT_FAILURE:
- WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d",
- (longlong) thd->thread_id,
- thd->get_stmt_da()->sql_errno() );
- thd->wsrep_conflict_state = NO_CONFLICT;
- break;
-
- case MUST_REPLAY:
- (void) wsrep_replay_transaction(thd);
- break;
-
- default:
- break;
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
if (unlikely(error) &&
(sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) &&
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 2ee175293de..1847416368a 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3845,6 +3845,17 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len,
return 1;
}
+#ifdef WITH_WSREP
+ if (WSREP_ON)
+ {
+ /* RESET MASTER will initialize GTID sequence, and that would happen locally
+ in this node, so better reject it
+ */
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ "RESET MASTER not allowed when node is in cluster", MYF(0));
+ return 1;
+ }
+#endif /* WITH_WSREP */
bool ret= 0;
/* Temporarily disable master semisync before reseting master. */
repl_semisync_master.before_reset_master();
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b04d869bf1d..a8db937f6c3 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2646,7 +2646,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno()
: 0;
#ifdef WITH_WSREP
- thd->wsrep_skip_wsrep_GTID = false;
+ thd->wsrep_skip_wsrep_GTID = true;
#endif /* WITH_WSREP */
error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
built_query.ptr(),
@@ -2697,7 +2697,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
end:
#ifdef WITH_WSREP
- thd->wsrep_skip_wsrep_GTID = false;
+ thd->wsrep_skip_wsrep_GTID = false;
#endif /* WITH_WSREP */
DBUG_RETURN(error);
}
@@ -7559,6 +7559,19 @@ static bool mysql_inplace_alter_table(THD *thd,
}
}
+#ifdef WITH_WSREP
+ if (thd->wsrep_nbo_ctx) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+ DBUG_EXECUTE_IF("sync.alter_locked_tables_inplace",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.alter_locked_tables_inplace";
+ DBUG_ASSERT(!debug_sync_set_action(thd,
+ STRING_WITH_LEN(act)));
+ };);
+#endif /* WITH_WSREP */
DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade");
THD_STAGE_INFO(thd, stage_alter_inplace);
@@ -9781,6 +9794,21 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
+#ifdef WITH_WSREP
+ if (thd->wsrep_nbo_ctx) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+
+ DBUG_EXECUTE_IF("sync.alter_locked_tables",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.alter_locked_tables";
+ DBUG_ASSERT(!debug_sync_set_action(thd,
+ STRING_WITH_LEN(act)));
+ };);
+
+#endif /* WITH_WSREP */
/* Open the table since we need to copy the data. */
if (table->s->tmp_table != NO_TMP_TABLE)
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index fd128f8dc1c..a14f3473c12 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -517,7 +517,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
}
#ifdef WITH_WSREP
- if (thd->wsrep_exec_mode == LOCAL_STATE)
+ // if (thd->wsrep_exec_mode == LOCAL_STATE)
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
#endif
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 798e929170c..7b9ed483755 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -419,9 +419,20 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
if (WSREP(thd) &&
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0))
DBUG_RETURN(TRUE);
- if (lock_table(thd, table_ref, &hton_can_recreate))
- DBUG_RETURN(TRUE);
+ /*
+ When using non-blocking operation for TRUNCATE always fall to
+ handler_truncate() in order to avoid calling lock_table_names()
+ twice.
+ */
+ if (WSREP(thd) && thd->wsrep_nbo_ctx) {
+ hton_can_recreate= false;
+ }
+ else
+ {
+ if (lock_table(thd, table_ref, &hton_can_recreate))
+ DBUG_RETURN(TRUE);
+ }
if (hton_can_recreate)
{
/*
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 6d2dbbf646e..1d015e42683 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5404,7 +5404,7 @@ static Sys_var_ulong Sys_wsrep_max_ws_size (
GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1024, WSREP_MAX_WS_SIZE), DEFAULT(WSREP_MAX_WS_SIZE),
BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
- ON_CHECK(wsrep_max_ws_size_check), ON_UPDATE(wsrep_max_ws_size_update));
+ ON_CHECK(0), ON_UPDATE(wsrep_max_ws_size_update));
static Sys_var_ulong Sys_wsrep_max_ws_rows (
"wsrep_max_ws_rows", "Max number of rows in write set",
@@ -5441,7 +5441,7 @@ static Sys_var_uint Sys_wsrep_sync_wait(
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(wsrep_sync_wait_update));
-static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS };
+static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", "NBO", NullS };
static Sys_var_enum Sys_wsrep_OSU_method(
"wsrep_OSU_method", "Method for Online Schema Upgrade",
SESSION_VAR(wsrep_OSU_method), CMD_LINE(OPT_ARG),
@@ -5491,7 +5491,7 @@ static Sys_var_ulong Sys_wsrep_mysql_replication_bundle(
static Sys_var_mybool Sys_wsrep_load_data_splitting(
"wsrep_load_data_splitting", "To commit LOAD DATA "
- "transaction after every 10K rows inserted",
+ "transaction after every 10K rows inserted (deprecating)",
GLOBAL_VAR(wsrep_load_data_splitting),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
@@ -5511,12 +5511,46 @@ static Sys_var_mybool Sys_wsrep_restart_slave(
"wsrep_restart_slave", "Should MariaDB slave be restarted automatically, when node joins back to cluster",
GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
+static Sys_var_ulong Sys_wsrep_trx_fragment_size(
+ "wsrep_trx_fragment_size",
+ "Size of transaction fragments for streaming replication (measured in "
+ "units of 'wsrep_trx_fragment_unit')",
+ SESSION_VAR(wsrep_trx_fragment_size), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(0, WSREP_MAX_WS_SIZE), DEFAULT(0), BLOCK_SIZE(1),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(wsrep_trx_fragment_size_check),
+ ON_UPDATE(wsrep_trx_fragment_size_update));
+
+extern const char *wsrep_fragment_units[];
+
+static Sys_var_enum Sys_wsrep_trx_fragment_unit(
+ "wsrep_trx_fragment_unit",
+ "Unit for streaming replication transaction fragments' size: bytes, "
+ "events, rows, statements",
+ SESSION_VAR(wsrep_trx_fragment_unit), CMD_LINE(REQUIRED_ARG),
+ wsrep_fragment_units,
+ DEFAULT(WSREP_FRAG_BYTES),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0));
+
+extern const char *wsrep_SR_store_types[];
+static Sys_var_enum Sys_wsrep_SR_store(
+ "wsrep_SR_store", "Storage for streaming replication fragments",
+ READ_ONLY GLOBAL_VAR(wsrep_SR_store_type), CMD_LINE(REQUIRED_ARG),
+ wsrep_SR_store_types, DEFAULT(WSREP_SR_STORE_TABLE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG);
+
static Sys_var_mybool Sys_wsrep_dirty_reads(
"wsrep_dirty_reads",
"Allow reads even when the node is not in the primary component.",
SESSION_VAR(wsrep_dirty_reads), CMD_LINE(OPT_ARG),
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG);
+static Sys_var_uint Sys_wsrep_ignore_apply_errors (
+ "wsrep_ignore_apply_errors", "Ignore replication errors",
+ GLOBAL_VAR(wsrep_ignore_apply_errors), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(WSREP_IGNORE_ERRORS_NONE, WSREP_IGNORE_ERRORS_MAX),
+ DEFAULT(7), BLOCK_SIZE(1));
+
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 "
diff --git a/sql/table.cc b/sql/table.cc
index 08b71114310..01fad6c388d 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -250,6 +250,13 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
DBUG_ASSERT(db != NULL);
DBUG_ASSERT(name != NULL);
+#ifdef WITH_WSREP
+ if (my_strcasecmp(system_charset_info, db->str, "wsrep_schema") == 0 &&
+ my_strcasecmp(system_charset_info, name->str, "SR") == 0)
+ {
+ return TABLE_CATEGORY_INFORMATION;
+ }
+#endif /* WITH_WSREP */
if (is_infoschema_db(db))
return TABLE_CATEGORY_INFORMATION;
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index 682f9455d26..8b8f66c057f 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -1141,8 +1141,38 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
All_share_tables_list::Iterator it(element->all_tables);
while ((table= it++))
{
- if (table->in_use == thd)
+#ifdef WITH_WSREP
+ if (remove_type == TDC_RT_REMOVE_ALL ||
+ remove_type == TDC_RT_REMOVE_NOT_OWN ||
+ remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
+ {
+ if (table->in_use != thd)
+ {
+ /*
+ We may end up here if we were granted some MDL
+ lock even if another thd was already granted.
+ In that case we expect their wsrep_conflict_state
+ to be either ABORTING or CERT_FAILURE.
+ See wsrep_grant_mdl_exception()
+ */
+ enum wsrep::transaction::state state=
+ table->in_use->wsrep_trx().state();
+ if (state == wsrep::transaction::s_cert_failed ||
+ state == wsrep::transaction::s_aborting)
+ {
+ WSREP_DEBUG("Table_cache_manager::free_table assert skipped");
+ }
+ else
+ {
+ DBUG_ASSERT(0);
+ }
+ }
+ }
+ my_refs++;
+#else
my_refs++;
+
+#endif /* WITH_WSREP */
}
}
mysql_mutex_unlock(&element->LOCK_table_share);
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 1c2820200d1..6d5cba859aa 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -24,6 +24,9 @@
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_acl.h"
#include "semisync_master.h"
+#ifdef WITH_WSREP
+#include "wsrep_trans_observer.h"
+#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
/**
@@ -135,8 +138,6 @@ static bool xa_trans_force_rollback(THD *thd)
by ha_rollback()/THD::transaction::cleanup().
*/
thd->transaction.xid_state.rm_error= 0;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
if (ha_rollback_trans(thd, true))
{
my_error(ER_XAER_RMERR, MYF(0));
@@ -184,14 +185,16 @@ bool trans_begin(THD *thd, uint flags)
(thd->variables.option_bits & OPTION_TABLE_LOCK))
{
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
+#ifdef WITH_WSREP
+ if (wsrep_thd_is_local(thd))
+ {
+ res= res || wsrep_after_statement(thd);
+ }
+#endif /* WITH_WSREP */
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
@@ -252,9 +255,14 @@ bool trans_begin(THD *thd, uint flags)
}
#ifdef WITH_WSREP
- thd->wsrep_PA_safe= true;
- if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
- DBUG_RETURN(TRUE);
+ if (wsrep_thd_is_local(thd))
+ {
+ if (wsrep_sync_wait(thd))
+ DBUG_RETURN(TRUE);
+ if (!thd->tx_read_only &&
+ wsrep_start_transaction(thd, thd->wsrep_next_trx_id()))
+ DBUG_RETURN(TRUE);
+ }
#endif /* WITH_WSREP */
thd->variables.option_bits|= OPTION_BEGIN;
@@ -299,8 +307,6 @@ bool trans_commit(THD *thd)
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
@@ -311,8 +317,6 @@ bool trans_commit(THD *thd)
mysql_mutex_assert_not_owner(&LOCK_after_binlog_sync);
mysql_mutex_assert_not_owner(&LOCK_commit_ordered);
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
/*
if res is non-zero, then ha_commit_trans has rolled back the
transaction, so the hooks for rollback will be called.
@@ -368,14 +372,10 @@ bool trans_commit_implicit(THD *thd)
/* Safety if one did "drop table" on locked tables */
if (!thd->locked_tables_mode)
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
@@ -409,14 +409,9 @@ bool trans_rollback(THD *thd)
int res;
DBUG_ENTER("trans_rollback");
-#ifdef WITH_WSREP
- thd->wsrep_PA_safe= true;
-#endif /* WITH_WSREP */
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
@@ -424,6 +419,7 @@ bool trans_rollback(THD *thd)
#ifdef HAVE_REPLICATION
repl_semisync_master.wait_after_rollback(thd, FALSE);
#endif
+ //(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
/* Reset the binlog transaction marker */
thd->variables.option_bits&= ~OPTION_GTID_BEGIN;
@@ -515,14 +511,10 @@ bool trans_commit_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, FALSE);
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
trans_reset_one_shot_chistics(thd);
- if (WSREP_ON)
- wsrep_post_commit(thd, FALSE);
}
}
@@ -578,8 +570,6 @@ bool trans_rollback_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, FALSE);
ha_rollback_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
trans_reset_one_shot_chistics(thd);
@@ -733,7 +723,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name)
logging is off.
*/
bool mdl_can_safely_rollback_to_savepoint=
- (!(mysql_bin_log.is_open() && thd->variables.sql_log_bin) ||
+ (!((WSREP_EMULATE_BINLOG_NNULL(thd) || mysql_bin_log.is_open())
+ && thd->variables.sql_log_bin) ||
ha_rollback_to_savepoint_can_release_mdl(thd));
if (ha_rollback_to_savepoint(thd, sv))
@@ -944,13 +935,9 @@ bool trans_xa_commit(THD *thd)
}
else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
int r= ha_commit_trans(thd, TRUE);
if ((res= MY_TEST(r)))
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
}
else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
{
@@ -969,8 +956,6 @@ bool trans_xa_commit(THD *thd)
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
{
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
ha_rollback_trans(thd, TRUE);
my_error(ER_XAER_RMERR, MYF(0));
}
diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc
index 1f50ee55711..4321d332215 100644
--- a/sql/wsrep_applier.cc
+++ b/sql/wsrep_applier.cc
@@ -14,12 +14,17 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "mariadb.h"
+#include "mysql/service_wsrep.h"
+#include "wsrep_applier.h"
+
#include "wsrep_priv.h"
#include "wsrep_binlog.h" // wsrep_dump_rbr_buf()
#include "wsrep_xid.h"
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h"
+#include "slave.h" // opt_log_slave_updates
#include "log_event.h" // class THD, EVENT_LEN_OFFSET, etc.
-#include "wsrep_applier.h"
#include "debug_sync.h"
/*
@@ -27,7 +32,6 @@
At the end (*buf) is shitfed to point to the following event or NULL and
(*buf_len) will be changed to account just being read bytes of the 1st event.
*/
-
static Log_event* wsrep_read_log_event(
char **arg_buf, size_t *arg_buf_len,
const Format_description_log_event *description_event)
@@ -62,12 +66,13 @@ void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev)
{
if (thd->wsrep_apply_format)
{
- delete (Format_description_log_event*)thd->wsrep_apply_format;
+ delete (Format_description_log_event*)thd->wsrep_apply_format;
}
thd->wsrep_apply_format= ev;
}
-Format_description_log_event* wsrep_get_apply_format(THD* thd)
+Format_description_log_event*
+wsrep_get_apply_format(THD* thd)
{
if (thd->wsrep_apply_format)
{
@@ -79,45 +84,77 @@ Format_description_log_event* wsrep_get_apply_format(THD* thd)
return thd->wsrep_rgi->rli->relay_log.description_event_for_exec;
}
-static wsrep_cb_status_t wsrep_apply_events(THD* thd,
- const void* events_buf,
- size_t buf_len)
+void wsrep_apply_error::store(const THD* const thd)
{
- char *buf= (char *)events_buf;
- int rcode= 0;
- int event= 1;
- Log_event_type typ;
+ Diagnostics_area::Sql_condition_iterator it=
+ thd->get_stmt_da()->sql_conditions();
+ const Sql_condition* cond;
- DBUG_ENTER("wsrep_apply_events");
+ static size_t const max_len= 2*MAX_SLAVE_ERRMSG; // 2x so that we have enough
+
+ if (NULL == str_)
+ {
+ // this must be freeable by standard free()
+ str_= static_cast<char*>(malloc(max_len));
+ if (NULL == str_)
+ {
+ WSREP_ERROR("Failed to allocate %zu bytes for error buffer.", max_len);
+ len_ = 0;
+ return;
+ }
+ }
+ else
+ {
+ /* This is possible when we invoke rollback after failed applying.
+ * In this situation DA should not be reset yet and should contain
+ * all previous errors from applying and new ones from rollbacking,
+ * so we just overwrite is from scratch */
+ }
- if (thd->killed == KILL_CONNECTION &&
- thd->wsrep_conflict_state != REPLAYING)
+ char* slider= str_;
+ const char* const buf_end= str_ + max_len - 1; // -1: leave space for \0
+
+ for (cond= it++; cond && slider < buf_end; cond= it++)
{
- WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld",
- (long long) wsrep_thd_trx_seqno(thd));
- DBUG_RETURN(WSREP_CB_FAILURE);
+ uint const err_code= cond->get_sql_errno();
+ const char* const err_str= cond->get_message_text();
+
+ slider+= my_snprintf(slider, buf_end - slider, " %s, Error_code: %d;",
+ err_str, err_code);
}
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXEC;
- if (thd->wsrep_conflict_state!= REPLAYING)
- thd->wsrep_conflict_state= NO_CONFLICT;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ *slider= '\0';
+ len_= slider - str_ + 1; // +1: add \0
+
+ WSREP_DEBUG("Error buffer for thd %llu seqno %lld, %zu bytes: %s",
+ thd->thread_id, (long long)wsrep_thd_trx_seqno(thd),
+ len_, str_ ? str_ : "(null)");
+}
+
+int wsrep_apply_events(THD* thd,
+ Relay_log_info* rli,
+ const void* events_buf,
+ size_t buf_len)
+{
+ char *buf= (char *)events_buf;
+ int rcode= 0;
+ int event= 1;
+ Log_event_type typ;
+ DBUG_ENTER("wsrep_apply_events");
if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld",
(long long) wsrep_thd_trx_seqno(thd));
- while(buf_len)
+ while (buf_len)
{
int exec_res;
Log_event* ev= wsrep_read_log_event(&buf, &buf_len,
- wsrep_get_apply_format(thd));
-
+ wsrep_get_apply_format(thd));
if (!ev)
{
WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %zu",
(long long)wsrep_thd_trx_seqno(thd), buf_len);
- rcode= 1;
+ rcode= WSREP_ERR_BAD_EVENT;
goto error;
}
@@ -147,9 +184,6 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
thd->set_server_id(ev->server_id);
thd->set_time(); // time the query
thd->transaction.start_time.reset(thd);
- wsrep_xid_init(&thd->transaction.xid_state.xid,
- thd->wsrep_trx_meta.gtid.uuid,
- thd->wsrep_trx_meta.gtid.seqno);
thd->lex->current_select= 0;
if (!ev->when)
{
@@ -168,7 +202,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
if (exec_res)
{
- WSREP_WARN("RBR event %d %s apply warning: %d, %lld",
+ WSREP_WARN("Event %d %s apply failed: %d, seqno %lld",
event, ev->get_type_str(), exec_res,
(long long) wsrep_thd_trx_seqno(thd));
rcode= exec_res;
@@ -178,230 +212,14 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
}
event++;
- if (thd->wsrep_conflict_state!= NO_CONFLICT &&
- thd->wsrep_conflict_state!= REPLAYING)
- WSREP_WARN("conflict state after RBR event applying: %d, %lld",
- thd->wsrep_query_state, (long long)wsrep_thd_trx_seqno(thd));
-
- if (thd->wsrep_conflict_state == MUST_ABORT) {
- WSREP_WARN("RBR event apply failed, rolling back: %lld",
- (long long) wsrep_thd_trx_seqno(thd));
- trans_rollback(thd);
- thd->locked_tables_list.unlock_locked_tables(thd);
- /* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
- thd->wsrep_conflict_state= NO_CONFLICT;
- DBUG_RETURN(WSREP_CB_FAILURE);
- }
-
delete_or_keep_event_post_apply(thd->wsrep_rgi, typ, ev);
}
- error:
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_IDLE;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
-
- assert(thd->wsrep_exec_mode== REPL_RECV);
-
+error:
if (thd->killed == KILL_CONNECTION)
WSREP_INFO("applier aborted: %lld", (long long)wsrep_thd_trx_seqno(thd));
- if (rcode) DBUG_RETURN(WSREP_CB_FAILURE);
- DBUG_RETURN(WSREP_CB_SUCCESS);
-}
-
-wsrep_cb_status_t wsrep_apply_cb(void* const ctx,
- const void* const buf,
- size_t const buf_len,
- uint32_t const flags,
- const wsrep_trx_meta_t* meta)
-{
- THD* const thd((THD*)ctx);
-
- assert(thd->wsrep_apply_toi == false);
-
- // Allow tests to block the applier thread using the DBUG facilities.
- DBUG_EXECUTE_IF("sync.wsrep_apply_cb",
- {
- const char act[]=
- "now "
- "SIGNAL sync.wsrep_apply_cb_reached "
- "WAIT_FOR signal.wsrep_apply_cb";
- DBUG_ASSERT(!debug_sync_set_action(thd,
- STRING_WITH_LEN(act)));
- };);
-
- thd->wsrep_trx_meta = *meta;
-
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Applying write set %lld: %p, %zu",
- (long long)wsrep_thd_trx_seqno(thd), buf, buf_len);
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Applying write set");
-#endif /* WSREP_PROC_INFO */
-
- /* tune FK and UK checking policy */
- if (wsrep_slave_UK_checks == FALSE)
- thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS;
- else
- thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS;
-
- if (wsrep_slave_FK_checks == FALSE)
- thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
- else
- thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
-
- /* With galera we assume that the master has done the constraint checks */
- thd->variables.option_bits|= OPTION_NO_CHECK_CONSTRAINT_CHECKS;
-
- if (flags & WSREP_FLAG_ISOLATION)
- {
- thd->wsrep_apply_toi= true;
- /*
- Don't run in transaction mode with TOI actions.
- */
- thd->variables.option_bits&= ~OPTION_BEGIN;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- }
- wsrep_cb_status_t rcode(wsrep_apply_events(thd, buf, buf_len));
-
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Applied write set %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Applied write set");
-#endif /* WSREP_PROC_INFO */
-
- if (WSREP_CB_SUCCESS != rcode)
- {
- wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
- }
-
- if (thd->has_thd_temporary_tables())
- {
- WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..",
- thd->thread_id);
- thd->close_temporary_tables();
- }
-
- return rcode;
-}
-
-static wsrep_cb_status_t wsrep_commit(THD* const thd)
-{
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Committing %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Committing");
-#endif /* WSREP_PROC_INFO */
-
- wsrep_cb_status_t const rcode(trans_commit(thd) ?
- WSREP_CB_FAILURE : WSREP_CB_SUCCESS);
-
- if (WSREP_CB_SUCCESS == rcode)
- {
- thd->wsrep_rgi->cleanup_context(thd, false);
-#ifdef GTID_SUPPORT
- thd->variables.gtid_next.set_automatic();
-#endif /* GTID_SUPPORT */
- if (thd->wsrep_apply_toi)
- {
- wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
- thd->wsrep_trx_meta.gtid.seqno);
- }
- }
-
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Committed %lld", (long long) wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Committed");
-#endif /* WSREP_PROC_INFO */
-
- return rcode;
-}
-
-static wsrep_cb_status_t wsrep_rollback(THD* const thd)
-{
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Rolling back %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Rolling back");
-#endif /* WSREP_PROC_INFO */
-
- wsrep_cb_status_t const rcode(trans_rollback(thd) ?
- WSREP_CB_FAILURE : WSREP_CB_SUCCESS);
-
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Rolled back %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Rolled back");
-#endif /* WSREP_PROC_INFO */
-
- return rcode;
-}
-
-wsrep_cb_status_t wsrep_commit_cb(void* const ctx,
- uint32_t const flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* const exit,
- bool const commit)
-{
- THD* const thd((THD*)ctx);
-
- assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd));
-
- wsrep_cb_status_t rcode;
-
- if (commit)
- rcode = wsrep_commit(thd);
- else
- rcode = wsrep_rollback(thd);
-
- /* Cleanup */
wsrep_set_apply_format(thd, NULL);
- thd->mdl_context.release_transactional_locks();
- thd->reset_query(); /* Mutex protected */
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
- thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
- if (wsrep_slave_count_change < 0 && commit && WSREP_CB_SUCCESS == rcode)
- {
- mysql_mutex_lock(&LOCK_wsrep_slave_threads);
- if (wsrep_slave_count_change < 0)
- {
- wsrep_slave_count_change++;
- *exit = true;
- }
- mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
- }
-
- if (thd->wsrep_applier)
- {
- /* From trans_begin() */
- thd->variables.option_bits|= OPTION_BEGIN;
- thd->server_status|= SERVER_STATUS_IN_TRANS;
- thd->wsrep_apply_toi= false;
- }
-
- return rcode;
-}
-
-
-wsrep_cb_status_t wsrep_unordered_cb(void* const ctx,
- const void* const data,
- size_t const size)
-{
- return WSREP_CB_SUCCESS;
+ DBUG_RETURN(rcode);
}
diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h
index f19d2d46d0c..875c025785b 100644
--- a/sql/wsrep_applier.h
+++ b/sql/wsrep_applier.h
@@ -1,4 +1,4 @@
-/* Copyright 2013 Codership Oy <http://www.codership.com>
+/* Copyright 2013-2015 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,26 +19,56 @@
#include <my_config.h>
#include "../wsrep/wsrep_api.h"
-void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev);
-Format_description_log_event* wsrep_get_apply_format(THD* thd);
+#include "sql_class.h" // THD class
+
+int wsrep_apply_events(THD* thd,
+ Relay_log_info* rli,
+ const void* events_buf,
+ size_t buf_len);
-/* wsrep callback prototypes */
-extern "C" {
-wsrep_cb_status_t wsrep_apply_cb(void *ctx,
- const void* buf, size_t buf_len,
- uint32_t flags,
- const wsrep_trx_meta_t* meta);
+/* Applier error codes, when nothing better is available. */
+#define WSREP_RET_SUCCESS 0 // Success
+#define WSREP_ERR_GENERIC 1 // When in doubt (MySQL default error code)
+#define WSREP_ERR_BAD_EVENT 2 // Can't parse event
+#define WSREP_ERR_NOT_FOUND 3 // Key. table, schema not found
+#define WSREP_ERR_EXISTS 4 // Key, table, schema already exists
+#define WSREP_ERR_WRONG_TYPE 5 // Incompatible data type
+#define WSREP_ERR_FAILED 6 // Operation failed for some internal reason
+#define WSREP_ERR_ABORTED 7 // Operation was aborted externally
-wsrep_cb_status_t wsrep_commit_cb(void *ctx,
- uint32_t flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* exit,
- bool commit);
+class wsrep_apply_error
+{
+public:
+ wsrep_apply_error() : str_(NULL), len_(0) {};
+ ~wsrep_apply_error() { ::free(str_); }
+ /* stores the current THD error info from the diagnostic area. Works only
+ * once, subsequent invocations are ignored in order to preserve the original
+ * condition. */
+ void store(const THD* thd);
+ const char* c_str() const { return str_; }
+ size_t length() const { return len_; }
+ bool is_null() const { return (c_str() == NULL && length() == 0); }
+ wsrep_buf_t get_buf() const
+ {
+ wsrep_buf_t ret= { c_str(), length() };
+ return ret;
+ }
+private:
+ char* str_;
+ size_t len_;
+};
+
+class Format_description_log_event;
+void wsrep_set_apply_format(THD*, Format_description_log_event*);
+Format_description_log_event* wsrep_get_apply_format(THD* thd);
+int wsrep_apply(void* ctx,
+ uint32_t flags,
+ const wsrep_buf_t* buf,
+ const wsrep_trx_meta_t* meta,
+ wsrep_apply_error& err);
-wsrep_cb_status_t wsrep_unordered_cb(void* ctx,
- const void* data,
- size_t size);
+wsrep_cb_status_t wsrep_unordered_cb(void* ctx,
+ const wsrep_buf_t* data);
-} /* extern "C" */
#endif /* WSREP_APPLIER_H */
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index 0cbcdcd64aa..c961ef4b68f 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -14,12 +14,19 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "mariadb.h"
+#include "mysql/service_wsrep.h"
#include "wsrep_binlog.h"
#include "wsrep_priv.h"
#include "log.h"
#include "log_event.h"
#include "wsrep_applier.h"
+#include "transaction.h"
+
+const char *wsrep_fragment_units[] = { "bytes", "rows", "statements", NullS };
+const char *wsrep_SR_store_types[] = { "none", "file", "table", NullS };
+
+
extern handlerton *binlog_hton;
/*
Write the contents of a cache to a memory buffer.
@@ -111,130 +118,6 @@ heap_size(size_t length)
return (length + HEAP_PAGE_SIZE - 1)/HEAP_PAGE_SIZE*HEAP_PAGE_SIZE;
}
-/* append data to writeset */
-static inline wsrep_status_t
-wsrep_append_data(wsrep_t* const wsrep,
- wsrep_ws_handle_t* const ws,
- const void* const data,
- size_t const len)
-{
- struct wsrep_buf const buff = { data, len };
- wsrep_status_t const rc(wsrep->append_data(wsrep, ws, &buff, 1,
- WSREP_DATA_ORDERED, true));
- DBUG_DUMP("buff", (uchar*) data, len);
- if (rc != WSREP_OK)
- {
- WSREP_WARN("append_data() returned %d", rc);
- }
-
- return rc;
-}
-
-/*
- Write the contents of a cache to wsrep provider.
-
- This function quite the same as MYSQL_BIN_LOG::write_cache(),
- with the exception that here we write in buffer instead of log file.
-
- This version reads all of cache into single buffer and then appends to a
- writeset at once.
- */
-static int wsrep_write_cache_once(wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len)
-{
- my_off_t const saved_pos(my_b_tell(cache));
- DBUG_ENTER("wsrep_write_cache_once");
-
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
- {
- WSREP_ERROR("failed to initialize io-cache");
- DBUG_RETURN(ER_ERROR_ON_WRITE);
- }
-
- int err(WSREP_OK);
-
- size_t total_length(0);
- uchar stack_buf[STACK_SIZE]; /* to avoid dynamic allocations for few data*/
- uchar* heap_buf(NULL);
- uchar* buf(stack_buf);
- size_t allocated(sizeof(stack_buf));
- size_t used(0);
-
- uint length(my_b_bytes_in_cache(cache));
- if (unlikely(0 == length)) length = my_b_fill(cache);
-
- if (likely(length > 0)) do
- {
- total_length += length;
- /*
- Bail out if buffer grows too large.
- A temporary fix to avoid allocating indefinitely large buffer,
- not a real limit on a writeset size which includes other things
- like header and keys.
- */
- if (unlikely(total_length > wsrep_max_ws_size))
- {
- WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
- wsrep_max_ws_size, total_length);
- err = WSREP_TRX_SIZE_EXCEEDED;
- goto cleanup;
- }
-
- if (total_length > allocated)
- {
- size_t const new_size(heap_size(total_length));
- uchar* tmp = (uchar *)my_realloc(heap_buf, new_size,
- MYF(MY_ALLOW_ZERO_PTR));
- if (!tmp)
- {
- WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
- allocated, length);
- err = WSREP_TRX_SIZE_EXCEEDED;
- goto cleanup;
- }
-
- heap_buf = tmp;
- buf = heap_buf;
- allocated = new_size;
-
- if (used <= STACK_SIZE && used > 0) // there's data in stack_buf
- {
- DBUG_ASSERT(buf == stack_buf);
- memcpy(heap_buf, stack_buf, used);
- }
- }
-
- memcpy(buf + used, cache->read_pos, length);
- used = total_length;
- if (cache->file < 0)
- {
- cache->read_pos= cache->read_end;
- break;
- }
- } while ((length = my_b_fill(cache)));
-
- if (used > 0)
- err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used);
-
- if (WSREP_OK == err) *len = total_length;
-
-cleanup:
- if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
- {
- WSREP_ERROR("failed to reinitialize io-cache");
- }
-
- if (unlikely(WSREP_OK != err))
- {
- wsrep_dump_rbr_buf_with_header(thd, buf, used);
- }
-
- my_free(heap_buf);
- DBUG_RETURN(err);
-}
-
/*
Write the contents of a cache to wsrep provider.
@@ -243,62 +126,58 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep,
This version uses incremental data appending as it reads it from cache.
*/
-static int wsrep_write_cache_inc(wsrep_t* const wsrep,
- THD* const thd,
+static int wsrep_write_cache_inc(THD* const thd,
IO_CACHE* const cache,
size_t* const len)
{
- my_off_t const saved_pos(my_b_tell(cache));
- DBUG_ENTER("wsrep_write_cache_inc");
-
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
- {
- WSREP_ERROR("failed to initialize io-cache");
- DBUG_RETURN(WSREP_TRX_ERROR);
- }
+ DBUG_ENTER("wsrep_write_cache_inc");
+ my_off_t const saved_pos(my_b_tell(cache));
- int err(WSREP_OK);
+ if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0))
+ {
+ WSREP_ERROR("failed to initialize io-cache");
+ DBUG_RETURN(1);;
+ }
- size_t total_length(0);
+ int ret= 0;
+ size_t total_length(0);
- uint length(my_b_bytes_in_cache(cache));
- if (unlikely(0 == length)) length = my_b_fill(cache);
+ uint length(my_b_bytes_in_cache(cache));
+ if (unlikely(0 == length)) length = my_b_fill(cache);
- if (likely(length > 0)) do
+ if (likely(length > 0))
+ {
+ do
{
- total_length += length;
- /* bail out if buffer grows too large
- not a real limit on a writeset size which includes other things
- like header and keys.
- */
- if (unlikely(total_length > wsrep_max_ws_size))
- {
- WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
- wsrep_max_ws_size, total_length);
- err = WSREP_TRX_SIZE_EXCEEDED;
- goto cleanup;
- }
-
- if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle,
- cache->read_pos, length)))
- goto cleanup;
-
- if (cache->file < 0)
- {
- cache->read_pos= cache->read_end;
- break;
- }
- } while ((length = my_b_fill(cache)));
-
- if (WSREP_OK == err) *len = total_length;
+ total_length += length;
+ /* bail out if buffer grows too large
+ not a real limit on a writeset size which includes other things
+ like header and keys.
+ */
+ if (unlikely(total_length > wsrep_max_ws_size))
+ {
+ WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
+ wsrep_max_ws_size, total_length);
+ ret = 1;
+ goto cleanup;
+ }
+ if (thd->wsrep_cs().append_data(wsrep::const_buffer(cache->read_pos, length)))
+ goto cleanup;
+ cache->read_pos = cache->read_end;
+ } while ((cache->file >= 0) && (length = my_b_fill(cache)));
+ }
+ if (ret == 0)
+ {
+ assert(total_length + thd->wsrep_sr().bytes_certified() == saved_pos);
+ }
cleanup:
- if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
- {
- WSREP_ERROR("failed to reinitialize io-cache");
- }
-
- DBUG_RETURN(err);
+ *len = total_length;
+ if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
+ {
+ WSREP_ERROR("failed to reinitialize io-cache");
+ }
+ DBUG_RETURN(ret);
}
/*
@@ -307,17 +186,11 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
This function quite the same as MYSQL_BIN_LOG::write_cache(),
with the exception that here we write in buffer instead of log file.
*/
-int wsrep_write_cache(wsrep_t* const wsrep,
- THD* const thd,
+int wsrep_write_cache(THD* const thd,
IO_CACHE* const cache,
size_t* const len)
{
- if (wsrep_incremental_data_collection) {
- return wsrep_write_cache_inc(wsrep, thd, cache, len);
- }
- else {
- return wsrep_write_cache_once(wsrep, thd, cache, len);
- }
+ return wsrep_write_cache_inc(thd, cache, len);
}
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
@@ -544,3 +417,123 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf,
DBUG_VOID_RETURN;
}
+
+#include "wsrep_thd_pool.h"
+extern Wsrep_thd_pool *wsrep_thd_pool;
+
+#include "log_event.h"
+// #include "binlog.h"
+
+int wsrep_write_skip_event(THD* thd)
+{
+ DBUG_ENTER("wsrep_write_skip_event");
+ Ignorable_log_event skip_event(thd);
+ int ret= mysql_bin_log.write_event(&skip_event);
+ if (ret)
+ {
+ WSREP_WARN("wsrep_write_skip_event: write to binlog failed: %d", ret);
+ }
+ if (!ret && (ret = trans_commit_stmt(thd)))
+ {
+ WSREP_WARN("wsrep_write_skip_event: statt commit failed");
+ }
+ DBUG_RETURN(ret);
+}
+
+int wsrep_write_dummy_event_low(THD *thd, const char *msg)
+{
+ ::abort();
+ return 0;
+#if 0
+ int ret= 0;
+ if (mysql_bin_log.is_open() && wsrep_gtid_mode)
+ {
+ DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
+
+ /* For restoring orig thd state before returing it back to pool */
+ int wsrep_on= thd->variables.wsrep_on;
+ int sql_log_bin= thd->variables.sql_log_bin;
+ int option_bits= thd->variables.option_bits;
+ enum wsrep_exec_mode exec_mode= thd->wsrep_exec_mode;
+
+ /*
+ Fake that the connection is local client connection for the duration
+ of mysql_bin_log.write_event(), otherwise the write will fail.
+ */
+ thd->wsrep_exec_mode= LOCAL_STATE;
+ thd->variables.wsrep_on= 1;
+ thd->variables.sql_log_bin= 1;
+ thd->variables.option_bits |= OPTION_BIN_LOG;
+
+ Ignorable_log_event skip_event(thd);
+ ret= mysql_bin_log.write_event(&skip_event);
+
+ /* Restore original thd state */
+ thd->wsrep_exec_mode= exec_mode;
+ thd->variables.wsrep_on= wsrep_on;
+ thd->variables.sql_log_bin= sql_log_bin;
+ thd->variables.option_bits= option_bits;
+
+ if (ret)
+ {
+ WSREP_ERROR("Write to binlog failed: %d", ret);
+ abort();
+ unireg_abort(1);
+ }
+ ret= trans_commit_stmt(thd);
+ if (ret)
+ {
+ WSREP_ERROR("STMT commit failed: %d", ret);
+ abort();
+ }
+ }
+
+ return ret;
+#endif
+}
+
+int wsrep_write_dummy_event(THD *orig_thd, const char *msg)
+{
+ return 0;
+#if 0
+ if (WSREP_EMULATE_BINLOG(orig_thd))
+ {
+ return 0;
+ }
+
+ /* Use tmp thd for the transaction to avoid messing up orig_thd
+ transaction state */
+ THD* thd= wsrep_thd_pool->get_thd(0);
+
+ if (!thd)
+ {
+ return 1;
+ }
+
+ /*
+ Use original THD wsrep TRX meta data and WS handle to make
+ commit generate GTID and go through commit ordering hooks.
+ */
+ wsrep_trx_meta_t meta_save= thd->wsrep_trx_meta;
+ thd->wsrep_trx_meta= orig_thd->wsrep_trx_meta;
+ wsrep_ws_handle_t handle_save= thd->wsrep_ws_handle;
+ thd->wsrep_ws_handle= orig_thd->wsrep_ws_handle;
+
+ int ret= wsrep_write_dummy_event_low(thd, msg);
+
+ if (ret || (ret= trans_commit(thd)))
+ {
+ WSREP_ERROR("Failed to write skip event into binlog");
+ abort();
+ unireg_abort(1);
+ }
+
+ thd->wsrep_trx_meta= meta_save;
+ thd->wsrep_ws_handle= handle_save;
+
+ wsrep_thd_pool->release_thd(thd);
+
+ orig_thd->store_globals();
+ return ret;
+#endif
+}
diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h
index 864813d5c98..2daa4c5db4d 100644
--- a/sql/wsrep_binlog.h
+++ b/sql/wsrep_binlog.h
@@ -16,6 +16,35 @@
#ifndef WSREP_BINLOG_H
#define WSREP_BINLOG_H
+#include "my_global.h"
+
+#define WSREP_FRAG_BYTES 0
+#define WSREP_FRAG_ROWS 1
+#define WSREP_FRAG_STATEMENTS 2
+#include "wsrep/streaming_context.hpp"
+static inline enum wsrep::streaming_context::fragment_unit
+wsrep_fragment_unit(ulong unit)
+{
+ switch (unit)
+ {
+ case WSREP_FRAG_BYTES: return wsrep::streaming_context::bytes;
+ case WSREP_FRAG_ROWS: return wsrep::streaming_context::row;
+ case WSREP_FRAG_STATEMENTS: return wsrep::streaming_context::statement;
+ default:
+ DBUG_ASSERT(0);
+ return wsrep::streaming_context::bytes;
+ }
+}
+
+#define WSREP_SR_STORE_NONE 0
+#define WSREP_SR_STORE_FILE 1
+#define WSREP_SR_STORE_TABLE 2
+
+extern ulong wsrep_SR_store_type;
+extern const char *wsrep_fragment_units[];
+extern const char *wsrep_SR_store_types[];
+
+class wsrep_SR_trx;
#include "sql_class.h" // THD, IO_CACHE
#define HEAP_PAGE_SIZE 65536 /* 64K */
@@ -38,23 +67,40 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len);
@param len total amount of data written
@return wsrep error status
*/
-int wsrep_write_cache (wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len);
+int wsrep_write_cache(THD* thd,
+ IO_CACHE* cache,
+ size_t* len);
/* Dump replication buffer to disk */
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len);
-/* Dump replication buffer to disk without intermediate buffer */
-void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache);
-
/* Dump replication buffer along with header to a file */
void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf,
size_t buf_len);
int wsrep_binlog_close_connection(THD* thd);
-int wsrep_binlog_savepoint_set(THD *thd, void *sv);
-int wsrep_binlog_savepoint_rollback(THD *thd, void *sv);
+uint wsrep_get_trans_cache_position(THD *thd);
+
+/**
+ Write a skip event into binlog.
+
+ @param thd Thread object pointer
+ @return Zero in case of success, non-zero on failure.
+*/
+int wsrep_write_skip_event(THD* thd);
+
+/*
+ Write dummy event into binlog in place of unused GTID.
+ The binlog write is done in thd context.
+*/
+int wsrep_write_dummy_event_low(THD *thd, const char *msg);
+/*
+ Write dummy event to binlog in place of unused GTID and
+ commit. The binlog write and commit are done in temporary
+ thd context, the original thd state is not altered.
+*/
+int wsrep_write_dummy_event(THD* thd, const char *msg);
+
+void wsrep_register_binlog_handler(THD *thd, bool trx);
#endif /* WSREP_BINLOG_H */
diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc
new file mode 100644
index 00000000000..ee7a1b904c5
--- /dev/null
+++ b/sql/wsrep_client_service.cc
@@ -0,0 +1,300 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "wsrep_client_service.h"
+#include "wsrep_high_priority_service.h"
+#include "wsrep_applier.h" /* wsrep_apply_events() */
+#include "wsrep_binlog.h" /* wsrep_dump_rbr_buf() */
+#include "wsrep_schema.h" /* remove_fragments() */
+#include "wsrep_thd.h"
+#include "wsrep_xid.h"
+#include "wsrep_trans_observer.h"
+
+#include "sql_base.h" /* close_temporary_table() */
+#include "sql_class.h" /* THD */
+#include "sql_parse.h" /* stmt_causes_implicit_commit() */
+#include "rpl_filter.h" /* binlog_filter */
+#include "rpl_rli.h" /* Relay_log_info */
+#include "slave.h" /* opt_log_slave_updates */
+#include "transaction.h" /* trans_commit()... */
+#include "log.h" /* stmt_has_updated_trans_table() */
+//#include "debug_sync.h"
+#include "mysql/service_debug_sync.h"
+namespace
+{
+
+void debug_sync_caller(THD* thd, const char* sync_point)
+{
+#ifdef ENABLED_DEBUG_SYNC_OUT
+ debug_sync_set_action(thd, sync_point, strlen(sync_point));
+#endif
+#ifdef ENABLED_DEBUG_SYNC
+ debug_sync_service(thd, sync_point, strlen(sync_point));
+#endif
+
+}
+}
+
+Wsrep_client_service::Wsrep_client_service(THD* thd,
+ Wsrep_client_state& client_state)
+ : wsrep::client_service()
+ , m_thd(thd)
+ , m_client_state(client_state)
+{ }
+
+bool Wsrep_client_service::do_2pc() const
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ THD_TRANS* trans= &m_thd->transaction.all.ha_list ?
+ &m_thd->transaction.all :
+ &m_thd->transaction.stmt;
+ return (!trans->no_2pc && trans->rw_ha_count > 1);
+
+}
+
+void Wsrep_client_service::store_globals()
+{
+ DBUG_ENTER("Wsrep_client_service::store_globals");
+ m_thd->store_globals();
+ DBUG_VOID_RETURN;
+}
+
+void Wsrep_client_service::reset_globals()
+{
+ DBUG_ENTER("Wsrep_client_service::reset_globals");
+ m_thd->reset_globals();
+ DBUG_VOID_RETURN;
+}
+
+bool Wsrep_client_service::interrupted() const
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ mysql_mutex_lock(&m_thd->LOCK_thd_data);
+ bool ret= (m_thd->killed != NOT_KILLED);
+ mysql_mutex_unlock(&m_thd->LOCK_thd_data);
+ return ret;
+}
+
+int Wsrep_client_service::prepare_data_for_replication()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_ENTER("Wsrep_client_service::prepare_data_for_replication");
+ size_t data_len= 0;
+ IO_CACHE* cache= wsrep_get_trans_cache(m_thd);
+
+ if (cache)
+ {
+ m_thd->binlog_flush_pending_rows_event(true);
+ if (wsrep_write_cache(m_thd, cache, &data_len))
+ {
+ WSREP_ERROR("rbr write fail, data_len: %zu",
+ data_len);
+ // wsrep_override_error(m_thd, ER_ERROR_DURING_COMMIT);
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (data_len == 0)
+ {
+ if (m_thd->get_stmt_da()->is_ok() &&
+ m_thd->get_stmt_da()->affected_rows() > 0 &&
+ !binlog_filter->is_on() &&
+ !m_thd->wsrep_trx().is_streaming())
+ {
+ WSREP_DEBUG("empty rbr buffer, query: %s, "
+ "affected rows: %llu, "
+ "changed tables: %d, "
+ "sql_log_bin: %d",
+ WSREP_QUERY(m_thd),
+ m_thd->get_stmt_da()->affected_rows(),
+ stmt_has_updated_trans_table(m_thd),
+ m_thd->variables.sql_log_bin);
+ }
+ else
+ {
+ WSREP_DEBUG("empty rbr buffer, query: %s", WSREP_QUERY(m_thd));
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+void Wsrep_client_service::cleanup_transaction()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ if (WSREP_EMULATE_BINLOG(m_thd)) wsrep_thd_binlog_trx_reset(m_thd);
+ m_thd->wsrep_affected_rows= 0;
+}
+
+
+int Wsrep_client_service::prepare_fragment_for_replication(wsrep::mutable_buffer& buffer)
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ THD* thd= m_thd;
+ DBUG_ENTER("Wsrep_client_service::prepare_fragment_for_replication");
+ IO_CACHE* cache= wsrep_get_trans_cache(thd);
+ thd->binlog_flush_pending_rows_event(true);
+
+ const my_off_t saved_pos(my_b_tell(cache));
+ if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0))
+ {
+ DBUG_RETURN(1);
+ }
+
+ int ret= 0;
+ size_t total_length= 0;
+ size_t length= my_b_bytes_in_cache(cache);
+
+ if (!length)
+ {
+ length= my_b_fill(cache);
+ }
+
+ if (length > 0)
+ {
+ do
+ {
+ total_length+= length;
+ if (total_length > wsrep_max_ws_size)
+ {
+ WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
+ wsrep_max_ws_size, total_length);
+ ret= 1;
+ goto cleanup;
+ }
+
+ buffer.push_back(reinterpret_cast<const char*>(cache->read_pos),
+ reinterpret_cast<const char*>(cache->read_pos + length));
+ cache->read_pos= cache->read_end;
+ }
+ while (cache->file >= 0 && (length= my_b_fill(cache)));
+ }
+ DBUG_ASSERT(total_length == buffer.size());
+cleanup:
+ if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
+ {
+ WSREP_WARN("Failed to reinitialize IO cache");
+ ret= 1;
+ }
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_client_service::remove_fragments()
+{
+ DBUG_ENTER("Wsrep_client_service::remove_fragments");
+ if (wsrep_schema->remove_fragments(m_thd,
+ Wsrep_server_state::instance().id(),
+ m_thd->wsrep_trx().id(),
+ m_thd->wsrep_sr().fragments()))
+ {
+ WSREP_DEBUG("Failed to remove fragments from SR storage for transaction "
+ "%lu, %llu",
+ m_thd->thread_id, m_thd->wsrep_trx().id().get());
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+bool Wsrep_client_service::statement_allowed_for_streaming() const
+{
+ /*
+ Todo: Decide if implicit commit is allowed with streaming
+ replication.
+ !stmt_causes_implicit_commit(m_thd, CF_IMPLICIT_COMMIT_BEGIN);
+ */
+ return true;
+}
+
+size_t Wsrep_client_service::bytes_generated() const
+{
+ IO_CACHE* cache= wsrep_get_trans_cache(m_thd);
+ if (cache)
+ {
+ m_thd->binlog_flush_pending_rows_event(true);
+ return my_b_tell(cache);
+ }
+ return 0;
+}
+
+void Wsrep_client_service::will_replay()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ ++wsrep_replaying;
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+}
+
+enum wsrep::provider::status Wsrep_client_service::replay()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ Wsrep_replayer_service replayer_service(m_thd);
+ wsrep::provider& provider(m_thd->wsrep_cs().provider());
+ mysql_mutex_lock(&m_thd->LOCK_thd_data);
+ m_thd->killed= NOT_KILLED;
+ mysql_mutex_unlock(&m_thd->LOCK_thd_data);
+ enum wsrep::provider::status ret=
+ provider.replay(m_thd->wsrep_trx().ws_handle(), &replayer_service);
+ replayer_service.replay_status(ret);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ --wsrep_replaying;
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ return ret;
+}
+
+void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock)
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ lock.unlock();
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ while (wsrep_replaying > 0)
+ {
+ mysql_cond_wait(&COND_wsrep_replaying, &LOCK_wsrep_replaying);
+ }
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ lock.lock();
+}
+
+void Wsrep_client_service::debug_sync(const char* sync_point)
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ debug_sync_caller(m_thd, sync_point);
+}
+
+void Wsrep_client_service::debug_crash(const char* crash_point)
+{
+ // DBUG_ASSERT(m_thd == current_thd);
+ DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE(); );
+}
+
+int Wsrep_client_service::bf_rollback()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_ENTER("Wsrep_client_service::rollback");
+
+ int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
+ if (m_thd->locked_tables_mode && m_thd->lock)
+ {
+ m_thd->locked_tables_list.unlock_locked_tables(m_thd);
+ m_thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
+ }
+ if (m_thd->global_read_lock.is_acquired())
+ {
+ m_thd->global_read_lock.unlock_global_read_lock(m_thd);
+ }
+ m_thd->mdl_context.release_transactional_locks();
+ m_thd->mdl_context.release_explicit_locks();
+
+ DBUG_RETURN(ret);
+}
diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h
new file mode 100644
index 00000000000..c2fe4e3985b
--- /dev/null
+++ b/sql/wsrep_client_service.h
@@ -0,0 +1,64 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/** @file wsrep_client_service.h
+
+ This file provides declaratios for client service implementation.
+ See wsrep/client_service.hpp for interface documentation.
+*/
+
+#ifndef WSREP_CLIENT_SERVICE_H
+#define WSREP_CLIENT_SERVICE_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/client_service.hpp"
+#include "../wsrep-lib/include/wsrep/client_state.hpp"
+#include "../wsrep-lib/include/wsrep/exception.hpp" /* not_implemented_error, remove when finished */
+
+class THD;
+class Wsrep_client_state;
+class Wsrep_high_priority_context;
+
+class Wsrep_client_service : public wsrep::client_service
+{
+public:
+ Wsrep_client_service(THD*, Wsrep_client_state&);
+
+ bool do_2pc() const;
+ bool interrupted() const;
+ void reset_globals();
+ void store_globals();
+ int prepare_data_for_replication();
+ void cleanup_transaction();
+ bool statement_allowed_for_streaming() const;
+ size_t bytes_generated() const;
+ int prepare_fragment_for_replication(wsrep::mutable_buffer&);
+ int remove_fragments();
+ void emergency_shutdown()
+ { throw wsrep::not_implemented_error(); }
+ void will_replay();
+ enum wsrep::provider::status replay();
+ void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&);
+ void debug_sync(const char*);
+ void debug_crash(const char*);
+ int bf_rollback();
+private:
+ friend class Wsrep_server_service;
+ THD* m_thd;
+ Wsrep_client_state& m_client_state;
+};
+
+
+#endif /* WSREP_CLIENT_SERVICE_H */
diff --git a/sql/wsrep_client_state.h b/sql/wsrep_client_state.h
new file mode 100644
index 00000000000..5d32e92eaa4
--- /dev/null
+++ b/sql/wsrep_client_state.h
@@ -0,0 +1,47 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_CLIENT_STATE_H
+#define WSREP_CLIENT_STATE_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/client_state.hpp"
+#include "my_global.h"
+
+class THD;
+
+class Wsrep_client_state : public wsrep::client_state
+{
+public:
+ Wsrep_client_state(THD* thd,
+ wsrep::mutex& mutex,
+ wsrep::condition_variable& cond,
+ wsrep::server_state& server_state,
+ wsrep::client_service& client_service,
+ const wsrep::client_id& id)
+ : wsrep::client_state(mutex,
+ cond,
+ server_state,
+ client_service,
+ id,
+ wsrep::client_state::m_local)
+ , m_thd(thd)
+ { }
+ THD* thd() { return m_thd; }
+private:
+ THD* m_thd;
+};
+
+#endif /* WSREP_CLIENT_STATE_H */
diff --git a/sql/wsrep_condition_variable.h b/sql/wsrep_condition_variable.h
new file mode 100644
index 00000000000..fa22de4d845
--- /dev/null
+++ b/sql/wsrep_condition_variable.h
@@ -0,0 +1,54 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_CONDITION_VARIABLE_H
+#define WSREP_CONDITION_VARIABLE_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/condition_variable.hpp"
+
+/* implementation */
+#include "my_pthread.h"
+
+class Wsrep_condition_variable : public wsrep::condition_variable
+{
+public:
+
+ Wsrep_condition_variable(mysql_cond_t& cond)
+ : m_cond(cond)
+ { }
+ ~Wsrep_condition_variable()
+ { }
+
+ void notify_one()
+ {
+ mysql_cond_signal(&m_cond);
+ }
+
+ void notify_all()
+ {
+ mysql_cond_broadcast(&m_cond);
+ }
+
+ void wait(wsrep::unique_lock<wsrep::mutex>& lock)
+ {
+ mysql_mutex_t* mutex= static_cast<mysql_mutex_t*>(lock.mutex().native());
+ mysql_cond_wait(&m_cond, mutex);
+ }
+private:
+ mysql_cond_t& m_cond;
+};
+
+#endif /* WSREP_CONDITION_VARIABLE_H */
diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc
index 9a4bbd01bcd..87ee0334ce0 100644
--- a/sql/wsrep_dummy.cc
+++ b/sql/wsrep_dummy.cc
@@ -17,7 +17,7 @@
#include <sql_class.h>
#include <mysql/service_wsrep.h>
-my_bool wsrep_thd_is_BF(THD *, my_bool)
+my_bool wsrep_thd_is_BF(void *, my_bool)
{ return 0; }
int wsrep_trx_order_before(THD *, THD *)
@@ -26,7 +26,8 @@ int wsrep_trx_order_before(THD *, THD *)
enum wsrep_conflict_state wsrep_thd_conflict_state(THD *, my_bool)
{ return NO_CONFLICT; }
-int wsrep_is_wsrep_xid(const XID*)
+//int wsrep_is_wsrep_xid(const XID*)
+int wsrep_is_wsrep_xid(const void* xid)
{ return 0; }
long long wsrep_xid_seqno(const XID* x)
@@ -38,6 +39,10 @@ const unsigned char* wsrep_xid_uuid(const XID*)
return uuid;
}
+#ifdef TODO
+bool wsrep_prepare_key_for_innodb(THD* thd, const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*)
+{ return -1; }
+#endif
bool wsrep_prepare_key(const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*)
{ return 0; }
diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc
new file mode 100644
index 00000000000..4408ee99f44
--- /dev/null
+++ b/sql/wsrep_high_priority_service.cc
@@ -0,0 +1,681 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "wsrep_high_priority_service.h"
+#include "wsrep_applier.h"
+#include "wsrep_binlog.h"
+#include "wsrep_schema.h"
+#include "wsrep_xid.h"
+#include "wsrep_trans_observer.h"
+
+#include "sql_class.h" /* THD */
+#include "transaction.h"
+#include "debug_sync.h"
+/* RLI */
+#include "rpl_rli.h"
+#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1
+#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2
+#include "slave.h"
+#include "rpl_mi.h"
+
+namespace
+{
+/*
+ Scoped mode for applying non-transactional write sets (TOI)
+ */
+class Wsrep_non_trans_mode
+{
+public:
+ Wsrep_non_trans_mode(THD* thd, const wsrep::ws_meta& ws_meta)
+ : m_thd(thd)
+ , m_option_bits(thd->variables.option_bits)
+ , m_server_status(thd->server_status)
+ {
+ m_thd->variables.option_bits&= ~OPTION_BEGIN;
+ m_thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ m_thd->wsrep_cs().enter_toi(ws_meta);
+ }
+ ~Wsrep_non_trans_mode()
+ {
+ m_thd->variables.option_bits= m_option_bits;
+ m_thd->server_status= m_server_status;
+ m_thd->wsrep_cs().leave_toi();
+ }
+private:
+ Wsrep_non_trans_mode(const Wsrep_non_trans_mode&);
+ Wsrep_non_trans_mode& operator=(const Wsrep_non_trans_mode&);
+ THD* m_thd;
+ ulonglong m_option_bits;
+ uint m_server_status;
+};
+}
+
+static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
+{
+ Relay_log_info* rli= new Relay_log_info(false);
+
+ if (!rli->relay_log.description_event_for_exec)
+ {
+ rli->relay_log.description_event_for_exec=
+ new Format_description_log_event(4);
+ }
+
+ static LEX_CSTRING connection_name= { STRING_WITH_LEN("wsrep") };
+
+ /*
+ Master_info's constructor initializes rpl_filter by either an already
+ constructed Rpl_filter object from global 'rpl_filters' list if the
+ specified connection name is same, or it constructs a new Rpl_filter
+ object and adds it to rpl_filters. This object is later destructed by
+ Mater_info's destructor by looking it up based on connection name in
+ rpl_filters list.
+
+ However, since all Master_info objects created here would share same
+ connection name ("wsrep"), destruction of any of the existing Master_info
+ objects (in wsrep_return_from_bf_mode()) would free rpl_filter referenced
+ by any/all existing Master_info objects.
+
+ In order to avoid that, we have added a check in Master_info's destructor
+ to not free the "wsrep" rpl_filter. It will eventually be freed by
+ free_all_rpl_filters() when server terminates.
+ */
+ rli->mi = new Master_info(&connection_name, false);
+
+ struct rpl_group_info *rgi= new rpl_group_info(rli);
+ rgi->thd= rli->sql_driver_thd= current_thd;
+
+ if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()))
+ {
+ rgi->deferred_events= new Deferred_log_events(rli);
+ }
+
+ return rgi;
+}
+
+static void wsrep_setup_uk_and_fk_checks(THD* thd)
+{
+ /* Tune FK and UK checking policy. These are reset back to original
+ in Wsrep_high_priority_service destructor. */
+ if (wsrep_slave_UK_checks == FALSE)
+ thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS;
+ else
+ thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS;
+
+ if (wsrep_slave_FK_checks == FALSE)
+ thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
+ else
+ thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
+}
+
+/****************************************************************************
+ High priority service
+*****************************************************************************/
+
+Wsrep_high_priority_service::Wsrep_high_priority_service(THD* thd)
+ : wsrep::high_priority_service(Wsrep_server_state::instance())
+ , wsrep::high_priority_context(thd->wsrep_cs())
+ , m_thd(thd)
+ , m_rli()
+{
+ LEX_CSTRING db_str= { NULL, 0 };
+ m_shadow.option_bits = thd->variables.option_bits;
+ m_shadow.server_status = thd->server_status;
+ m_shadow.vio = thd->net.vio;
+ m_shadow.tx_isolation = thd->variables.tx_isolation;
+ m_shadow.db = (char *)thd->db.str;
+ m_shadow.db_length = thd->db.length;
+ //m_shadow.user_time = hrtime_to_my_time(thd->user_time);
+ m_shadow.user_time = thd->user_time;
+ m_shadow.row_count_func= thd->get_row_count_func();
+ m_shadow.wsrep_applier = thd->wsrep_applier;
+
+ /* Disable general logging on applier threads */
+ thd->variables.option_bits |= OPTION_LOG_OFF;
+ /* Enable binlogging if opt_log_slave_updates is set */
+ if (opt_log_slave_updates)
+ thd->variables.option_bits|= OPTION_BIN_LOG;
+ else
+ thd->variables.option_bits&= ~(OPTION_BIN_LOG);
+
+ thd->net.vio= 0;
+ thd->reset_db(&db_str);
+ thd->clear_error();
+ thd->variables.tx_isolation = ISO_READ_COMMITTED;
+ thd->tx_isolation = ISO_READ_COMMITTED;
+
+ /* From trans_begin() */
+ thd->variables.option_bits|= OPTION_BEGIN;
+ thd->server_status|= SERVER_STATUS_IN_TRANS;
+
+ /* Make THD wsrep_applier so that it cannot be killed */
+ thd->wsrep_applier= true;
+
+ if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay");
+
+ m_rgi= thd->wsrep_rgi;
+ m_rgi->thd = thd;
+ m_rli= m_rgi->rli;
+ thd_proc_info(thd, "wsrep applier idle");
+}
+
+Wsrep_high_priority_service::~Wsrep_high_priority_service()
+{
+ THD* thd= m_thd;
+ thd->variables.option_bits = m_shadow.option_bits;
+ thd->server_status = m_shadow.server_status;
+ thd->net.vio = m_shadow.vio;
+ thd->variables.tx_isolation = m_shadow.tx_isolation;
+ LEX_CSTRING db_str= { m_shadow.db, m_shadow.db_length };
+ thd->reset_db(&db_str);
+ thd->user_time = m_shadow.user_time;
+
+ if (thd->wsrep_rgi && thd->wsrep_rgi->rli)
+ delete thd->wsrep_rgi->rli->mi;
+ if (thd->wsrep_rgi)
+ delete thd->wsrep_rgi->rli;
+ delete thd->wsrep_rgi;
+ thd->wsrep_rgi= NULL;
+
+ thd->set_row_count_func(m_shadow.row_count_func);
+ thd->wsrep_applier = m_shadow.wsrep_applier;
+}
+
+int Wsrep_high_priority_service::start_transaction(
+ const wsrep::ws_handle& ws_handle, const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER(" Wsrep_high_priority_service::start_transaction");
+ DBUG_RETURN(m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta));
+}
+
+const wsrep::transaction& Wsrep_high_priority_service::transaction() const
+{
+ DBUG_ENTER(" Wsrep_high_priority_service::transaction");
+ DBUG_RETURN(m_thd->wsrep_trx());
+}
+
+void Wsrep_high_priority_service::adopt_transaction(const wsrep::transaction& transaction)
+{
+ DBUG_ENTER(" Wsrep_high_priority_service::adopt_transaction");
+ m_thd->wsrep_cs().adopt_transaction(transaction);
+ DBUG_VOID_RETURN;
+}
+
+
+int Wsrep_high_priority_service::append_fragment_and_commit(
+ const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::append_fragment");
+ int ret= start_transaction(ws_handle, ws_meta);
+ ret= ret || wsrep_schema->append_fragment(m_thd,
+ ws_meta.server_id(),
+ ws_meta.transaction_id(),
+ ws_meta.seqno(),
+ ws_meta.flags(),
+ data);
+
+ /*
+ Note: The commit code below seems to be identical to
+ Wsrep_storage_service::commit(). Consider implementing
+ common utility function to deal with commit.
+ */
+ const bool do_binlog_commit= (opt_log_slave_updates &&
+ wsrep_gtid_mode &&
+ m_thd->variables.gtid_seq_no);
+ /*
+ Write skip event into binlog if gtid_mode is on. This is to
+ maintain gtid continuity.
+ */
+ if (do_binlog_commit)
+ {
+ ret= wsrep_write_skip_event(m_thd);
+ }
+
+ if (!ret)
+ {
+ ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle,
+ ws_meta, true);
+ }
+
+ if (!ret)
+ {
+ DBUG_ASSERT(wsrep_thd_trx_seqno(m_thd) > 0);
+ if (!do_binlog_commit)
+ {
+ ret= wsrep_before_commit(m_thd, true);
+ }
+ ret= ret || trans_commit(m_thd);
+ if (!do_binlog_commit)
+ {
+ if (opt_log_slave_updates)
+ {
+ ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error());
+ }
+ ret= ret || wsrep_after_commit(m_thd, true);
+ }
+ }
+ m_thd->wsrep_cs().after_applying();
+ m_thd->mdl_context.release_transactional_locks();
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_high_priority_service::remove_fragments(const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::remove_fragments");
+ int ret= wsrep_schema->remove_fragments(m_thd,
+ ws_meta.server_id(),
+ ws_meta.transaction_id(),
+ m_thd->wsrep_sr().fragments());
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_high_priority_service::commit(const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::commit");
+ THD* thd= m_thd;
+ DBUG_ASSERT(thd->wsrep_trx().active());
+ thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, true);
+ thd_proc_info(thd, "committing");
+
+ int ret= 0;
+ const bool is_ordered= !ws_meta.seqno().is_undefined();
+ /* If opt_log_slave_updates is not on, applier does not write
+ anything to binlog cache and neither wsrep_before_commit()
+ nor wsrep_after_commit() we be reached from binlog code
+ path for applier. Therefore run wsrep_before_commit()
+ and wsrep_after_commit() here. wsrep_ordered_commit()
+ will be called from wsrep_ordered_commit_if_no_binlog(). */
+ if (!opt_log_slave_updates && !opt_bin_log && is_ordered)
+ {
+ if (m_thd->transaction.all.no_2pc == false)
+ {
+ ret= wsrep_before_prepare(thd, true);
+ ret= ret || wsrep_after_prepare(thd, true);
+ }
+ ret= ret || wsrep_before_commit(thd, true);
+ }
+ ret= ret || trans_commit(thd);
+
+ if (ret == 0)
+ {
+ m_rgi->cleanup_context(thd, 0);
+ }
+
+ if (ret == 0 && !opt_log_slave_updates && !opt_bin_log && is_ordered)
+ {
+ ret= wsrep_after_commit(thd, true);
+ }
+
+ m_thd->mdl_context.release_transactional_locks();
+
+ thd_proc_info(thd, "wsrep applier committed");
+
+ if (!is_ordered)
+ {
+ /* Wsrep commit was not ordered so it does not go through commit time
+ hooks and remains active. Roll it back to make cleanup happen
+ in after_applying() call. */
+ m_thd->wsrep_cs().before_rollback();
+ m_thd->wsrep_cs().after_rollback();
+ }
+
+ must_exit_ = check_exit_status();
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::rollback");
+ m_thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, false);
+ int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
+ m_thd->mdl_context.release_transactional_locks();
+ m_thd->mdl_context.release_explicit_locks();
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::apply_toi");
+ THD* thd= m_thd;
+ Wsrep_non_trans_mode non_trans_mode(thd, ws_meta);
+
+ wsrep::client_state& client_state(thd->wsrep_cs());
+ DBUG_ASSERT(client_state.in_toi());
+
+ thd_proc_info(thd, "wsrep applier toi");
+
+ WSREP_DEBUG("Wsrep_high_priority_service::apply_toi: %lld",
+ client_state.toi_meta().seqno().get());
+
+ int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size());
+ if (ret != 0 || thd->wsrep_has_ignored_error)
+ {
+ wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size());
+ thd->wsrep_has_ignored_error= false;
+ /* todo: error voting */
+ }
+ trans_commit(thd);
+
+ thd->close_temporary_tables();
+#ifdef OUT
+ bool locked;
+ TMP_TABLE_SHARE *share;
+ locked= lock_temporary_tables();
+ All_tmp_tables_list::Iterator it(*thd->temporary_tables);
+ while ((share= it++))
+ {
+ WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s",
+ thd->thread_id, share->db.str, share->table_name.str);
+ close_temporary_table(thd, share, 1, 1);
+ }
+ if (locked)
+ {
+ unlock_temporary_tables();
+ }
+#endif
+ wsrep_set_SE_checkpoint(client_state.toi_meta().gtid());
+
+ must_exit_ = check_exit_status();
+
+ DBUG_RETURN(ret);
+}
+
+void Wsrep_high_priority_service::store_globals()
+{
+ DBUG_ENTER("Wsrep_high_priority_service::store_globals");
+ /* In addition to calling THD::store_globals(), call
+ wsrep::client_state::store_globals() to gain ownership of
+ the client state */
+ m_thd->store_globals();
+ m_thd->wsrep_cs().store_globals();
+ DBUG_VOID_RETURN;
+}
+
+void Wsrep_high_priority_service::reset_globals()
+{
+ DBUG_ENTER("Wsrep_high_priority_service::reset_globals");
+ m_thd->reset_globals();
+ DBUG_VOID_RETURN;
+}
+
+void Wsrep_high_priority_service::switch_execution_context(wsrep::high_priority_service& orig_high_priority_service)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::switch_execution_context");
+ Wsrep_high_priority_service&
+ orig_hps= static_cast<Wsrep_high_priority_service&>(orig_high_priority_service);
+ m_thd->thread_stack= orig_hps.m_thd->thread_stack;
+ DBUG_VOID_RETURN;
+}
+
+int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_high_priority_service::log_dummy_write_set");
+ int ret= 0;
+ DBUG_PRINT("info",
+ ("Wsrep_high_priority_service::log_dummy_write_set: seqno=%lld",
+ ws_meta.seqno().get()));
+ m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta);
+ WSREP_DEBUG("Log dummy write set %lld", ws_meta.seqno().get());
+ if (!(opt_log_slave_updates && wsrep_gtid_mode && m_thd->variables.gtid_seq_no))
+ {
+ m_thd->wsrep_cs().before_rollback();
+ m_thd->wsrep_cs().after_rollback();
+ }
+ m_thd->wsrep_cs().after_applying();
+ DBUG_RETURN(ret);
+}
+
+void Wsrep_high_priority_service::debug_crash(const char* crash_point)
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE(););
+}
+
+/****************************************************************************
+ Applier service
+*****************************************************************************/
+
+Wsrep_applier_service::Wsrep_applier_service(THD* thd)
+ : Wsrep_high_priority_service(thd)
+{
+ thd->wsrep_applier_service= this;
+ thd->wsrep_cs().open(wsrep::client_id(thd->thread_id));
+ thd->wsrep_cs().before_command();
+ thd->wsrep_cs().debug_log_level(wsrep_debug);
+
+}
+
+Wsrep_applier_service::~Wsrep_applier_service()
+{
+ m_thd->wsrep_cs().after_command_before_result();
+ m_thd->wsrep_cs().after_command_after_result();
+ m_thd->wsrep_cs().close();
+ m_thd->wsrep_cs().cleanup();
+}
+
+int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_applier_service::apply_write_set");
+ THD* thd= m_thd;
+
+ thd->variables.option_bits |= OPTION_BEGIN;
+ thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT;
+ DBUG_ASSERT(thd->wsrep_trx().active());
+ DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_executing);
+
+ thd_proc_info(thd, "applying write set");
+ /* moved dbug sync point here, after possible THD switch for SR transactions
+ has ben done
+ */
+ /* Allow tests to block the applier thread using the DBUG facilities */
+ DBUG_EXECUTE_IF("sync.wsrep_apply_cb",
+ {
+ const char act[]=
+ "now "
+ "SIGNAL sync.wsrep_apply_cb_reached "
+ "WAIT_FOR signal.wsrep_apply_cb";
+ DBUG_ASSERT(!debug_sync_set_action(thd,
+ STRING_WITH_LEN(act)));
+ };);
+
+ wsrep_setup_uk_and_fk_checks(thd);
+
+ int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size());
+
+ if (ret || thd->wsrep_has_ignored_error)
+ {
+ wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size());
+ }
+
+ thd->close_temporary_tables();
+#ifdef OUT
+ TABLE *tmp;
+ while ((tmp = thd->temporary_tables))
+ {
+ WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s",
+ m_thd->thread_id,
+ (tmp->s) ? tmp->s->db.str : "void",
+ (tmp->s) ? tmp->s->table_name.str : "void");
+ close_temporary_table(m_thd, tmp, 1, 1);
+ }
+#endif
+ if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit))
+ {
+ thd->wsrep_cs().fragment_applied(ws_meta.seqno());
+ }
+ thd_proc_info(thd, "wsrep applied write set");
+ DBUG_RETURN(ret);
+}
+
+void Wsrep_applier_service::after_apply()
+{
+ DBUG_ENTER("Wsrep_applier_service::after_apply");
+ wsrep_after_apply(m_thd);
+ // thd_proc_info(m_thd, "wsrep applier idle");
+ DBUG_VOID_RETURN;
+}
+
+bool Wsrep_applier_service::check_exit_status() const
+{
+ bool ret= false;
+ mysql_mutex_lock(&LOCK_wsrep_slave_threads);
+ if (wsrep_slave_count_change < 0)
+ {
+ ++wsrep_slave_count_change;
+ ret= true;
+ }
+ mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
+ return ret;
+}
+
+/****************************************************************************
+ Replayer service
+*****************************************************************************/
+
+Wsrep_replayer_service::Wsrep_replayer_service(THD* thd)
+ : Wsrep_high_priority_service(thd)
+ , m_da_shadow()
+ , m_replay_status()
+{
+ /* Response must not have been sent to client */
+ DBUG_ASSERT(!thd->get_stmt_da()->is_sent());
+ /* PS reprepare observer should have been removed already
+ open_table() will fail if we have dangling observer here */
+ DBUG_ASSERT(!thd->m_reprepare_observer);
+ /* Replaying should happen always from after_statement() hook
+ after rollback, which should guarantee that there are no
+ transactional locks */
+ DBUG_ASSERT(!thd->mdl_context.has_transactional_locks());
+
+ /* Make a shadow copy of diagnostics area and reset */
+ m_da_shadow.status= thd->get_stmt_da()->status();
+ if (m_da_shadow.status == Diagnostics_area::DA_OK)
+ {
+ m_da_shadow.affected_rows= thd->get_stmt_da()->affected_rows();
+ m_da_shadow.last_insert_id= thd->get_stmt_da()->last_insert_id();
+ strmake(m_da_shadow.message, thd->get_stmt_da()->message(),
+ sizeof(m_da_shadow.message) - 1);
+ }
+ thd->get_stmt_da()->reset_diagnostics_area();
+
+ /* Release explicit locks */
+ if (thd->locked_tables_mode && thd->lock)
+ {
+ WSREP_WARN("releasing table lock for replaying (%ld)",
+ thd->thread_id);
+ thd->locked_tables_list.unlock_locked_tables(thd);
+ thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
+ }
+
+ /*
+ Replaying will call MYSQL_START_STATEMENT when handling
+ BEGIN Query_log_event so end statement must be called before
+ replaying.
+ */
+ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->m_statement_psi= NULL;
+ thd->m_digest= NULL;
+ thd_proc_info(thd, "wsrep replaying trx");
+}
+
+Wsrep_replayer_service::~Wsrep_replayer_service()
+{
+ THD* thd= m_thd;
+ DBUG_ASSERT(!thd->get_stmt_da()->is_sent());
+ DBUG_ASSERT(!thd->get_stmt_da()->is_set());
+ if (m_replay_status == wsrep::provider::success)
+ {
+ DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_success);
+ thd->killed= NOT_KILLED;
+ if (m_da_shadow.status == Diagnostics_area::DA_OK)
+ {
+ my_ok(thd,
+ m_da_shadow.affected_rows,
+ m_da_shadow.last_insert_id,
+ m_da_shadow.message);
+ }
+ else
+ {
+ my_ok(thd);
+ }
+ }
+ else if (m_replay_status == wsrep::provider::error_certification_failed)
+ {
+ DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_deadlock_error);
+ }
+ else
+ {
+ DBUG_ASSERT(0);
+ WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
+ m_replay_status,
+ thd->db.str, WSREP_QUERY(thd));
+ unireg_abort(1);
+ }
+}
+
+int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_replayer_service::apply_write_set");
+ THD* thd= m_thd;
+
+ DBUG_ASSERT(thd->wsrep_trx().active());
+ DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_replaying);
+
+ wsrep_setup_uk_and_fk_checks(thd);
+
+ int ret= 0;
+ if (!wsrep::starts_transaction(ws_meta.flags()))
+ {
+ DBUG_ASSERT(thd->wsrep_trx().is_streaming());
+ ret= wsrep_schema->replay_transaction(thd,
+ m_rli,
+ ws_meta,
+ thd->wsrep_sr().fragments());
+ }
+
+ ret= ret || wsrep_apply_events(thd, m_rli, data.data(), data.size());
+
+ if (ret || thd->wsrep_has_ignored_error)
+ {
+ wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size());
+ }
+
+ thd->close_temporary_tables();
+#ifdef OUT
+ TABLE *tmp;
+ while ((tmp = thd->temporary_tables))
+ {
+ WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s",
+ m_thd->thread_id,
+ (tmp->s) ? tmp->s->db.str : "void",
+ (tmp->s) ? tmp->s->table_name.str : "void");
+ close_temporary_table(m_thd, tmp, 1, 1);
+ }
+#endif
+ if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit))
+ {
+ thd->wsrep_cs().fragment_applied(ws_meta.seqno());
+ }
+
+ thd_proc_info(thd, "wsrep replayed write set");
+ DBUG_RETURN(ret);
+}
diff --git a/sql/wsrep_high_priority_service.h b/sql/wsrep_high_priority_service.h
new file mode 100644
index 00000000000..4012ca60a3e
--- /dev/null
+++ b/sql/wsrep_high_priority_service.h
@@ -0,0 +1,118 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_HIGH_PRIORITY_SERVICE_H
+#define WSREP_HIGH_PRIORITY_SERVICE_H
+
+#include "wsrep/high_priority_service.hpp"
+#include "wsrep/client_state.hpp"
+#include "my_global.h"
+#include "sql_error.h" /* Diagnostics area */
+#include "sql_class.h" /* rpl_group_info */
+
+class THD;
+class Relay_log_info;
+class Wsrep_server_service;
+
+class Wsrep_high_priority_service :
+ public wsrep::high_priority_service,
+ public wsrep::high_priority_context
+{
+public:
+ Wsrep_high_priority_service(THD*);
+ ~Wsrep_high_priority_service();
+ int start_transaction(const wsrep::ws_handle&,
+ const wsrep::ws_meta&);
+ const wsrep::transaction& transaction() const;
+ void adopt_transaction(const wsrep::transaction&);
+ int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&) = 0;
+ int append_fragment_and_commit(const wsrep::ws_handle&,
+ const wsrep::ws_meta&,
+ const wsrep::const_buffer&);
+ int remove_fragments(const wsrep::ws_meta&);
+ int commit(const wsrep::ws_handle&, const wsrep::ws_meta&);
+ int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&);
+ int apply_toi(const wsrep::ws_meta&, const wsrep::const_buffer&);
+ void store_globals();
+ void reset_globals();
+ void switch_execution_context(wsrep::high_priority_service&);
+ int log_dummy_write_set(const wsrep::ws_handle&,
+ const wsrep::ws_meta&);
+
+ virtual bool check_exit_status() const = 0;
+ void debug_crash(const char*);
+protected:
+ friend Wsrep_server_service;
+ THD* m_thd;
+ Relay_log_info* m_rli;
+ rpl_group_info* m_rgi;
+ struct shadow
+ {
+ ulonglong option_bits;
+ uint server_status;
+ struct st_vio* vio;
+ ulong tx_isolation;
+ char* db;
+ size_t db_length;
+ //struct timeval user_time;
+ my_hrtime_t user_time;
+ longlong row_count_func;
+ bool wsrep_applier;
+} m_shadow;
+};
+
+class Wsrep_applier_service : public Wsrep_high_priority_service
+{
+public:
+ Wsrep_applier_service(THD*);
+ ~Wsrep_applier_service();
+ int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&);
+ void after_apply();
+ bool is_replaying() const { return false; }
+ bool check_exit_status() const;
+};
+
+class Wsrep_replayer_service : public Wsrep_high_priority_service
+{
+public:
+ Wsrep_replayer_service(THD*);
+ ~Wsrep_replayer_service();
+ int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&);
+ void after_apply() { }
+ bool is_replaying() const { return true; }
+ void replay_status(enum wsrep::provider::status status)
+ { m_replay_status = status; }
+ enum wsrep::provider::status replay_status() const
+ { return m_replay_status; }
+ /* Replayer should never be forced to exit */
+ bool check_exit_status() const { return false; }
+private:
+ struct da_shadow
+ {
+ enum Diagnostics_area::enum_diagnostics_status status;
+ ulonglong affected_rows;
+ ulonglong last_insert_id;
+ char message[MYSQL_ERRMSG_SIZE];
+ da_shadow()
+ : status()
+ , affected_rows()
+ , last_insert_id()
+ , message()
+ { }
+ } m_da_shadow;
+ enum wsrep::provider::status m_replay_status;
+};
+
+#endif /* WSREP_HIGH_PRIORITY_SERVICE_H */
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index 8110faf7d11..a78020a891c 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -345,6 +345,7 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
}
+ DBUG_ENTER("wsrep_run_wsrep_commit");
DEBUG_SYNC(thd, "wsrep_before_replication");
if (thd->slave_thread && !opt_log_slave_updates) DBUG_RETURN(WSREP_TRX_OK);
diff --git a/sql/wsrep_mutex.h b/sql/wsrep_mutex.h
new file mode 100644
index 00000000000..03c9269119e
--- /dev/null
+++ b/sql/wsrep_mutex.h
@@ -0,0 +1,50 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_MUTEX_H
+#define WSREP_MUTEX_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/mutex.hpp"
+
+/* implementation */
+#include "my_pthread.h"
+
+class Wsrep_mutex : public wsrep::mutex
+{
+public:
+ Wsrep_mutex(mysql_mutex_t& mutex)
+ : m_mutex(mutex)
+ { }
+
+ void lock()
+ {
+ mysql_mutex_lock(&m_mutex);
+ }
+
+ void unlock()
+ {
+ mysql_mutex_unlock(&m_mutex);
+ }
+
+ void* native()
+ {
+ return &m_mutex;
+ }
+private:
+ mysql_mutex_t& m_mutex;
+};
+
+#endif /* WSREP_MUTEX_H */
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index d667d59b14f..c314fc65ce4 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -14,7 +14,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
+#include "my_global.h"
+#include "wsrep_server_state.h"
+
+#include "mariadb.h"
#include <mysqld.h>
+#include <transaction.h>
#include <sql_class.h>
#include <sql_parse.h>
#include <sql_base.h> /* find_temporary_table() */
@@ -33,19 +38,22 @@
#include "wsrep_var.h"
#include "wsrep_binlog.h"
#include "wsrep_applier.h"
+#include "wsrep_schema.h"
+#include "wsrep_thd_pool.h"
#include "wsrep_xid.h"
+#include "wsrep_trans_observer.h"
+#include "mysql/service_wsrep.h"
#include <cstdio>
#include <cstdlib>
+#include <string>
#include "log_event.h"
#include <slave.h>
-wsrep_t *wsrep = NULL;
-/*
- wsrep_emulate_bin_log is a flag to tell that binlog has not been configured.
- wsrep needs to get binlog events from transaction cache even when binlog is
- not enabled, wsrep_emulate_bin_log opens needed code paths to make this
- possible
-*/
+#include <sstream>
+
+/* 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 */
@@ -82,7 +90,7 @@ my_bool wsrep_certify_nonPK; // Certify, even when no primary
my_bool wsrep_recovery; // Recovery
my_bool wsrep_replicate_myisam; // Enable MyISAM replication
my_bool wsrep_log_conflicts;
-my_bool wsrep_load_data_splitting; // Commit load data every 10K intervals
+my_bool wsrep_load_data_splitting= 0; // Commit load data every 10K intervals
my_bool wsrep_slave_UK_checks; // Slave thread does UK checks
my_bool wsrep_slave_FK_checks; // Slave thread does FK checks
my_bool wsrep_restart_slave; // Should mysql slave thread be
@@ -107,7 +115,15 @@ my_bool wsrep_restart_slave_activated= 0; // Node has dropped, and slave
bool wsrep_new_cluster= false; // Bootstrap the cluster?
int wsrep_slave_count_change= 0; // No. of appliers to stop/start
int wsrep_to_isolation= 0; // No. of active TO isolation threads
-long wsrep_max_protocol_version= 3; // Maximum protocol version to use
+long wsrep_max_protocol_version= 4; // Maximum protocol version to use
+long int wsrep_protocol_version= wsrep_max_protocol_version;
+ulong wsrep_trx_fragment_size= 0; // size limit for fragmenting
+ // 0 = no fragmenting
+ulong wsrep_trx_fragment_unit= WSREP_FRAG_BYTES;
+ // unit for fragment size
+ulong wsrep_SR_store_type= WSREP_SR_STORE_TABLE;
+uint wsrep_ignore_apply_errors= 0;
+
/*
* End configuration options
@@ -123,29 +139,37 @@ mysql_mutex_t LOCK_wsrep_sst;
mysql_cond_t COND_wsrep_sst;
mysql_mutex_t LOCK_wsrep_sst_init;
mysql_cond_t COND_wsrep_sst_init;
-mysql_mutex_t LOCK_wsrep_rollback;
-mysql_cond_t COND_wsrep_rollback;
-wsrep_aborting_thd_t wsrep_aborting_thd= NULL;
mysql_mutex_t LOCK_wsrep_replaying;
mysql_cond_t COND_wsrep_replaying;
mysql_mutex_t LOCK_wsrep_slave_threads;
mysql_mutex_t LOCK_wsrep_desync;
mysql_mutex_t LOCK_wsrep_config_state;
+mysql_mutex_t LOCK_wsrep_SR_pool;
+mysql_mutex_t LOCK_wsrep_SR_store;
+mysql_mutex_t LOCK_wsrep_thd_pool; /* locking policy:
+ 1. LOCK_wsrep_slave_threads
+ 2. LOCK_wsrep_thd_pool
+ */
int wsrep_replaying= 0;
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
ulong my_bind_addr;
#ifdef HAVE_PSI_INTERFACE
-PSI_mutex_key key_LOCK_wsrep_rollback,
+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_config_state;
+ key_LOCK_wsrep_config_state,
+ key_LOCK_wsrep_SR_pool,
+ key_LOCK_wsrep_SR_store, key_LOCK_wsrep_thd_pool, key_LOCK_wsrep_nbo,
+ key_LOCK_wsrep_thd_queue;
-PSI_cond_key key_COND_wsrep_rollback,
+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_sst_init, key_COND_wsrep_sst_thread,
+ key_COND_wsrep_nbo, key_COND_wsrep_thd_queue;
+
PSI_file_key key_file_wsrep_gra_log;
@@ -156,11 +180,13 @@ static PSI_mutex_info wsrep_mutexes[]=
{ &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0},
{ &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
- { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", 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_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL},
- { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL}
+ { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_SR_pool, "LOCK_wsrep_SR_pool", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_SR_store, "LOCK_wsrep_SR_store", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_thd_pool, "LOCK_wsrep_thd_pool", PSI_FLAG_GLOBAL}
};
static PSI_cond_info wsrep_conds[]=
@@ -169,7 +195,7 @@ static PSI_cond_info wsrep_conds[]=
{ &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0},
- { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL},
+ { &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0},
{ &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL}
};
@@ -181,47 +207,48 @@ static PSI_file_info wsrep_files[]=
my_bool wsrep_inited = 0; // initialized ?
+static wsrep_uuid_t node_uuid= WSREP_UUID_UNDEFINED;
static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED;
static char cluster_uuid_str[40]= { 0, };
-static const char* cluster_status_str[WSREP_VIEW_MAX] =
-{
- "Primary",
- "non-Primary",
- "Disconnected"
-};
static char provider_name[256]= { 0, };
static char provider_version[256]= { 0, };
static char provider_vendor[256]= { 0, };
/*
- * wsrep status variables
+ * Wsrep status variables. LOCK_status must be locked When modifying
+ * these variables,
*/
my_bool wsrep_connected = FALSE;
-my_bool wsrep_ready = FALSE; // node can accept queries
+my_bool wsrep_ready = FALSE;
const char* wsrep_cluster_state_uuid = cluster_uuid_str;
long long wsrep_cluster_conf_id = WSREP_SEQNO_UNDEFINED;
-const char* wsrep_cluster_status = cluster_status_str[WSREP_VIEW_DISCONNECTED];
+const char* wsrep_cluster_status = "Disconnected";
long wsrep_cluster_size = 0;
long wsrep_local_index = -1;
long long wsrep_local_bf_aborts = 0;
const char* wsrep_provider_name = provider_name;
const char* wsrep_provider_version = provider_version;
const char* wsrep_provider_vendor = provider_vendor;
+char* wsrep_provider_capabilities = NULL;
+char* wsrep_cluster_capabilities = NULL;
/* End wsrep status variables */
-wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED;
-wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED;
-long wsrep_protocol_version = 3;
-
wsp::Config_state *wsrep_config_state;
-// Boolean denoting if server is in initial startup phase. This is needed
-// to make sure that main thread waiting in wsrep_sst_wait() is signaled
-// if there was no state gap on receiving first view event.
-static my_bool wsrep_startup = TRUE;
+
+wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED;
+wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED;
+wsp::node_status local_status;
+
+/*
+ */
+#define WSREP_THD_POOL_SIZE 16
+Wsrep_thd_pool* wsrep_thd_pool= 0;
+Wsrep_schema *wsrep_schema= 0;
+#if 0
static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) {
switch (level) {
case WSREP_LOG_INFO:
@@ -240,249 +267,163 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) {
break;
}
}
+#endif
-void wsrep_log(void (*fun)(const char *, ...), const char *format, ...)
-{
- va_list args;
- char msg[1024];
- va_start(args, format);
- vsnprintf(msg, sizeof(msg) - 1, format, args);
- va_end(args);
- (fun)("WSREP: %s", msg);
-}
-
-
-static void wsrep_log_states (wsrep_log_level_t const level,
- const wsrep_uuid_t* const group_uuid,
- wsrep_seqno_t const group_seqno,
- const wsrep_uuid_t* const node_uuid,
- wsrep_seqno_t const node_seqno)
-{
- char uuid_str[37];
- char msg[256];
-
- wsrep_uuid_print (group_uuid, uuid_str, sizeof(uuid_str));
- snprintf (msg, 255, "WSREP: Group state: %s:%lld",
- uuid_str, (long long)group_seqno);
- wsrep_log_cb (level, msg);
-
- wsrep_uuid_print (node_uuid, uuid_str, sizeof(uuid_str));
- snprintf (msg, 255, "WSREP: Local state: %s:%lld",
- uuid_str, (long long)node_seqno);
- wsrep_log_cb (level, msg);
-}
-
-#ifdef GTID_SUPPORT
-void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid)
+//#ifdef GTID_SUPPORT
+void wsrep_init_sidno(const wsrep::id& uuid)
{
- /* generate new Sid map entry from inverted uuid */
- rpl_sid sid;
- wsrep_uuid_t ltid_uuid;
-
- for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i)
+ /*
+ Protocol versions starting from 4 use group gtid as it is.
+ For lesser protocol versions generate new Sid map entry from inverted
+ uuid.
+ */
+ rpl_gtid sid;
+ if (wsrep_protocol_version >= 4)
{
- ltid_uuid.data[i] = ~wsrep_uuid.data[i];
+ memcpy((void*)&sid, (const uchar*)uuid.data(),16);
}
-
- sid.copy_from(ltid_uuid.data);
+ else
+ {
+ wsrep_uuid_t ltid_uuid;
+ for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i)
+ {
+ ltid_uuid.data[i] = ~((const uchar*)uuid.data())[i];
+ }
+ memcpy((void*)&sid, (const uchar*)ltid_uuid.data,16);
+ }
+#ifdef NOT_MERGED
global_sid_lock->wrlock();
wsrep_sidno= global_sid_map->add_sid(sid);
WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno);
global_sid_lock->unlock();
+#endif
}
-#endif /* GTID_SUPPORT */
+//#endif /* GTID_SUPPORT */
-static wsrep_cb_status_t
-wsrep_view_handler_cb (void* app_ctx,
- void* recv_ctx,
- const wsrep_view_info_t* view,
- const char* state,
- size_t state_len,
- void** sst_req,
- size_t* sst_req_len)
+void wsrep_init_schema()
{
- *sst_req = NULL;
- *sst_req_len = 0;
-
- wsrep_member_status_t memb_status= wsrep_config_state->get_status();
-
- if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t)))
- {
- memcpy(&cluster_uuid, &view->state_id.uuid, sizeof(cluster_uuid));
-
- wsrep_uuid_print (&cluster_uuid, cluster_uuid_str,
- sizeof(cluster_uuid_str));
- }
-
- wsrep_cluster_conf_id= view->view;
- wsrep_cluster_status= cluster_status_str[view->status];
- wsrep_cluster_size= view->memb_num;
- wsrep_local_index= view->my_idx;
-
- WSREP_INFO("New cluster view: global state: %s:%lld, view# %lld: %s, "
- "number of nodes: %ld, my index: %ld, protocol version %d",
- wsrep_cluster_state_uuid, (long long)view->state_id.seqno,
- (long long)wsrep_cluster_conf_id, wsrep_cluster_status,
- wsrep_cluster_size, wsrep_local_index, view->proto_ver);
-
- /* Proceed further only if view is PRIMARY */
- if (WSREP_VIEW_PRIMARY != view->status)
- {
-#ifdef HAVE_QUERY_CACHE
- // query cache must be initialised by now
- query_cache.flush();
-#endif /* HAVE_QUERY_CACHE */
-
- wsrep_ready_set(FALSE);
- memb_status= WSREP_MEMBER_UNDEFINED;
- /* Always record local_uuid and local_seqno in non-prim since this
- * may lead to re-initializing provider and start position is
- * determined according to these variables */
- // WRONG! local_uuid should be the last primary configuration uuid we were
- // a member of. local_seqno should be updated in commit calls.
- // local_uuid= cluster_uuid;
- // local_seqno= view->first - 1;
- goto out;
- }
+ DBUG_ASSERT(!wsrep_schema);
- switch (view->proto_ver)
+ WSREP_INFO("wsrep_init_schema_and_SR %p", wsrep_schema);
+ if (!wsrep_schema)
{
- case 0:
- case 1:
- case 2:
- case 3:
- // version change
- if (view->proto_ver != wsrep_protocol_version)
- {
- my_bool wsrep_ready_saved= wsrep_ready_get();
- wsrep_ready_set(FALSE);
- WSREP_INFO("closing client connections for "
- "protocol change %ld -> %d",
- wsrep_protocol_version, view->proto_ver);
- wsrep_close_client_connections(TRUE);
- wsrep_protocol_version= view->proto_ver;
- wsrep_ready_set(wsrep_ready_saved);
- }
- break;
- default:
- WSREP_ERROR("Unsupported application protocol version: %d",
- view->proto_ver);
+ // if (wsrep_before_SE()) {
+ DBUG_ASSERT(!wsrep_thd_pool);
+ wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE);
+ //}
+ wsrep_schema= new Wsrep_schema(wsrep_thd_pool);
+ if (wsrep_schema->init())
+ {
+ WSREP_ERROR("Failed to init wsrep schema");
unireg_abort(1);
+ }
}
+}
- if (view->state_gap)
+void wsrep_recover_sr_from_storage()
+{
+ switch (wsrep_SR_store_type)
{
- WSREP_WARN("Gap in state sequence. Need state transfer.");
-
- /* After that wsrep will call wsrep_sst_prepare. */
- /* keep ready flag 0 until we receive the snapshot */
- wsrep_ready_set(FALSE);
-
- /* Close client connections to ensure that they don't interfere
- * with SST. Necessary only if storage engines are initialized
- * before SST.
- * TODO: Just killing all ongoing transactions should be enough
- * since wsrep_ready is OFF and no new transactions can start.
- */
- if (!wsrep_before_SE())
- {
- WSREP_DEBUG("[debug]: closing client connections for PRIM");
- wsrep_close_client_connections(FALSE);
- }
-
- ssize_t const req_len= wsrep_sst_prepare (sst_req);
-
- if (req_len < 0)
- {
- WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len,
- strerror(-req_len));
- memb_status= WSREP_MEMBER_UNDEFINED;
- }
- else
+ case WSREP_SR_STORE_TABLE:
+ if (wsrep_schema->recover_sr_transactions())
{
- assert(sst_req != NULL);
- *sst_req_len= req_len;
- memb_status= WSREP_MEMBER_JOINER;
+ WSREP_ERROR("Failed to recover SR transactions from schema");
+ unireg_abort(1);
}
+ break;
+ default:
+ /* */
+ WSREP_ERROR("Unsupported wsrep SR store type: %lu", wsrep_SR_store_type);
+ unireg_abort(1);
+ break;
}
- else
- {
- /*
- * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized
- * before - OR - it was reinitilized on startup (lp:992840)
- */
- if (wsrep_startup)
+}
+
+/** Export the WSREP provider's capabilities as a human readable string.
+ * The result is saved in a dynamically allocated string of the form:
+ * :cap1:cap2:cap3:
+ */
+static void wsrep_capabilities_export(wsrep_cap_t const cap, char** str)
+{
+ static const char* names[] =
+ {
+ /* Keep in sync with wsrep/wsrep_api.h WSREP_CAP_* macros. */
+ "MULTI_MASTER",
+ "CERTIFICATION",
+ "PARALLEL_APPLYING",
+ "TRX_REPLAY",
+ "ISOLATION",
+ "PAUSE",
+ "CAUSAL_READS",
+ "CAUSAL_TRX",
+ "INCREMENTAL_WRITESET",
+ "SESSION_LOCKS",
+ "DISTRIBUTED_LOCKS",
+ "CONSISTENCY_CHECK",
+ "UNORDERED",
+ "ANNOTATION",
+ "PREORDERED",
+ "STREAMING",
+ "SNAPSHOT",
+ "NBO",
+ };
+
+ std::string s;
+ for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i)
+ {
+ if (cap & (1ULL << i))
{
- if (wsrep_before_SE())
- {
- wsrep_SE_init_grab();
- // Signal mysqld init thread to continue
- wsrep_sst_complete (&cluster_uuid, view->state_id.seqno, false);
- // and wait for SE initialization
- wsrep_SE_init_wait();
- }
- else
+ if (s.empty())
{
- local_uuid= cluster_uuid;
- local_seqno= view->state_id.seqno;
+ s = ":";
}
- /* Init storage engine XIDs from first view */
- wsrep_set_SE_checkpoint(local_uuid, local_seqno);
-#ifdef GTID_SUPPORT
- wsrep_init_sidno(local_uuid);
-#endif /* GTID_SUPPORT */
- memb_status= WSREP_MEMBER_JOINED;
- }
-
- // just some sanity check
- if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t)))
- {
- WSREP_ERROR("Undetected state gap. Can't continue.");
- wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno,
- &local_uuid, -1);
- unireg_abort(1);
+ s += names[i];
+ s += ":";
}
}
- if (wsrep_auto_increment_control)
- {
- global_system_variables.auto_increment_offset= view->my_idx + 1;
- global_system_variables.auto_increment_increment= view->memb_num;
- }
-
- { /* capabilities may be updated on new configuration */
- uint64_t const caps(wsrep->capabilities (wsrep));
+ /* A read from the string pointed to by *str may be started at any time,
+ * so it must never point to free(3)d memory or non '\0' terminated string. */
- my_bool const idc((caps & WSREP_CAP_INCREMENTAL_WRITESET) != 0);
- if (TRUE == wsrep_incremental_data_collection && FALSE == idc)
- {
- WSREP_WARN("Unsupported protocol downgrade: "
- "incremental data collection disabled. Expect abort.");
- }
- wsrep_incremental_data_collection = idc;
- }
+ char* const previous = *str;
-out:
- if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE;
- wsrep_config_state->set(memb_status, view);
+ *str = strdup(s.c_str());
- return WSREP_CB_SUCCESS;
+ if (previous != NULL)
+ {
+ free(previous);
+ }
}
-my_bool wsrep_ready_set (my_bool x)
+/* Verifies that SE position is consistent with the group position
+ * and initializes other variables */
+void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid,
+ wsrep_seqno_t const seqno)
{
- WSREP_DEBUG("Setting wsrep_ready to %d", x);
- if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- my_bool ret= (wsrep_ready != x);
- if (ret)
+#if 0
+ wsrep_get_SE_checkpoint(local_uuid, local_seqno);
+
+ if (memcmp(&local_uuid, &uuid, sizeof (wsrep_uuid_t)) ||
+ local_seqno > seqno)
{
- wsrep_ready= x;
- mysql_cond_signal (&COND_wsrep_ready);
+ WSREP_ERROR("Failed to update SE checkpoint. Can't continue.");
+ wsrep_log_states(WSREP_LOG_FATAL, &uuid, seqno,
+ &local_uuid, local_seqno);
+ assert(0);
+ unireg_abort(1);
}
- mysql_mutex_unlock (&LOCK_wsrep_ready);
- return ret;
+#endif
+ // wsrep_init_sidno(local_uuid);
}
+/*
+ Wsrep is considered ready if
+ 1) Provider is not loaded (native mode)
+ 2) Server has reached synced state
+ 3) Server is in joiner mode and mysqldump SST method has been
+ specified
+ See Wsrep_server_service::log_state_change() for further details.
+ */
my_bool wsrep_ready_get (void)
{
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
@@ -499,63 +440,20 @@ int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff)
return 0;
}
-// Wait until wsrep has reached ready state
-void wsrep_ready_wait ()
-{
- if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- while (!wsrep_ready)
- {
- WSREP_INFO("Waiting to reach ready state");
- mysql_cond_wait (&COND_wsrep_ready, &LOCK_wsrep_ready);
- }
- WSREP_INFO("ready state reached");
- mysql_mutex_unlock (&LOCK_wsrep_ready);
-}
-
-static void wsrep_synced_cb(void* app_ctx)
+void wsrep_update_cluster_state_uuid(const char* uuid)
{
- WSREP_INFO("Synchronized with group, ready for connections");
- my_bool signal_main= wsrep_ready_set(TRUE);
- wsrep_config_state->set(WSREP_MEMBER_SYNCED);
-
- if (signal_main)
- {
- wsrep_SE_init_grab();
- // Signal mysqld init thread to continue
- wsrep_sst_complete (&local_uuid, local_seqno, false);
- // and wait for SE initialization
- wsrep_SE_init_wait();
- }
- if (wsrep_restart_slave_activated)
- {
- int rcode;
- WSREP_INFO("MariaDB slave restart");
- wsrep_restart_slave_activated= FALSE;
-
- mysql_mutex_lock(&LOCK_active_mi);
- if ((rcode = start_slave_threads(0,
- 1 /* need mutex */,
- 0 /* no wait for start*/,
- active_mi,
- master_info_file,
- relay_log_info_file,
- SLAVE_SQL)))
- {
- WSREP_WARN("Failed to create slave threads: %d", rcode);
- }
- mysql_mutex_unlock(&LOCK_active_mi);
-
- }
+ strncpy(cluster_uuid_str, uuid, sizeof(cluster_uuid_str) - 1);
}
static void wsrep_init_position()
{
+#if 0
/* read XIDs from storage engines */
wsrep_uuid_t uuid;
wsrep_seqno_t seqno;
wsrep_get_SE_checkpoint(uuid, seqno);
- if (!memcmp(&uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)))
+ if (wsrep_uuid_compare(&uuid, &WSREP_UUID_UNDEFINED) == 0)
{
WSREP_INFO("Read nil XID from storage engines, skipping position init");
return;
@@ -563,9 +461,10 @@ static void wsrep_init_position()
char uuid_str[40] = {0, };
wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
- WSREP_INFO("Initial position: %s:%lld", uuid_str, (long long)seqno);
+ WSREP_INFO("Storage engines initial position: %s:%lld",
+ uuid_str, (long long)seqno);
- if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(local_uuid)) &&
+ if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 &&
local_seqno == WSREP_SEQNO_UNDEFINED)
{
// Initial state
@@ -578,99 +477,70 @@ static void wsrep_init_position()
WSREP_WARN("Initial position was provided by configuration or SST, "
"avoiding override");
}
+#endif
}
-extern char* my_bind_addr_str;
-
-int wsrep_init()
+/****************************************************************************
+ Helpers for wsrep_init()
+ ****************************************************************************/
+static std::string wsrep_server_name()
{
- int rcode= -1;
- DBUG_ASSERT(wsrep_inited == 0);
-
- if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) &&
- wsrep_start_position_init(wsrep_start_position))
- {
- return 1;
- }
-
- wsrep_sst_auth_init();
-
- wsrep_ready_set(FALSE);
- assert(wsrep_provider);
+ std::string ret(wsrep_node_name ? wsrep_node_name : "");
+ return ret;
+}
- wsrep_init_position();
+static std::string wsrep_server_id()
+{
+#ifdef WSREP_TODO
+ std::stringstream ss;
+ ss << server_id;
+ return(ss.str());
+#endif
+ /* using empty server_id, which enables view change handler to
+ set final server_id later on
+ */
+ std::string ret("");
+ return ret;
+}
- if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK)
- {
- if (strcasecmp(wsrep_provider, WSREP_NONE))
- {
- WSREP_ERROR("wsrep_load(%s) failed: %s (%d). Reverting to no provider.",
- wsrep_provider, strerror(rcode), rcode);
- strcpy((char*)wsrep_provider, WSREP_NONE); // damn it's a dirty hack
- return wsrep_init();
- }
- else /* this is for recursive call above */
- {
- WSREP_ERROR("Could not revert to no provider: %s (%d). Need to abort.",
- strerror(rcode), rcode);
- unireg_abort(1);
- }
- }
+static std::string wsrep_server_node_address()
+{
- if (!WSREP_PROVIDER_EXISTS)
+ std::string ret;
+ WSREP_INFO("node_address ptr %p", wsrep_node_address);
+ if (wsrep_node_address)
{
- // enable normal operation in case no provider is specified
- wsrep_ready_set(TRUE);
- wsrep_inited= 1;
- global_system_variables.wsrep_on = 0;
- wsrep_init_args args;
- args.logger_cb = wsrep_log_cb;
- args.options = (wsrep_provider_options) ?
- wsrep_provider_options : "";
- rcode = wsrep->init(wsrep, &args);
- if (rcode)
- {
- DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode));
- WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode);
- wsrep->free(wsrep);
- free(wsrep);
- wsrep = NULL;
- }
- return rcode;
+ WSREP_INFO("node_address %s", wsrep_node_address);
}
- else
+ if (!(wsrep_node_address && strlen(wsrep_node_address)))
{
- global_system_variables.wsrep_on = 1;
- strncpy(provider_name,
- wsrep->provider_name, sizeof(provider_name) - 1);
- strncpy(provider_version,
- wsrep->provider_version, sizeof(provider_version) - 1);
- strncpy(provider_vendor,
- wsrep->provider_vendor, sizeof(provider_vendor) - 1);
- }
-
- if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
- wsrep_data_home_dir = mysql_real_data_home;
+ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
+ wsrep_data_home_dir = mysql_real_data_home;
- /* Initialize node address */
- char node_addr[512]= { 0, };
- size_t const node_addr_max= sizeof(node_addr) - 1;
- if (!wsrep_node_address || !strcmp(wsrep_node_address, ""))
- {
- size_t const ret= wsrep_guess_ip(node_addr, node_addr_max);
- if (!(ret > 0 && ret < node_addr_max))
+ char node_addr[512] = {0, };
+ const size_t node_addr_max= sizeof(node_addr) - 1;
+ size_t guess_ip_ret= wsrep_guess_ip(node_addr, node_addr_max);
+ if (!(guess_ip_ret > 0 && guess_ip_ret < node_addr_max))
{
WSREP_WARN("Failed to guess base node address. Set it explicitly via "
"wsrep_node_address.");
- node_addr[0]= '\0';
+ }
+ else
+ {
+ ret = node_addr;
}
}
else
{
- strncpy(node_addr, wsrep_node_address, node_addr_max);
+ ret = wsrep_node_address;
}
+ return ret;
+}
- /* Initialize node's incoming address */
+static std::string wsrep_server_incoming_address()
+{
+ std::string ret;
+ const std::string node_addr(wsrep_server_node_address());
char inc_addr[512]= { 0, };
size_t const inc_addr_max= sizeof (inc_addr);
@@ -704,22 +574,28 @@ int wsrep_init()
}
else /* mysqld binds to 0.0.0.0, try taking IP from wsrep_node_address. */
{
- size_t const node_addr_len= strlen(node_addr);
- if (node_addr_len > 0)
+ if (node_addr.size())
{
- wsp::Address addr(node_addr);
-
- if (!addr.is_valid())
+ size_t const ip_len= wsrep_host_len(node_addr.c_str(), node_addr.size());
+ if (ip_len + 7 /* :55555\0 */ < inc_addr_max)
{
- WSREP_DEBUG("Could not parse node address : %s", node_addr);
- WSREP_WARN("Guessing address for incoming client connections failed. "
- "Try setting wsrep_node_incoming_address explicitly.");
- goto done;
+ memcpy (inc_addr, node_addr.c_str(), ip_len);
+ snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",
+ (int)mysqld_port);
}
+ else
+ {
+ WSREP_WARN("Guessing address for incoming client connections: "
+ "address too long.");
+ inc_addr[0]= '\0';
+ }
+ }
- const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u";
- snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(),
- (int) mysqld_port);
+ if (!strlen(inc_addr))
+ {
+ WSREP_WARN("Guessing address for incoming client connections failed. "
+ "Try setting wsrep_node_incoming_address explicitly.");
+ WSREP_INFO("Node addr: %s", node_addr.c_str());
}
}
}
@@ -743,46 +619,152 @@ int wsrep_init()
snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port);
}
+
+ done:
+ ret = wsrep_node_incoming_address;
+ return ret;
+}
+
+static std::string wsrep_server_working_dir()
+{
+ std::string ret;
+ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
+ {
+ ret = mysql_real_data_home;
+ }
+ else
+ {
+ ret = wsrep_data_home_dir;
+ }
+ return ret;
+}
+
+static wsrep::gtid wsrep_server_initial_position()
+{
+ wsrep::gtid ret;
+ WSREP_INFO("Server initial position: %s", wsrep_start_position);
+ std::istringstream is(wsrep_start_position);
+ is >> ret;
+ return ret;
+}
+
+int wsrep_init_server()
+{
+ try
+ {
+ const std::string server_name= wsrep_server_name();
+ const std::string server_id= wsrep_server_id();
+ const std::string node_address= wsrep_server_node_address();
+ const std::string incoming_address= wsrep_server_incoming_address();
+ const std::string working_dir= wsrep_server_working_dir();
+ const wsrep::gtid initial_position= wsrep_server_initial_position();
+
+ Wsrep_server_state::init_once(server_name,
+ server_id,
+ incoming_address,
+ node_address,
+ working_dir,
+ initial_position,
+ wsrep_max_protocol_version);
+ }
+ catch (const wsrep::runtime_error& e)
+ {
+ WSREP_ERROR("Failed to init wsrep server %s", e.what());
+ return 1;
+ }
+ catch (const std::exception& e)
+ {
+ WSREP_ERROR("Failed to init wsrep server %s", e.what());
+ }
+ return 0;
+}
+
+void wsrep_init_globals()
+{
+ wsrep_init_sidno(Wsrep_server_state::instance().connected_gtid().id());
+ wsrep_init_schema();
+ wsrep_recover_sr_from_storage();
+ if (WSREP_ON)
+ {
+ Wsrep_server_state::instance().initialized();
+ }
+}
-done:
- struct wsrep_init_args wsrep_args;
+void wsrep_deinit_server()
+{
+ Wsrep_server_state::destroy();
+}
- struct wsrep_gtid const state_id = { local_uuid, local_seqno };
+int wsrep_init()
+{
+ const std::string server_name= wsrep_server_name();
+ const std::string server_id= wsrep_server_id();
+ const std::string node_address= wsrep_server_node_address();
+ const std::string incoming_address= wsrep_server_incoming_address();
+ const std::string working_dir= wsrep_server_working_dir();
- wsrep_args.data_dir = wsrep_data_home_dir;
- wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : "";
- wsrep_args.node_address = node_addr;
- wsrep_args.node_incoming = inc_addr;
- wsrep_args.options = (wsrep_provider_options) ?
- wsrep_provider_options : "";
- wsrep_args.proto_ver = wsrep_max_protocol_version;
+ assert(wsrep_provider);
- wsrep_args.state_id = &state_id;
+ wsrep_init_position();
+ wsrep_sst_auth_init();
- wsrep_args.logger_cb = wsrep_log_cb;
- wsrep_args.view_handler_cb = wsrep_view_handler_cb;
- wsrep_args.apply_cb = wsrep_apply_cb;
- wsrep_args.commit_cb = wsrep_commit_cb;
- wsrep_args.unordered_cb = wsrep_unordered_cb;
- wsrep_args.sst_donate_cb = wsrep_sst_donate_cb;
- wsrep_args.synced_cb = wsrep_synced_cb;
+ if (strlen(wsrep_provider)== 0 ||
+ !strcmp(wsrep_provider, WSREP_NONE))
+ {
+ // enable normal operation in case no provider is specified
+ global_system_variables.wsrep_on = 0;
+ int err= Wsrep_server_state::instance().load_provider(wsrep_provider, wsrep_provider_options ? wsrep_provider_options : "");
+ if (err)
+ {
+ DBUG_PRINT("wsrep",("wsrep::init() failed: %d", err));
+ WSREP_ERROR("wsrep::init() failed: %d, must shutdown", err);
+ }
+ return err;
+ }
- rcode = wsrep->init(wsrep, &wsrep_args);
+ global_system_variables.wsrep_on = 1;
- if (rcode)
+ if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates)
{
- DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode));
- WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode);
- wsrep->free(wsrep);
- free(wsrep);
- wsrep = NULL;
- } else {
- wsrep_inited= 1;
+ WSREP_ERROR("Option --log-slave-updates is required if "
+ "binlog is enabled, GTID mode is on and wsrep provider "
+ "is specified");
+ return 1;
}
- return rcode;
-}
+ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
+ wsrep_data_home_dir = mysql_real_data_home;
+ if (Wsrep_server_state::instance().load_provider(wsrep_provider,
+ wsrep_provider_options))
+ {
+ WSREP_ERROR("Failed to load provider");
+ return 1;
+ }
+
+ if (!wsrep_provider_is_SR_capable() &&
+ global_system_variables.wsrep_trx_fragment_size > 0)
+ {
+ WSREP_ERROR("The WSREP provider (%s) does not support streaming "
+ "replication but wsrep_trx_fragment_size is set to a "
+ "value other than 0 (%lu). Cannot continue. Either set "
+ "wsrep_trx_fragment_size to 0 or use wsrep_provider that "
+ "supports streaming replication.",
+ wsrep_provider, global_system_variables.wsrep_trx_fragment_size);
+ Wsrep_server_state::instance().unload_provider();
+ return 1;
+ }
+ wsrep_inited= 1;
+
+ wsrep_capabilities_export(Wsrep_server_state::instance().provider().capabilities(),
+ &wsrep_provider_capabilities);
+
+ WSREP_DEBUG("SR storage init for: %s",
+ (wsrep_SR_store_type == WSREP_SR_STORE_TABLE) ? "table" :
+ (wsrep_SR_store_type == WSREP_SR_STORE_FILE) ? "file" : "void");
+
+ return 0;
+}
/* Initialize wsrep thread LOCKs and CONDs */
void wsrep_thr_init()
@@ -801,25 +783,28 @@ void wsrep_thr_init()
mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst, NULL);
mysql_mutex_init(key_LOCK_wsrep_sst_init, &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init, NULL);
- mysql_mutex_init(key_LOCK_wsrep_rollback, &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST);
- mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback, NULL);
mysql_mutex_init(key_LOCK_wsrep_replaying, &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST);
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_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);
+ mysql_mutex_init(key_LOCK_wsrep_SR_pool,
+ &LOCK_wsrep_SR_pool, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_wsrep_SR_store,
+ &LOCK_wsrep_SR_store, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_wsrep_thd_pool,
+ &LOCK_wsrep_thd_pool, MY_MUTEX_INIT_FAST);
DBUG_VOID_RETURN;
}
-void wsrep_init_startup (bool first)
+extern int wsrep_on(void *);
+
+void wsrep_init_startup (bool sst_first)
{
if (wsrep_init()) unireg_abort(1);
- wsrep_thr_lock_init(
- (wsrep_thd_is_brute_force_fun)wsrep_thd_is_BF,
- (wsrep_abort_thd_fun)wsrep_abort_thd,
- wsrep_debug, wsrep_convert_LOCK_to_trx,
- (wsrep_on_fun)wsrep_on);
+ wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_thd_bf_abort,
+ wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
/*
Pre-initialize global_system_variables.table_plugin with a dummy engine
@@ -838,31 +823,56 @@ void wsrep_init_startup (bool first)
/* Skip replication start if no cluster address */
if (!wsrep_cluster_address || wsrep_cluster_address[0] == 0) return;
- if (first) wsrep_sst_grab(); // do it so we can wait for SST below
-
+ /*
+ Read value of wsrep_new_cluster before wsrep_start_replication(),
+ the value is reset to FALSE inside wsrep_start_replication.
+ */
if (!wsrep_start_replication()) unireg_abort(1);
wsrep_create_rollbacker();
wsrep_create_appliers(1);
- if (first && !wsrep_sst_wait()) unireg_abort(1);// wait until SST is completed
+ Wsrep_server_state& server_state= Wsrep_server_state::instance();
+ /*
+ If the SST happens before server initialization, wait until the server
+ state reaches initializing. This indicates that
+ either SST was not necessary or SST has been delivered.
+
+ With mysqldump SST (!sst_first) wait until the server reaches
+ joiner state and procedd to accepting connections.
+ */
+ if (sst_first)
+ {
+ server_state.wait_until_state(Wsrep_server_state::s_initializing);
+ }
+ else
+ {
+ server_state.wait_until_state(Wsrep_server_state::s_joiner);
+ }
}
-void wsrep_deinit(bool free_options)
+void wsrep_deinit()
{
DBUG_ASSERT(wsrep_inited == 1);
- wsrep_unload(wsrep);
- wsrep= 0;
+ delete wsrep_schema;
+ wsrep_schema= 0;
+ WSREP_DEBUG("wsrep_deinit");
+ delete wsrep_thd_pool;
+ wsrep_thd_pool= 0;
+
+ Wsrep_server_state::instance().unload_provider();
provider_name[0]= '\0';
provider_version[0]= '\0';
provider_vendor[0]= '\0';
wsrep_inited= 0;
- if (free_options)
+ if (wsrep_provider_capabilities != NULL)
{
- wsrep_sst_auth_free();
+ char* p = wsrep_provider_capabilities;
+ wsrep_provider_capabilities = NULL;
+ free(p);
}
}
@@ -871,28 +881,38 @@ void wsrep_thr_deinit()
{
if (!wsrep_config_state)
return; // Never initialized
+ WSREP_DEBUG("wsrep_thr_deinit");
mysql_mutex_destroy(&LOCK_wsrep_ready);
mysql_cond_destroy(&COND_wsrep_ready);
mysql_mutex_destroy(&LOCK_wsrep_sst);
mysql_cond_destroy(&COND_wsrep_sst);
mysql_mutex_destroy(&LOCK_wsrep_sst_init);
mysql_cond_destroy(&COND_wsrep_sst_init);
- mysql_mutex_destroy(&LOCK_wsrep_rollback);
- mysql_cond_destroy(&COND_wsrep_rollback);
mysql_mutex_destroy(&LOCK_wsrep_replaying);
mysql_cond_destroy(&COND_wsrep_replaying);
mysql_mutex_destroy(&LOCK_wsrep_slave_threads);
mysql_mutex_destroy(&LOCK_wsrep_desync);
mysql_mutex_destroy(&LOCK_wsrep_config_state);
+ mysql_mutex_destroy(&LOCK_wsrep_SR_pool);
+ mysql_mutex_destroy(&LOCK_wsrep_SR_store);
+ mysql_mutex_destroy(&LOCK_wsrep_thd_pool);
+
delete wsrep_config_state;
wsrep_config_state= 0; // Safety
+
+ if (wsrep_cluster_capabilities != NULL)
+ {
+ char* p = wsrep_cluster_capabilities;
+ wsrep_cluster_capabilities = NULL;
+ free(p);
+ }
}
void wsrep_recover()
{
char uuid_str[40];
- if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) &&
+ if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 &&
local_seqno == -2)
{
wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str));
@@ -900,43 +920,72 @@ void wsrep_recover()
uuid_str, (long long)local_seqno);
return;
}
- wsrep_uuid_t uuid;
- wsrep_seqno_t seqno;
- wsrep_get_SE_checkpoint(uuid, seqno);
- wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
- WSREP_INFO("Recovered position: %s:%lld", uuid_str, (long long)seqno);
+ wsrep::gtid gtid= wsrep_get_SE_checkpoint();
+ std::ostringstream oss;
+ oss << gtid;
+ WSREP_INFO("Recovered position: %s", oss.str().c_str());
}
void wsrep_stop_replication(THD *thd)
{
WSREP_INFO("Stop replication");
- if (!wsrep)
+ if (Wsrep_server_state::instance().state() !=
+ Wsrep_server_state::s_disconnected)
+ {
+ WSREP_DEBUG("Provider disconnect");
+ Wsrep_server_state::instance().disconnect();
+ Wsrep_server_state::instance().wait_until_state(Wsrep_server_state::s_disconnected);
+ }
+
+ /* my connection, should not terminate with wsrep_close_client_connection(),
+ make transaction to rollback
+ */
+ if (thd && !thd->wsrep_applier) trans_rollback(thd);
+ wsrep_close_client_connections(TRUE, thd);
+
+ /* wait until appliers have stopped */
+ wsrep_wait_appliers_close(thd);
+
+ node_uuid= WSREP_UUID_UNDEFINED;
+
+ delete wsrep_schema;
+ wsrep_schema= 0;
+
+ return;
+}
+
+void wsrep_shutdown_replication()
+{
+ WSREP_INFO("Shutdown replication");
+ if (Wsrep_server_state::instance().state() == wsrep::server_state::s_disconnected)
{
- WSREP_INFO("Provider was not loaded, in stop replication");
+ WSREP_INFO("Provider was not loaded, in shutdown replication");
return;
}
- /* disconnect from group first to get wsrep_ready == FALSE */
WSREP_DEBUG("Provider disconnect");
- wsrep->disconnect(wsrep);
-
- wsrep_connected= FALSE;
+ Wsrep_server_state::instance().disconnect();
wsrep_close_client_connections(TRUE);
+ // wsrep_close_SR_transactions(NULL);
/* wait until appliers have stopped */
- wsrep_wait_appliers_close(thd);
+ wsrep_wait_appliers_close(NULL);
+ node_uuid= WSREP_UUID_UNDEFINED;
- return;
+ if (current_thd)
+ {
+ /* Undocking the thread specific data. */
+ my_pthread_setspecific_ptr(THR_THD, NULL);
+ //my_pthread_setspecific_ptr(THR_MALLOC, NULL);
+ }
}
bool wsrep_start_replication()
{
- wsrep_status_t rcode;
-
- /* wsrep provider must be loaded. */
- DBUG_ASSERT(wsrep);
+ int rcode;
+ WSREP_DEBUG("wsrep_start_replication");
/*
if provider is trivial, don't even try to connect,
@@ -945,34 +994,27 @@ bool wsrep_start_replication()
if (!WSREP_PROVIDER_EXISTS)
{
// enable normal operation in case no provider is specified
- wsrep_ready_set(TRUE);
return true;
}
if (!wsrep_cluster_address || wsrep_cluster_address[0]== 0)
{
// if provider is non-trivial, but no address is specified, wait for address
- wsrep_ready_set(FALSE);
return true;
}
- bool const bootstrap= wsrep_new_cluster;
+ bool const bootstrap(TRUE == wsrep_new_cluster);
+ wsrep_new_cluster= FALSE;
WSREP_INFO("Start replication");
- if (wsrep_new_cluster)
+ if ((rcode= Wsrep_server_state::instance().connect(
+ wsrep_cluster_name,
+ wsrep_cluster_address,
+ wsrep_sst_donor,
+ bootstrap)))
{
- WSREP_INFO("'wsrep-new-cluster' option used, bootstrapping the cluster");
- wsrep_new_cluster= false;
- }
-
- if ((rcode = wsrep->connect(wsrep,
- wsrep_cluster_name,
- wsrep_cluster_address,
- wsrep_sst_donor,
- bootstrap)))
- {
- DBUG_PRINT("wsrep",("wsrep->connect(%s) failed: %d",
+ DBUG_PRINT("wsrep",("wsrep_ptr->connect(%s) failed: %d",
wsrep_cluster_address, rcode));
WSREP_ERROR("wsrep::connect(%s) failed: %d",
wsrep_cluster_address, rcode);
@@ -980,15 +1022,12 @@ bool wsrep_start_replication()
}
else
{
- wsrep_connected= TRUE;
-
- char* opts= wsrep->options_get(wsrep);
- if (opts)
+ try
{
- wsrep_provider_options_init(opts);
- free(opts);
+ std::string opts= Wsrep_server_state::instance().provider().options();
+ wsrep_provider_options_init(opts.c_str());
}
- else
+ catch (const wsrep::runtime_error&)
{
WSREP_WARN("Failed to get wsrep options");
}
@@ -999,13 +1038,19 @@ bool wsrep_start_replication()
bool wsrep_must_sync_wait (THD* thd, uint mask)
{
- return (thd->variables.wsrep_sync_wait & mask) &&
+ bool ret;
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ ret= (thd->variables.wsrep_sync_wait & mask) &&
thd->variables.wsrep_on &&
!(thd->variables.wsrep_dirty_reads &&
!is_update_query(thd->lex->sql_command)) &&
!thd->in_active_multi_stmt_transaction() &&
- thd->wsrep_conflict_state != REPLAYING &&
- thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
+ thd->wsrep_trx().state() !=
+ wsrep::transaction::s_replaying &&
+ thd->wsrep_cs().sync_wait_gtid().is_undefined();
+ // thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ return ret;
}
bool wsrep_sync_wait (THD* thd, uint mask)
@@ -1016,9 +1061,8 @@ bool wsrep_sync_wait (THD* thd, uint mask)
thd->variables.wsrep_sync_wait, mask);
// This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0
// TODO: modify to check if thd has locked any rows.
- wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid);
-
- if (unlikely(WSREP_OK != ret))
+ // enum wsrep::provider::status ret = wsrep_sync_wait_upto(thd, NULL, -1);
+ if (thd->wsrep_cs().sync_wait(-1))
{
const char* msg;
int err;
@@ -1028,11 +1072,11 @@ bool wsrep_sync_wait (THD* thd, uint mask)
// ER_FUNCTION_NOT_DEFINED, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET,
// ER_FEATURE_DISABLED, ER_QUERY_INTERRUPTED
- switch (ret)
+ switch (thd->wsrep_cs().current_error())
{
- case WSREP_NOT_IMPLEMENTED:
+ case wsrep::e_not_supported_error:
msg= "synchronous reads by wsrep backend. "
- "Please unset wsrep_causal_reads variable.";
+ "Please unset wsrep_causal_reads variable.";
err= ER_NOT_SUPPORTED_YET;
break;
default:
@@ -1050,6 +1094,27 @@ bool wsrep_sync_wait (THD* thd, uint mask)
return false;
}
+enum wsrep::provider::status
+wsrep_sync_wait_upto (THD* thd,
+ wsrep_gtid_t* upto,
+ int timeout)
+{
+ DBUG_ASSERT(upto);
+ enum wsrep::provider::status ret;
+ if (upto)
+ {
+ wsrep::gtid upto_gtid(wsrep::id(upto->uuid.data, sizeof(upto->uuid.data)),
+ wsrep::seqno(upto->seqno));
+ ret= Wsrep_server_state::instance().wait_for_gtid(upto_gtid, timeout);
+ }
+ else
+ {
+ ret= Wsrep_server_state::instance().causal_read(timeout).second;
+ }
+ WSREP_DEBUG("wsrep_sync_wait_upto: %d", ret);
+ return ret;
+}
+
void wsrep_keys_free(wsrep_key_arr_t* key_arr)
{
for (size_t i= 0; i < key_arr->keys_len; ++i)
@@ -1073,9 +1138,9 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
*/
static bool wsrep_prepare_key_for_isolation(const char* db,
- const char* table,
- wsrep_buf_t* key,
- size_t* key_len)
+ const char* table,
+ wsrep_buf_t* key,
+ size_t* key_len)
{
if (*key_len < 2) return false;
@@ -1087,6 +1152,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
case 1:
case 2:
case 3:
+ case 4:
{
*key_len= 0;
if (db)
@@ -1105,6 +1171,9 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
break;
}
default:
+ assert(0);
+ WSREP_ERROR("Unsupported protocol version: %ld", wsrep_protocol_version);
+ unireg_abort(1);
return false;
}
return true;
@@ -1124,7 +1193,6 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
tmp= (wsrep_key_t*)my_realloc(ka->keys,
(ka->keys_len + 1) * sizeof(wsrep_key_t),
MYF(0));
-
if (!tmp)
{
WSREP_ERROR("Can't allocate memory for key_array");
@@ -1224,7 +1292,6 @@ bool wsrep_prepare_keys_for_isolation(THD* thd,
return wsrep_prepare_keys_for_isolation(thd, db, table, table_list, NULL, ka);
}
-
bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
const uchar* row_id, size_t row_id_len,
wsrep_buf_t* key, size_t* key_len)
@@ -1245,6 +1312,7 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
case 1:
case 2:
case 3:
+ case 4:
{
key[0].ptr = cache_key;
key[0].len = strlen( (char*)cache_key );
@@ -1266,7 +1334,79 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
return true;
}
+bool wsrep_prepare_key_for_innodb(THD* thd,
+ const uchar* cache_key,
+ size_t cache_key_len,
+ const uchar* row_id,
+ size_t row_id_len,
+ wsrep_buf_t* key,
+ size_t* key_len)
+{
+
+ return wsrep_prepare_key(cache_key, cache_key_len, row_id, row_id_len, key, key_len);
+}
+
+wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
+ enum wsrep::key::type type)
+{
+ wsrep::key ret(type);
+ DBUG_ASSERT(db);
+ ret.append_key_part(db, strlen(db));
+ if (table) ret.append_key_part(table, strlen(table));
+ return ret;
+}
+
+wsrep::key_array
+wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
+ Alter_info* alter_info)
+
+{
+ wsrep::key_array ret;
+ Key *key;
+ List_iterator<Key> key_iterator(alter_info->key_list);
+ while ((key= key_iterator++))
+ {
+ if (key->type == Key::FOREIGN_KEY)
+ {
+ Foreign_key *fk_key= (Foreign_key *)key;
+ const char *db_name= fk_key->ref_db.str;
+ const char *table_name= fk_key->ref_table.str;
+ if (!db_name)
+ {
+ db_name= child_table_db;
+ }
+ ret.push_back(wsrep_prepare_key_for_toi(db_name, table_name,
+ wsrep::key::exclusive));
+ }
+ }
+ return ret;
+}
+wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info)
+{
+ wsrep::key_array ret;
+ if (db || table)
+ {
+ ret.push_back(wsrep_prepare_key_for_toi(db, table, wsrep::key::exclusive));
+ }
+ for (const TABLE_LIST* table= table_list; table; table= table->next_global)
+ {
+ ret.push_back(wsrep_prepare_key_for_toi(table->db.str, table->table_name.str,
+ wsrep::key::exclusive));
+ }
+ if (alter_info && (alter_info->flags & ALTER_ADD_FOREIGN_KEY))
+ {
+ wsrep::key_array fk(wsrep_prepare_keys_for_alter_add_fk(table_list->db.str, alter_info));
+ if (!fk.empty())
+ {
+ ret.insert(ret.end(), fk.begin(), fk.end());
+ }
+ }
+ return ret;
+}
/*
* Construct Query_log_Event from thd query and serialize it
* into buffer.
@@ -1277,7 +1417,7 @@ int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len)
{
IO_CACHE tmp_io_cache;
- Log_event_writer writer(&tmp_io_cache,0);
+ Log_event_writer writer(&tmp_io_cache, 0);
if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX,
65536, MYF(MY_WME)))
return 1;
@@ -1496,9 +1636,14 @@ static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len)
/* Forward declarations. */
-static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
-static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+/*
+ Rewrite DROP TABLE for TOI. Temporary tables are eliminated from
+ the query as they are visible only to client connection.
+ TODO: See comments for sql_base.cc:drop_temporary_table() and refine
+ the function to deal with transactional locked tables.
+ */
/*
Decide if statement should run in TOI.
@@ -1596,249 +1741,427 @@ static const char* wsrep_get_query_or_msg(const THD* thd)
}
}
-/*
- returns:
- 0: statement was replicated as TOI
- 1: TOI replication was skipped
- -1: TOI replication failed
- */
-static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
- const TABLE_LIST* table_list,
- Alter_info* alter_info)
+static bool wsrep_can_run_in_nbo(THD *thd)
{
- wsrep_status_t ret(WSREP_WARNING);
- uchar* buf(0);
- size_t buf_len(0);
- int buf_err;
- int rc= 0;
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_ALTER_TABLE:
+ /*
+ CREATE INDEX and DROP INDEX are mapped to ALTER TABLE internally
+ */
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_DROP_INDEX:
+ switch (thd->lex->alter_info.requested_lock)
+ {
+ case Alter_info::ALTER_TABLE_LOCK_SHARED:
+ case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE:
+ return true;
+ default:
+ return false;
+ }
+ case SQLCOM_OPTIMIZE:
+ return true;
+ default:
+ break; /* Keep compiler happy */
+ }
+ return false;
+}
+
+static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
+{
+ String log_query;
+ sp_head *sp = thd->lex->sphead;
+ sql_mode_t saved_mode= thd->variables.sql_mode;
+ String retstr(64);
+ LEX_CSTRING returns= empty_clex_str;
+ retstr.set_charset(system_charset_info);
+
+ log_query.set_charset(system_charset_info);
- if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false)
+ if (sp->m_handler->type() == TYPE_ENUM_FUNCTION)
{
- WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd));
+ sp_returns_type(thd, retstr, sp);
+ returns= retstr.lex_cstring();
+ }
+ if (sp->m_handler->
+ show_create_sp(thd, &log_query,
+ sp->m_explicit_name ? sp->m_db : null_clex_str,
+ sp->m_name, sp->m_params, returns,
+ sp->m_body, sp->chistics(),
+ thd->lex->definer[0],
+ thd->lex->create_info,
+ saved_mode))
+ {
+ WSREP_WARN("SP create string failed: schema: %s, query: %s",
+ thd->get_db(), thd->query());
return 1;
}
- WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd));
+ return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len);
+}
+static int wsrep_TOI_event_buf(THD* thd, uchar** buf, size_t* buf_len)
+{
+ int err;
switch (thd->lex->sql_command)
{
case SQLCOM_CREATE_VIEW:
- buf_err= create_view_query(thd, &buf, &buf_len);
+ err= create_view_query(thd, buf, buf_len);
break;
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
- buf_err= wsrep_create_sp(thd, &buf, &buf_len);
+ err= wsrep_create_sp(thd, buf, buf_len);
break;
case SQLCOM_CREATE_TRIGGER:
- buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len);
+ err= wsrep_create_trigger_query(thd, buf, buf_len);
break;
case SQLCOM_CREATE_EVENT:
- buf_err= wsrep_create_event_query(thd, &buf, &buf_len);
+ err= wsrep_create_event_query(thd, buf, buf_len);
break;
case SQLCOM_ALTER_EVENT:
- buf_err= wsrep_alter_event_query(thd, &buf, &buf_len);
+ err= wsrep_alter_event_query(thd, buf, buf_len);
break;
case SQLCOM_DROP_TABLE:
- buf_err= wsrep_drop_table_query(thd, &buf, &buf_len);
+ err= wsrep_drop_table_query(thd, buf, buf_len);
break;
- case SQLCOM_CREATE_ROLE:
- if (sp_process_definer(thd))
- {
- WSREP_WARN("Failed to set CREATE ROLE definer for TOI.");
- }
- /* fallthrough */
default:
- buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(),
- &buf, &buf_len);
+ err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), buf,
+ buf_len);
break;
}
- wsrep_key_arr_t key_arr= {0, 0};
- struct wsrep_buf buff = { buf, buf_len };
- if (!buf_err &&
- !wsrep_prepare_keys_for_isolation(thd, db_, table_,
- table_list, alter_info, &key_arr) &&
- key_arr.keys_len > 0 &&
- WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id,
- key_arr.keys, key_arr.keys_len,
- &buff, 1,
- &thd->wsrep_trx_meta)))
- {
- thd->wsrep_exec_mode= TOTAL_ORDER;
- wsrep_to_isolation++;
- wsrep_keys_free(&key_arr);
- WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode);
- }
- else if (key_arr.keys_len > 0) {
- /* jump to error handler in mysql_execute_command() */
- WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. Check wsrep "
- "connection state and retry the query.",
- ret,
- thd->get_db(),
- (thd->query()) ? thd->query() : "void");
- my_message(ER_LOCK_DEADLOCK, "WSREP replication failed. Check "
- "your wsrep connection state and retry the query.", MYF(0));
- wsrep_keys_free(&key_arr);
- rc= -1;
- }
- else {
- /* non replicated DDL, affecting temporary tables only */
- WSREP_DEBUG("TO isolation skipped for: %d, sql: %s."
- "Only temporary tables affected.",
- ret, (thd->query()) ? thd->query() : "void");
- rc= 1;
- }
- if (buf) my_free(buf);
- return rc;
+ return err;
}
-static void wsrep_TOI_end(THD *thd) {
- wsrep_status_t ret;
- wsrep_to_isolation--;
-
- WSREP_DEBUG("TO END: %lld, %d: %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd));
-
- wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
- thd->wsrep_trx_meta.gtid.seqno);
- WSREP_DEBUG("TO END: %lld, update seqno",
- (long long)wsrep_thd_trx_seqno(thd));
-
- if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) {
- WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd));
- }
- else {
- WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
- ret,
- thd->get_db(),
- (thd->query()) ? thd->query() : "void");
+static void wsrep_TOI_begin_failed(THD* thd, const wsrep_buf_t* /* const err */)
+{
+ if (wsrep_thd_trx_seqno(thd) > 0)
+ {
+ /* GTID was granted and TO acquired - need to log event and release TO */
+ if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd);
+ if (wsrep_write_dummy_event(thd, "TOI begin failed")) { goto fail; }
+#if 0
+ /* todo */
+ wsrep_xid_init(&thd->wsrep_xid,
+ thd->wsrep_trx_meta.gtid.uuid,
+ thd->wsrep_trx_meta.gtid.seqno);
+ if (tc_log) tc_log->commit(thd, true);
+#endif /* 0 */
+ wsrep::client_state& cs(thd->wsrep_cs());
+ int const ret= cs.leave_toi();
+ if (ret)
+ {
+ WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %lld, "
+ "schema: %s, SQL: %s, rcode: %d wsrep_error: %s",
+ (long long)thd->real_id, thd->db.str,
+ thd->query(), ret, wsrep::to_c_string(cs.current_error()));
+ goto fail;
+ }
}
+ return;
+fail:
+ WSREP_ERROR("Failed to release TOI resources. Need to abort.");
+ unireg_abort(1);
}
-static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
+
+/*
+ returns:
+ 0: statement was replicated as TOI
+ 1: TOI replication was skipped
+ -1: TOI replication failed
+ -2: NBO begin failed
+ */
+static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info)
{
- wsrep_status_t ret(WSREP_WARNING);
- WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, thd->query() );
+ /* FIXME: NBO is broken in this codepath */
+ DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
+ DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI ||
+ thd->variables.wsrep_OSU_method == WSREP_OSU_NBO);
- ret = wsrep->desync(wsrep);
- if (ret != WSREP_OK)
+ WSREP_DEBUG("TOI Begin");
+ if (wsrep_can_run_in_toi(thd, db, table, table_list) == false)
{
- WSREP_WARN("RSU desync failed %d for schema: %s, query: %s",
- ret, thd->get_db(), thd->query());
- my_error(ER_LOCK_DEADLOCK, MYF(0));
- return(ret);
+ WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd));
+ return 1;
}
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- wsrep_replaying++;
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
-
- if (wsrep_wait_committing_connections_close(5000))
+ if (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO &&
+ Wsrep_server_state::has_capability(wsrep::provider::capability::nbo))
{
- /* no can do, bail out from DDL */
- WSREP_WARN("RSU failed due to pending transactions, schema: %s, query %s",
- thd->get_db(), thd->query());
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- wsrep_replaying--;
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
-
- ret = wsrep->resync(wsrep);
- if (ret != WSREP_OK)
- {
- WSREP_WARN("resync failed %d for schema: %s, query: %s",
- ret, thd->get_db(), thd->query());
- }
-
- my_error(ER_LOCK_DEADLOCK, MYF(0));
- return(1);
+ const char* const msg=
+ "wsrep_OSU_method NBO is not supported by wsrep provider";
+ WSREP_DEBUG("%s", msg);
+ my_message(ER_NOT_SUPPORTED_YET, msg, MYF(0));
+ return -1;
}
- wsrep_seqno_t seqno = wsrep->pause(wsrep);
- if (seqno == WSREP_SEQNO_UNDEFINED)
+ bool can_run_in_nbo(wsrep_can_run_in_nbo(thd));
+ if (can_run_in_nbo == false &&
+ thd->variables.wsrep_OSU_method == WSREP_OSU_NBO)
{
- WSREP_WARN("pause failed %lld for schema: %s, query: %s", (long long)seqno,
- thd->get_db(), thd->query());
- return(1);
+ WSREP_DEBUG("wsrep_OSU_method NBO not supported for %s",
+ WSREP_QUERY(thd));
+ my_message(ER_NOT_SUPPORTED_YET,
+ "wsrep_OSU_method NBO not supported for query",
+ MYF(0));
+ return -1;
}
- WSREP_DEBUG("paused at %lld", (long long)seqno);
- thd->variables.wsrep_on = 0;
- return 0;
-}
-static void wsrep_RSU_end(THD *thd)
-{
- wsrep_status_t ret(WSREP_WARNING);
- WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, thd->query() );
+ bool run_in_nbo= (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO &&
+ can_run_in_nbo);
+ // uint32_t flags= (run_in_nbo ? WSREP_FLAG_TRX_START :
+ // WSREP_FLAG_TRX_START | WSREP_FLAG_TRX_END);
+ uchar* buf= 0;
+ size_t buf_len(0);
+ int buf_err;
+ int rc;
+ time_t wait_start;
+
+ buf_err= wsrep_TOI_event_buf(thd, &buf, &buf_len);
+ if (buf_err) {
+ WSREP_ERROR("Failed to create TOI event buf: %d", buf_err);
+ my_message(ER_UNKNOWN_ERROR,
+ "WSREP replication failed to prepare TOI event buffer. "
+ "Check your query.",
+ MYF(0));
+ return -1;
+ }
+ struct wsrep_buf buff= { buf, buf_len };
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- wsrep_replaying--;
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ wsrep::key_array key_array=
+ wsrep_prepare_keys_for_toi(db, table, table_list, alter_info);
- ret = wsrep->resume(wsrep);
- if (ret != WSREP_OK)
+ /* wsrep_can_run_in_toi() should take care of checking that
+ DDLs with only temp tables should not be TOId at all */
+ if (key_array.size() == 0)
{
- WSREP_WARN("resume failed %d for schema: %s, query: %s", ret,
- thd->get_db(), thd->query());
+ /* non replicated DDL, affecting temporary tables only */
+ WSREP_DEBUG("TO isolation skipped, sql: %s."
+ "Only temporary tables affected.",
+ WSREP_QUERY(thd));
+ if (buf) my_free(buf);
+ return -1;
}
- ret = wsrep->resync(wsrep);
- if (ret != WSREP_OK)
+ thd_proc_info(thd, "acquiring total order isolation");
+ wait_start= time(NULL);
+ wsrep::client_state& cs(thd->wsrep_cs());
+ int ret;
+ do
{
- WSREP_WARN("resync failed %d for schema: %s, query: %s", ret,
- thd->get_db(), thd->query());
- return;
- }
+ ret= cs.enter_toi(key_array,
+ wsrep::const_buffer(buff.ptr, buff.len),
+ wsrep::provider::flag::start_transaction |
+ wsrep::provider::flag::commit);
+ if (thd->killed != NOT_KILLED) break;
- thd->variables.wsrep_on = 1;
-}
+ if (ret)
+ {
+ DBUG_ASSERT(cs.current_error());
+ WSREP_DEBUG("to_execute_start() failed for %llu: %s, NBO: %s, seqno: %lld",
+ thd->thread_id, WSREP_QUERY(thd), run_in_nbo ? "yes" : "no",
+ (long long)wsrep_thd_trx_seqno(thd));
+ if (ulong(time(NULL) - wait_start) < thd->variables.lock_wait_timeout)
+ {
+ usleep(100000);
+ }
+ else
+ {
+ my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
+ break;
+ }
+ if (run_in_nbo) /* will loop */
+ {
+ wsrep_TOI_begin_failed(thd, NULL /* failed repl/certification doesn't mean error in execution */);
+ }
+ }
+ } while (ret && cs.current_error() == wsrep::e_error_during_commit /* ? */ && run_in_nbo);
-int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
- const TABLE_LIST* table_list,
- Alter_info* alter_info)
-{
- int ret= 0;
+ if (ret) {
+ /* jump to error handler in mysql_execute_command() */
+ switch (cs.current_error())
+ {
+ case wsrep::e_size_exceeded_error:
+ WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
+ "Maximum size exceeded.",
+ ret,
+ (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
+ break;
+ default:
+ WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
+ "Check wsrep connection state and retry the query.",
+ ret,
+ (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ if (!thd->is_error())
+ {
+ my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check "
+ "your wsrep connection state and retry the query.");
+ }
+ }
+ rc= -1;
+ }
+ else {
- /*
- No isolation for applier or replaying threads.
- */
- if (thd->wsrep_exec_mode == REPL_RECV)
- return 0;
+ try {
+ /*
+ Allocate dummy thd->wsrep_nbo_ctx to track execution state
+ in mysql_execute_command().
+ */
+ if (run_in_nbo) {
+ thd->wsrep_nbo_ctx= new Wsrep_nbo_ctx(0, 0, 0, wsrep_trx_meta_t());
+ ::abort();
+ }
- mysql_mutex_lock(&thd->LOCK_thd_data);
+ // thd->wsrep_exec_mode= TOTAL_ORDER;
+ ++wsrep_to_isolation;
- if (thd->wsrep_conflict_state == MUST_ABORT)
- {
- WSREP_INFO("thread: %lld schema: %s query: %s has been aborted due to multi-master conflict",
- (longlong) thd->thread_id, thd->get_db(), thd->query());
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- return WSREP_TRX_FAIL;
+ // WSREP_DEBUG("TO BEGIN(%lu): %lld, %d, %s",
+ // thd->thread_id,
+ // (long long)wsrep_thd_trx_seqno(thd),
+ // thd->wsrep_exec_mode, WSREP_QUERY(thd));
+ rc= 0;
+
+ }
+ catch (std::bad_alloc& e) {
+ rc= -2;
+ }
}
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
- DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED);
+ if (buf) my_free(buf);
- if (thd->global_read_lock.can_acquire_protection())
+ switch(rc)
{
- WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld",
- thd->query(), (longlong) thd->thread_id);
- return -1;
- }
-
- if (wsrep_debug && thd->mdl_context.has_locks())
+ case 0:
+ break;
+ case -2:
{
- WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lld",
- thd->query(), (longlong) thd->thread_id);
+ const char* const err_str= "Failed to allocate NBO context object.";
+ wsrep_buf_t const err= { err_str, strlen(err_str) };
+ wsrep_TOI_begin_failed(thd, &err);
+ break;
+ }
+ default:
+ wsrep_TOI_begin_failed(thd, NULL);
}
- /*
- It makes sense to set auto_increment_* to defaults in TOI operations.
- Must be done before wsrep_TOI_begin() since Query_log_event encapsulating
+ return rc;
+}
+
+static void wsrep_TOI_end(THD *thd) {
+ int ret;
+ wsrep_to_isolation--;
+ wsrep::client_state& client_state(thd->wsrep_cs());
+ DBUG_ASSERT(wsrep_thd_is_local_toi(thd));
+ WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(),
+ WSREP_QUERY(thd));
+
+ if (wsrep_thd_is_local_toi(thd))
+ {
+ wsrep_set_SE_checkpoint(client_state.toi_meta().gtid());
+ if (thd->is_error() && !wsrep_must_ignore_error(thd))
+ {
+ wsrep_apply_error err;
+ err.store(thd);
+ // wsrep_buf_t const tmp= err.get_buf();
+ // ret= wsrep_ptr->to_execute_end(wsrep_ptr, thd->thread_id, &tmp);
+ client_state.leave_toi();
+ }
+ else
+ {
+ ret= client_state.leave_toi();
+ }
+
+ if (ret == 0)
+ {
+ WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get());
+ }
+ else
+ {
+ WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
+ ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd));
+ }
+ }
+
+ if (thd->wsrep_nbo_ctx)
+ {
+ delete thd->wsrep_nbo_ctx;
+ thd->wsrep_nbo_ctx= NULL;
+ }
+}
+
+static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
+{
+ WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd),
+ WSREP_QUERY(thd));
+ if (thd->wsrep_cs().begin_rsu(5000))
+ {
+ WSREP_WARN("RSU begin failed");
+ }
+ else
+ {
+ thd->variables.wsrep_on = 0;
+ }
+ return 0;
+}
+
+static void wsrep_RSU_end(THD *thd)
+{
+ WSREP_DEBUG("RSU END: %ld : %s", wsrep_thd_trx_seqno(thd),
+ WSREP_QUERY(thd));
+ if (thd->wsrep_cs().end_rsu())
+ {
+ WSREP_WARN("Failed to end RSU, server may need to be restarted");
+ }
+ thd->variables.wsrep_on = 1;
+}
+
+int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info)
+{
+ /*
+ No isolation for applier or replaying threads.
+ */
+ if (!wsrep_thd_is_local(thd)) return 0;
+
+ int ret= 0;
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+
+ if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort)
+ {
+ WSREP_INFO("thread: %lld schema: %s query: %s has been aborted due to multi-master conflict",
+ (longlong) thd->thread_id, thd->get_db(), thd->query());
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ return WSREP_TRX_FAIL;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+
+ DBUG_ASSERT(wsrep_thd_is_local(thd));
+ DBUG_ASSERT(thd->wsrep_trx().ws_meta().seqno().is_undefined());
+
+ if (thd->global_read_lock.can_acquire_protection())
+ {
+ WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu",
+ WSREP_QUERY(thd), thd->thread_id);
+ return -1;
+ }
+
+ if (wsrep_debug && thd->mdl_context.has_locks())
+ {
+ WSREP_DEBUG("thread holds MDL locks at TI begin: %s %llu",
+ WSREP_QUERY(thd), thd->thread_id);
+ }
+
+ /*
+ It makes sense to set auto_increment_* to defaults in TOI operations.
+ Must be done before wsrep_TOI_begin() since Query_log_event encapsulating
TOI statement and auto inc variables for wsrep replication is constructed
there. Variables are reset back in THD::reset_for_next_command() before
processing of next command.
@@ -1849,14 +2172,15 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
thd->variables.auto_increment_increment = 1;
}
- if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE)
+ if (thd->variables.wsrep_on && wsrep_thd_is_local(thd))
{
switch (thd->variables.wsrep_OSU_method) {
case WSREP_OSU_TOI:
+ case WSREP_OSU_NBO:
ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info);
break;
case WSREP_OSU_RSU:
- ret= wsrep_RSU_begin(thd, db_, table_);
+ ret= wsrep_RSU_begin(thd, db_, table_);
break;
default:
WSREP_ERROR("Unsupported OSU method: %lu",
@@ -1865,7 +2189,7 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
break;
}
switch (ret) {
- case 0: thd->wsrep_exec_mode= TOTAL_ORDER; break;
+ case 0: /* wsrep_TOI_begin sould set toi mode */ break;
case 1:
/* TOI replication skipped, treat as success */
ret = 0;
@@ -1875,38 +2199,137 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
break;
}
}
+
return ret;
}
void wsrep_to_isolation_end(THD *thd)
{
- if (thd->wsrep_exec_mode == TOTAL_ORDER)
+ DBUG_ASSERT(wsrep_thd_is_local_toi(thd) ||
+ wsrep_thd_is_in_rsu(thd));
+ if (wsrep_thd_is_local_toi(thd))
+ {
+ DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
+ wsrep_TOI_end(thd);
+ }
+ else if (wsrep_thd_is_in_rsu(thd))
+ {
+ DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_RSU);
+ wsrep_RSU_end(thd);
+ }
+ else
+ {
+ DBUG_ASSERT(0);
+ }
+ if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd);
+}
+
+void wsrep_begin_nbo_unlock(THD* thd)
+{
+ DBUG_ASSERT(0);
+#if 0
+ DBUG_ASSERT(thd->wsrep_nbo_ctx);
+ if (wsrep_thd_is_toi(thd))
+ {
+ if (wsrep_ptr->to_execute_end(wsrep_ptr, thd->thread_id, NULL) != WSREP_OK) {
+ WSREP_ERROR("Non-blocking operation failed to release provider "
+ "resources, cannot continue");
+ unireg_abort(1);
+ }
+ }
+ else if (wsrep_thd_is_applying(thd))
{
- switch(thd->variables.wsrep_OSU_method)
+ thd->wsrep_nbo_ctx->signal();
+ }
+ thd->wsrep_nbo_ctx->set_toi_released(true);
+#endif
+}
+
+void wsrep_end_nbo_lock(THD* thd, const TABLE_LIST *table_list)
+{
+ DBUG_ASSERT(0);
+#if 0
+ DBUG_ASSERT(thd->wsrep_nbo_ctx);
+
+ // Release TOI critical section if not released yet. This
+ // may happen if operation fails in early phase.
+ if (thd->wsrep_nbo_ctx->toi_released() == false) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+
+ DBUG_ASSERT(wsrep_thd_is_toi(thd) || wsrep_thd_is_applying(thd));
+ wsrep_status_t ret;
+ uint32_t flags= WSREP_FLAG_TRX_END;
+
+ wsrep_key_arr_t key_arr= {0, 0};
+
+ if (wsrep_prepare_keys_for_isolation(thd, NULL, NULL, table_list, &key_arr))
+ {
+ WSREP_ERROR("Failed to prepare keys for NBO end. This is fatal, must abort");
+ unireg_abort(1);
+
+ }
+ thd_proc_info(thd, "acquiring total order isolation for NBO end");
+
+ DBUG_ASSERT(key_arr.keys_len > 0);
+
+ time_t wait_start= time(NULL);
+ while ((ret= wsrep_ptr->to_execute_start(wsrep_ptr, thd->thread_id,
+ key_arr.keys, key_arr.keys_len, 0, 0,
+ flags,
+ &thd->wsrep_trx_meta))
+ == WSREP_CONN_FAIL) {
+ if (thd->killed != NOT_KILLED) {
+ WSREP_ERROR("Non-blocking operation end failed to sync with group, "
+ "thd killed %d", thd->killed);
+ /* Error handling happens outside of while() */
+ break;
+ }
+ usleep(100000);
+ if (ulong(time(NULL) - wait_start) >= thd->variables.lock_wait_timeout)
{
- case WSREP_OSU_TOI: wsrep_TOI_end(thd); break;
- case WSREP_OSU_RSU: wsrep_RSU_end(thd); break;
- default:
- WSREP_WARN("Unsupported wsrep OSU method at isolation end: %lu",
- thd->variables.wsrep_OSU_method);
+ WSREP_ERROR("Lock wait timeout while waiting NBO end to replicate.");
break;
}
- wsrep_cleanup_transaction(thd);
}
+
+ if (ret != WSREP_OK)
+ {
+ WSREP_ERROR("Failed to acquire total order isolation for non-blocking DDL "
+ "end event, provider returned error code %d: "
+ "(schema: %s, query: %s)",
+ ret, (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ thd->get_stmt_da()->set_overwrite_status(true);
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), ret);
+ thd->get_stmt_da()->set_overwrite_status(false);
+ WSREP_ERROR("This will leave database in inconsistent state since DDL "
+ "execution cannot be terminated in order. Node must rejoin "
+ "the cluster via SST");
+ wsrep_ptr->free_connection(wsrep_ptr, thd->thread_id);
+ wsrep_ptr->disconnect(wsrep_ptr);
+ // We let the operation to finish out of order in order to release
+ // all resources properly. However GTID is cleared so that the
+ // event won't be binlogged with incorrect GTID.
+ thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+ }
+
+ thd->wsrep_nbo_ctx->set_toi_released(false);
+#endif
}
#define WSREP_MDL_LOG(severity, msg, schema, schema_len, req, gra) \
WSREP_##severity( \
"%s\n" \
"schema: %.*s\n" \
- "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \
- "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \
+ "request: (%llu \tseqno %lld \twsrep (%s, %s, %s) cmd %d %d \t%s)\n" \
+ "granted: (%llu \tseqno %lld \twsrep (%s, %s, %s) cmd %d %d \t%s)", \
msg, schema_len, schema, \
- (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \
- req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \
+ req->thread_id, (long long)wsrep_thd_trx_seqno(req), \
+ wsrep_thd_client_mode_str(req), wsrep_thd_client_state_str(req), wsrep_thd_transaction_state_str(req), \
req->get_command(), req->lex->sql_command, req->query(), \
- (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \
- gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \
+ gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \
+ wsrep_thd_client_mode_str(gra), wsrep_thd_client_state_str(gra), wsrep_thd_transaction_state_str(gra), \
gra->get_command(), gra->lex->sql_command, gra->query());
/**
@@ -1934,43 +2357,35 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
int schema_len= key->db_name_length();
mysql_mutex_lock(&request_thd->LOCK_thd_data);
+ if (wsrep_thd_is_toi(request_thd) ||
+ wsrep_thd_is_applying(request_thd)) {
- /*
- We consider granting MDL exceptions only for appliers (BF THD) and ones
- executing under TOI mode.
-
- Rules:
- 1. If granted/owner THD is also an applier (BF THD) or one executing
- under TOI mode, then we grant the requested lock to the requester
- THD.
- @return true
-
- 2. If granted/owner THD is executing a FLUSH command or already has an
- explicit lock, then do not grant the requested lock to the requester
- THD and it has to wait.
- @return false
-
- 3. In all other cases the granted/owner THD is aborted and the requested
- lock is not granted to the requester THD, thus it has to wait.
- @return false
- */
- if (request_thd->wsrep_exec_mode == TOTAL_ORDER ||
- request_thd->wsrep_exec_mode == REPL_RECV)
- {
mysql_mutex_unlock(&request_thd->LOCK_thd_data);
WSREP_MDL_LOG(DEBUG, "MDL conflict ", schema, schema_len,
request_thd, granted_thd);
ticket->wsrep_report(wsrep_debug);
mysql_mutex_lock(&granted_thd->LOCK_thd_data);
- if (granted_thd->wsrep_exec_mode == TOTAL_ORDER ||
- granted_thd->wsrep_exec_mode == REPL_RECV)
+ if (wsrep_thd_is_toi(granted_thd) ||
+ wsrep_thd_is_applying(granted_thd))
{
- WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len,
- request_thd, granted_thd);
- ticket->wsrep_report(true);
- mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- ret= true;
+ if (wsrep_thd_is_SR((void*)granted_thd) &&
+ !wsrep_thd_is_SR((void*)request_thd))
+ {
+ WSREP_MDL_LOG(INFO, "MDL conflict, DDL vs SR",
+ schema, schema_len, request_thd, granted_thd);
+ mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
+ }
+ else
+ {
+ WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len,
+ request_thd, granted_thd);
+ ticket->wsrep_report(true);
+ mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
+ ret = TRUE;
+ }
}
else if (granted_thd->lex->sql_command == SQLCOM_FLUSH ||
granted_thd->mdl_context.has_explicit_locks())
@@ -1978,173 +2393,60 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
WSREP_DEBUG("BF thread waiting for FLUSH");
ticket->wsrep_report(wsrep_debug);
mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- ret= false;
+ ret = FALSE;
+ }
+ else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
+ {
+ WSREP_DEBUG("DROP caused BF abort, conf %s",
+ wsrep_thd_transaction_state_str(granted_thd));
+ ticket->wsrep_report(wsrep_debug);
+ mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
}
else
{
- /* Print some debug information. */
- if (wsrep_debug)
+ WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len,
+ request_thd, granted_thd);
+ ticket->wsrep_report(wsrep_debug);
+ if (granted_thd->wsrep_trx().active())
{
- if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE ||
- request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE)
- {
- WSREP_DEBUG("DROP caused BF abort, conf %d", granted_thd->wsrep_conflict_state);
- }
- else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
+ mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
+ wsrep_abort_thd(request_thd, granted_thd, 1);
+ ret= FALSE;
+ }
+ else
+ {
+ /*
+ Granted_thd is likely executing with wsrep_on=0. If the requesting
+ thd is BF, BF abort and wait.
+ */
+ mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
+ if (wsrep_thd_is_BF(request_thd, FALSE))
{
- WSREP_DEBUG("MDL granted, but committing thd abort scheduled");
+ ha_abort_transaction(request_thd, granted_thd, TRUE);
+ ret= FALSE;
}
else
{
- WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len,
- request_thd, granted_thd);
+ DBUG_ASSERT(0);
+ ret= TRUE;
}
- ticket->wsrep_report(true);
}
-
- mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- wsrep_abort_thd((void *) request_thd, (void *) granted_thd, 1);
- ret= false;
}
}
else
{
mysql_mutex_unlock(&request_thd->LOCK_thd_data);
}
-
return ret;
}
-
-pthread_handler_t start_wsrep_THD(void *arg)
-{
- THD *thd;
- wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
-
- if (my_thread_init() || (!(thd= new THD(next_thread_id(), true))))
- {
- goto error;
- }
-
- mysql_mutex_lock(&LOCK_thread_count);
-
- if (wsrep_gtid_mode)
- {
- /* Adjust domain_id. */
- thd->variables.gtid_domain_id= wsrep_gtid_domain_id;
- }
-
- thd->real_id=pthread_self(); // Keep purify happy
- thread_created++;
- threads.append(thd);
-
- my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
-
- DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
- thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
- (void) mysql_mutex_unlock(&LOCK_thread_count);
-
- /* from bootstrap()... */
- thd->bootstrap=1;
- thd->max_client_packet_length= thd->net.max_packet;
- thd->security_ctx->master_access= ~(ulong)0;
-
- /* from handle_one_connection... */
- pthread_detach_this_thread();
-
- mysql_thread_set_psi_id(thd->thread_id);
- thd->thr_create_utime= microsecond_interval_timer();
- if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
- {
- close_connection(thd, ER_OUT_OF_RESOURCES);
- statistic_increment(aborted_connects,&LOCK_status);
- MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
- goto error;
- }
-
-// </5.1.17>
- /*
- handle_one_connection() is normally the only way a thread would
- start and would always be on the very high end of the stack ,
- therefore, the thread stack always starts at the address of the
- first local variable of handle_one_connection, which is thd. We
- need to know the start of the stack so that we could check for
- stack overruns.
- */
- DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n",
- (long long)thd->thread_id));
- /* now that we've called my_thread_init(), it is safe to call DBUG_* */
-
- thd->thread_stack= (char*) &thd;
- if (thd->store_globals())
- {
- close_connection(thd, ER_OUT_OF_RESOURCES);
- statistic_increment(aborted_connects,&LOCK_status);
- MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
- goto error;
- }
-
- thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
- thd->security_ctx->skip_grants();
-
- /* handle_one_connection() again... */
- //thd->version= refresh_version;
- thd->proc_info= 0;
- thd->set_command(COM_SLEEP);
- thd->init_for_queries();
-
- mysql_mutex_lock(&LOCK_thread_count);
- wsrep_running_threads++;
- mysql_cond_broadcast(&COND_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
-
- processor(thd);
-
- close_connection(thd, 0);
-
- mysql_mutex_lock(&LOCK_thread_count);
- wsrep_running_threads--;
- WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
- mysql_cond_broadcast(&COND_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
-
- // Note: We can't call THD destructor without crashing
- // if plugins have not been initialized. However, in most of the
- // cases this means that pre SE initialization SST failed and
- // we are going to exit anyway.
- if (plugins_are_initialized)
- {
- net_end(&thd->net);
- MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1));
- }
- else
- {
- // TODO: lightweight cleanup to get rid of:
- // 'Error in my_thread_global_end(): 2 threads didn't exit'
- // at server shutdown
- }
-
- unlink_not_visible_thd(thd);
- delete thd;
- my_thread_end();
- return(NULL);
-
-error:
- WSREP_ERROR("Failed to create/initialize system thread");
-
- /* Abort if its the first applier/rollbacker thread. */
- if (!mysqld_server_initialized)
- unireg_abort(1);
- else
- return NULL;
-}
-
-
/**/
static bool abort_replicated(THD *thd)
{
bool ret_code= false;
- if (thd->wsrep_query_state== QUERY_COMMITTING)
+ if (thd->wsrep_trx().state() == wsrep::transaction::s_committing)
{
WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id));
@@ -2154,38 +2456,34 @@ static bool abort_replicated(THD *thd)
return ret_code;
}
-
/**/
static inline bool is_client_connection(THD *thd)
{
return (thd->wsrep_client_thread && thd->variables.wsrep_on);
}
-
static inline bool is_replaying_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_thd_data);
- ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false;
+ ret= (thd->wsrep_trx().state() == wsrep::transaction::s_replaying) ? true : false;
mysql_mutex_unlock(&thd->LOCK_thd_data);
return ret;
}
-
static inline bool is_committing_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_thd_data);
- ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false;
+ ret= (thd->wsrep_trx().state() == wsrep::transaction::s_committing) ? true : false;
mysql_mutex_unlock(&thd->LOCK_thd_data);
return ret;
}
-
static bool have_client_connections()
{
THD *tmp;
@@ -2222,7 +2520,6 @@ static void wsrep_close_thread(THD *thd)
}
}
-
static my_bool have_committing_connections()
{
THD *tmp;
@@ -2236,6 +2533,7 @@ static my_bool have_committing_connections()
if (is_committing_connection(tmp))
{
+ mysql_mutex_unlock(&LOCK_thread_count);
return TRUE;
}
}
@@ -2243,7 +2541,6 @@ static my_bool have_committing_connections()
return FALSE;
}
-
int wsrep_wait_committing_connections_close(int wait_time)
{
int sleep_time= 100;
@@ -2261,8 +2558,7 @@ int wsrep_wait_committing_connections_close(int wait_time)
return 0;
}
-
-void wsrep_close_client_connections(my_bool wait_to_end)
+void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd)
{
/*
First signal all threads that it's time to die
@@ -2284,6 +2580,12 @@ void wsrep_close_client_connections(my_bool wait_to_end)
if (!is_client_connection(tmp))
continue;
+ if (tmp == except_caller_thd)
+ {
+ DBUG_ASSERT(is_client_connection(tmp));
+ continue;
+ }
+
if (is_replaying_connection(tmp))
{
tmp->set_killed(KILL_CONNECTION);
@@ -2313,7 +2615,8 @@ void wsrep_close_client_connections(my_bool wait_to_end)
#ifndef __bsdi__ // Bug in BSDI kernel
if (is_client_connection(tmp) &&
!abort_replicated(tmp) &&
- !is_replaying_connection(tmp))
+ !is_replaying_connection(tmp) &&
+ tmp != except_caller_thd)
{
WSREP_INFO("killing local connection: %lld", (longlong) tmp->thread_id);
close_connection(tmp,0);
@@ -2344,7 +2647,6 @@ void wsrep_close_applier(THD *thd)
wsrep_close_thread(thd);
}
-
void wsrep_close_threads(THD *thd)
{
THD *tmp;
@@ -2370,278 +2672,210 @@ void wsrep_wait_appliers_close(THD *thd)
{
/* Wait for wsrep appliers to gracefully exit */
mysql_mutex_lock(&LOCK_thread_count);
- while (wsrep_running_threads > 1)
- // 1 is for rollbacker thread which needs to be killed explicitly.
+ while (wsrep_running_threads > 2)
+ // 2 is for rollbacker thread which needs to be killed explicitly.
// This gotta be fixed in a more elegant manner if we gonna have arbitrary
// number of non-applier wsrep threads.
{
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_unlock(&LOCK_thread_count);
- my_sleep(100);
- mysql_mutex_lock(&LOCK_thread_count);
- }
- else
- mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
- DBUG_PRINT("quit",("One applier died (count=%u)",thread_count));
- }
- mysql_mutex_unlock(&LOCK_thread_count);
- /* Now kill remaining wsrep threads: rollbacker */
- wsrep_close_threads (thd);
- /* and wait for them to die */
- mysql_mutex_lock(&LOCK_thread_count);
- while (wsrep_running_threads > 0)
- {
- if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
- {
- mysql_mutex_unlock(&LOCK_thread_count);
- my_sleep(100);
- mysql_mutex_lock(&LOCK_thread_count);
- }
- else
- mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
- DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
- }
- mysql_mutex_unlock(&LOCK_thread_count);
-
- /* All wsrep applier threads have now been aborted. However, if this thread
- is also applier, we are still running...
- */
-}
-
-
-void wsrep_kill_mysql(THD *thd)
-{
- if (mysqld_server_started)
- {
- if (!shutdown_in_progress)
- {
- WSREP_INFO("starting shutdown");
- kill_mysql();
- }
- }
- else
- {
- unireg_abort(1);
- }
-}
-
-
-static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
-{
- String log_query;
- sp_head *sp = thd->lex->sphead;
- sql_mode_t saved_mode= thd->variables.sql_mode;
- String retstr(64);
- LEX_CSTRING returns= empty_clex_str;
- retstr.set_charset(system_charset_info);
-
- log_query.set_charset(system_charset_info);
-
- if (sp->m_handler->type() == TYPE_ENUM_FUNCTION)
- {
- sp_returns_type(thd, retstr, sp);
- returns= retstr.lex_cstring();
- }
- if (sp->m_handler->
- show_create_sp(thd, &log_query,
- sp->m_explicit_name ? sp->m_db : null_clex_str,
- sp->m_name, sp->m_params, returns,
- sp->m_body, sp->chistics(),
- thd->lex->definer[0],
- thd->lex->create_info,
- saved_mode))
- {
- WSREP_WARN("SP create string failed: schema: %s, query: %s",
- thd->get_db(), thd->query());
- return 1;
- }
-
- return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len);
-}
-
-
-extern int wsrep_on(THD *thd)
-{
- return (int)(WSREP(thd));
-}
-
-
-extern "C" bool wsrep_thd_is_wsrep_on(THD *thd)
-{
- return thd->variables.wsrep_on;
-}
-
-
-bool wsrep_consistency_check(THD *thd)
-{
- return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
-}
-
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
-{
- thd->wsrep_exec_mode= mode;
-}
-
-
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state)
-{
- thd->wsrep_query_state= state;
-}
-
-
-void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state)
-{
- if (WSREP(thd)) thd->wsrep_conflict_state= state;
-}
-
-
-enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd)
-{
- return thd->wsrep_exec_mode;
-}
-
+ my_sleep(100);
+ mysql_mutex_lock(&LOCK_thread_count);
+ }
+ else
+ mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
+ DBUG_PRINT("quit",("One applier died (count=%u)",thread_count));
+ }
+ mysql_mutex_unlock(&LOCK_thread_count);
+ /* Now kill remaining wsrep threads: rollbacker */
+ wsrep_close_threads (thd);
+ /* and wait for them to die */
+ mysql_mutex_lock(&LOCK_thread_count);
+ while (wsrep_running_threads > 0)
+ {
+ if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
+ {
+ mysql_mutex_unlock(&LOCK_thread_count);
+ my_sleep(100);
+ mysql_mutex_lock(&LOCK_thread_count);
+ }
+ else
+ mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
+ DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
+ }
+ mysql_mutex_unlock(&LOCK_thread_count);
-const char *wsrep_thd_exec_mode_str(THD *thd)
-{
- return
- (!thd) ? "void" :
- (thd->wsrep_exec_mode == LOCAL_STATE) ? "local" :
- (thd->wsrep_exec_mode == REPL_RECV) ? "applier" :
- (thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" :
- (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void";
+ /* All wsrep applier threads have now been aborted. However, if this thread
+ is also applier, we are still running...
+ */
}
-
-enum wsrep_query_state wsrep_thd_query_state(THD *thd)
+void wsrep_kill_mysql(THD *thd)
{
- return thd->wsrep_query_state;
+ if (mysqld_server_started)
+ {
+ if (!shutdown_in_progress)
+ {
+ WSREP_INFO("starting shutdown");
+ kill_mysql();
+ }
+ }
+ else
+ {
+ unireg_abort(1);
+ }
}
-
-const char *wsrep_thd_query_state_str(THD *thd)
+void
+wsrep_last_committed_id(wsrep_gtid_t* gtid)
{
- return
- (!thd) ? "void" :
- (thd->wsrep_query_state == QUERY_IDLE) ? "idle" :
- (thd->wsrep_query_state == QUERY_EXEC) ? "executing" :
- (thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" :
- (thd->wsrep_query_state == QUERY_EXITING) ? "exiting" :
- (thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void";
+ // wsrep_ptr->last_committed_id(wsrep_ptr, gtid);
+ wsrep::gtid ret= Wsrep_server_state::instance().last_committed_gtid();
+ memcpy(gtid->uuid.data, ret.id().data(), sizeof(gtid->uuid.data));
+ gtid->seqno= ret.seqno().get();
}
-
-enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *thd)
+void
+wsrep_node_uuid(wsrep_uuid_t& uuid)
{
- return thd->wsrep_conflict_state;
+ uuid = node_uuid;
}
-
-const char *wsrep_thd_conflict_state_str(THD *thd)
+int wsrep_must_ignore_error(THD* thd)
{
- return
- (!thd) ? "void" :
- (thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" :
- (thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" :
- (thd->wsrep_conflict_state == ABORTING) ? "aborting" :
- (thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" :
- (thd->wsrep_conflict_state == REPLAYING) ? "replaying" :
- (thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" :
- (thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void";
-}
-
+ const int error= thd->get_stmt_da()->sql_errno();
+ const uint flags= sql_command_flags[thd->lex->sql_command];
-wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd)
-{
- return &thd->wsrep_ws_handle;
-}
+ DBUG_ASSERT(error);
+ DBUG_ASSERT((wsrep_thd_is_toi(thd)) ||
+ (wsrep_thd_is_applying(thd) && thd->wsrep_apply_toi));
+ if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_DDL))
+ goto ignore_error;
-void wsrep_thd_LOCK(THD *thd)
-{
- mysql_mutex_lock(&thd->LOCK_thd_data);
-}
+ if ((flags & CF_WSREP_MAY_IGNORE_ERRORS) &&
+ (wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL))
+ {
+ switch (error)
+ {
+ case ER_DB_DROP_EXISTS:
+ case ER_BAD_TABLE_ERROR:
+ case ER_CANT_DROP_FIELD_OR_KEY:
+ goto ignore_error;
+ }
+ }
+ return 0;
-void wsrep_thd_UNLOCK(THD *thd)
-{
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ignore_error:
+ WSREP_WARN("Ignoring error '%s' on query. "
+ "Default database: '%s'. Query: '%s', Error_code: %d",
+ thd->get_stmt_da()->message(),
+ print_slave_db_safe(thd->db.str),
+ thd->query(),
+ error);
+ return 1;
}
-
-extern "C" time_t wsrep_thd_query_start(THD *thd)
+int wsrep_ignored_error_code(Log_event* ev, int error)
{
- return thd->query_start();
-}
+ const THD* thd= ev->thd;
+ DBUG_ASSERT(error);
+ DBUG_ASSERT(wsrep_thd_is_applying(thd) &&
+ !wsrep_thd_is_local_toi(thd));
-extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd)
-{
- return thd->wsrep_rand;
-}
-
-longlong wsrep_thd_trx_seqno(THD *thd)
-{
- return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED;
-}
+ if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DML))
+ {
+ const int ev_type= ev->get_type_code();
+ if (ev_type == DELETE_ROWS_EVENT && error == ER_KEY_NOT_FOUND)
+ goto ignore_error;
+ }
+ return 0;
-extern "C" query_id_t wsrep_thd_query_id(THD *thd)
-{
- return thd->query_id;
+ignore_error:
+ WSREP_WARN("Ignoring error '%s' on %s event. Error_code: %d",
+ thd->get_stmt_da()->message(),
+ ev->get_type_str(),
+ error);
+ return 1;
}
-
-char *wsrep_thd_query(THD *thd)
+bool wsrep_provider_is_SR_capable()
{
- return (thd) ? thd->query() : NULL;
+ return Wsrep_server_state::has_capability(wsrep::provider::capability::streaming);
}
-extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
+int wsrep_ordered_commit_if_no_binlog(THD* thd, bool all)
{
- return thd->wsrep_last_query_id;
+ if (((wsrep_thd_is_local(thd) && WSREP_EMULATE_BINLOG(thd)) ||
+ (wsrep_thd_is_applying(thd) && !opt_log_slave_updates && !opt_bin_log))
+ && wsrep_thd_trx_seqno(thd) > 0)
+ {
+ wsrep_apply_error unused;
+ return wsrep_ordered_commit(thd, all, unused);
+ }
+ return 0;
}
-
-extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
+wsrep_status_t wsrep_tc_log_commit(THD* thd)
{
- thd->wsrep_last_query_id= id;
-}
+ int cookie;
+ my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
+ DBUG_ASSERT(thd->lex->sql_command == SQLCOM_LOAD);
+ cookie= tc_log->log_and_order(thd, xid, 1, false, true);
+ if (!cookie)
+ {
+ WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie);
+ return WSREP_TRX_FAIL;
+ }
+ if (tc_log->unlog(cookie, xid))
+ {
+ WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie);
+ return WSREP_TRX_FAIL;
+ }
-extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
-{
- if (signal)
+ if (wsrep_after_statement(thd))
{
- thd->awake(KILL_QUERY);
+ return WSREP_TRX_FAIL;
}
- else
+ /* Set wsrep transaction id if not set. */
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ }
+ DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ }
+ if (wsrep_start_transaction(thd, thd->wsrep_next_trx_id()))
{
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- mysql_cond_broadcast(&COND_wsrep_replaying);
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ return WSREP_TRX_FAIL;
}
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ return WSREP_OK;
}
-
int wsrep_thd_retry_counter(THD *thd)
{
return(thd->wsrep_retry_counter);
}
-
-extern "C" bool wsrep_thd_ignore_table(THD *thd)
+extern bool wsrep_thd_ignore_table(THD *thd)
{
return thd->wsrep_ignore_table;
}
-
-extern int
-wsrep_trx_order_before(THD *thd1, THD *thd2)
+extern my_bool
+wsrep_trx_order_before(const void* thd1_ptr, const void* thd2_ptr)
{
+ THD *thd1= (THD*) thd1_ptr;
+ THD *thd2= (THD*) thd2_ptr;
+
if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno(thd1),
@@ -2654,39 +2888,11 @@ wsrep_trx_order_before(THD *thd1, THD *thd2)
return 0;
}
-
-int wsrep_trx_is_aborting(THD *thd_ptr)
-{
- if (thd_ptr) {
- if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) ||
- (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) {
- return 1;
- }
- }
- return 0;
-}
-
-
-void wsrep_copy_query(THD *thd)
-{
- thd->wsrep_retry_command = thd->get_command();
- thd->wsrep_retry_query_len = thd->query_length();
- if (thd->wsrep_retry_query) {
- my_free(thd->wsrep_retry_query);
- }
- thd->wsrep_retry_query = (char *)my_malloc(
- thd->wsrep_retry_query_len + 1, MYF(0));
- strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len);
- thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0';
-}
-
-
bool wsrep_is_show_query(enum enum_sql_command command)
{
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0;
}
-
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
HA_CREATE_INFO *create_info)
@@ -2736,8 +2942,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
return (true);
}
-
-static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
String stmt_query;
@@ -2792,6 +2997,142 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
buf, buf_len);
}
+void* start_wsrep_THD(void *arg)
+{
+ THD *thd;
+ //wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
+
+ Wsrep_thd_args* thd_args= (Wsrep_thd_args*) arg;
+
+ if (my_thread_init() || (!(thd= new THD(next_thread_id(), true))))
+ {
+ goto error;
+ }
+
+ mysql_mutex_lock(&LOCK_thread_count);
+
+ if (wsrep_gtid_mode)
+ {
+ /* Adjust domain_id. */
+ thd->variables.gtid_domain_id= wsrep_gtid_domain_id;
+ }
+
+ thd->real_id=pthread_self(); // Keep purify happy
+ thread_created++;
+ threads.append(thd);
+
+ my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
+
+ DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
+ thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
+ (void) mysql_mutex_unlock(&LOCK_thread_count);
+
+ /* from bootstrap()... */
+ thd->bootstrap=1;
+ thd->max_client_packet_length= thd->net.max_packet;
+ thd->security_ctx->master_access= ~(ulong)0;
+
+ /* from handle_one_connection... */
+ pthread_detach_this_thread();
+
+ mysql_thread_set_psi_id(thd->thread_id);
+ thd->thr_create_utime= microsecond_interval_timer();
+ if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
+ {
+ close_connection(thd, ER_OUT_OF_RESOURCES);
+ statistic_increment(aborted_connects,&LOCK_status);
+ MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
+ goto error;
+ }
+
+// </5.1.17>
+ /*
+ handle_one_connection() is normally the only way a thread would
+ start and would always be on the very high end of the stack ,
+ therefore, the thread stack always starts at the address of the
+ first local variable of handle_one_connection, which is thd. We
+ need to know the start of the stack so that we could check for
+ stack overruns.
+ */
+ DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n",
+ (long long)thd->thread_id));
+ /* now that we've called my_thread_init(), it is safe to call DBUG_* */
+
+ thd->thread_stack= (char*) &thd;
+ if (thd->store_globals())
+ {
+ close_connection(thd, ER_OUT_OF_RESOURCES);
+ statistic_increment(aborted_connects,&LOCK_status);
+ MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
+ delete thd;
+ delete thd_args;
+ goto error;
+ }
+
+ thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
+ thd->security_ctx->skip_grants();
+
+ /* handle_one_connection() again... */
+ //thd->version= refresh_version;
+ thd->proc_info= 0;
+ thd->set_command(COM_SLEEP);
+ thd->init_for_queries();
+
+ mysql_mutex_lock(&LOCK_thread_count);
+ wsrep_running_threads++;
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
+
+ WSREP_DEBUG("wsrep system thread %ld, %p starting",
+ thd->thread_id, thd);
+ thd_args->fun()(thd, thd_args->args());
+
+ WSREP_DEBUG("wsrep system thread: %ld, %p closing",
+ thd->thread_id, thd);
+ //processor(thd);
+
+ close_connection(thd, 0);
+
+ delete thd_args;
+
+ mysql_mutex_lock(&LOCK_thread_count);
+ wsrep_running_threads--;
+ WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
+
+ // Note: We can't call THD destructor without crashing
+ // if plugins have not been initialized. However, in most of the
+ // cases this means that pre SE initialization SST failed and
+ // we are going to exit anyway.
+ if (plugins_are_initialized)
+ {
+ net_end(&thd->net);
+ MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1));
+ }
+ else
+ {
+ // TODO: lightweight cleanup to get rid of:
+ // 'Error in my_thread_global_end(): 2 threads didn't exit'
+ // at server shutdown
+ }
+
+ unlink_not_visible_thd(thd);
+ delete thd;
+ my_thread_end();
+ return(NULL);
+
+error:
+ WSREP_ERROR("Failed to create/initialize system thread");
+
+ /* Abort if its the first applier/rollbacker thread. */
+ if (!mysqld_server_initialized)
+ unireg_abort(1);
+ else
+ return NULL;
+}
+
+
/***** callbacks for wsrep service ************/
my_bool get_wsrep_debug()
@@ -2824,56 +3165,17 @@ my_bool get_wsrep_log_conflicts()
return wsrep_log_conflicts;
}
-wsrep_t *get_wsrep()
+bool wsrep_consistency_check(THD *thd)
{
- return wsrep;
+ return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
}
+//wsrep_t *get_wsrep()
+//{
+// return wsrep;
+//}
+
my_bool get_wsrep_certify_nonPK()
{
return wsrep_certify_nonPK;
}
-
-void wsrep_lock_rollback()
-{
- mysql_mutex_lock(&LOCK_wsrep_rollback);
-}
-
-void wsrep_unlock_rollback()
-{
- mysql_cond_signal(&COND_wsrep_rollback);
- mysql_mutex_unlock(&LOCK_wsrep_rollback);
-}
-
-my_bool wsrep_aborting_thd_contains(THD *thd)
-{
- mysql_mutex_assert_owner(&LOCK_wsrep_rollback);
- wsrep_aborting_thd_t abortees = wsrep_aborting_thd;
- while (abortees)
- {
- if (abortees->aborting_thd == thd)
- return true;
- abortees = abortees->next;
- }
- return false;
-}
-
-void wsrep_aborting_thd_enqueue(THD *thd)
-{
- mysql_mutex_assert_owner(&LOCK_wsrep_rollback);
- wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t)
- my_malloc(sizeof(struct wsrep_aborting_thd), MYF(0));
- aborting->aborting_thd = thd;
- aborting->next = wsrep_aborting_thd;
- wsrep_aborting_thd = aborting;
-}
-
-bool wsrep_node_is_donor()
-{
- return (WSREP_ON) ? (wsrep_config_state->get_status() == 2) : false;
-}
-
-bool wsrep_node_is_synced()
-{
- return (WSREP_ON) ? (wsrep_config_state->get_status() == 4) : false;
-}
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 819a56b9f23..09f09d495e0 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2015 Codership Oy <http://www.codership.com>
+/* Copyright 2008-2017 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,18 +19,23 @@
#define WSREP_MYSQLD_H
#include <mysql/plugin.h>
-#include <mysql/service_wsrep.h>
+#include "mysql/service_wsrep.h"
-#ifdef WITH_WSREP
+#include <my_global.h>
+#include <my_pthread.h>
+#include "log.h"
+#include "mysqld.h"
typedef struct st_mysql_show_var SHOW_VAR;
#include <sql_priv.h>
//#include "rpl_gtid.h"
-#include "../wsrep/wsrep_api.h"
#include "mdl.h"
-#include "mysqld.h"
#include "sql_table.h"
+#include "../wsrep-lib/include/wsrep/provider.hpp"
+#include "../wsrep-lib/wsrep/wsrep_api.h"
+#include <vector>
+
#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX
class set_var;
@@ -42,20 +47,8 @@ enum wsrep_consistency_check_mode {
CONSISTENCY_CHECK_RUNNING,
};
-struct wsrep_thd_shadow {
- ulonglong options;
- uint server_status;
- enum wsrep_exec_mode wsrep_exec_mode;
- Vio *vio;
- ulong tx_isolation;
- const char *db;
- size_t db_length;
- my_hrtime_t user_time;
- longlong row_count_func;
-};
-
// Global wsrep parameters
-extern wsrep_t* wsrep;
+// extern wsrep_t* wsrep_ptr;
// MySQL wsrep options
extern const char* wsrep_provider;
@@ -69,24 +62,34 @@ extern const char* wsrep_data_home_dir;
extern const char* wsrep_dbug_option;
extern long wsrep_slave_threads;
extern int wsrep_slave_count_change;
+extern MYSQL_PLUGIN_IMPORT my_bool wsrep_debug;
extern my_bool wsrep_convert_LOCK_to_trx;
extern ulong wsrep_retry_autocommit;
extern my_bool wsrep_auto_increment_control;
+extern my_bool wsrep_drupal_282555_workaround;
extern my_bool wsrep_incremental_data_collection;
extern const char* wsrep_start_position;
extern ulong wsrep_max_ws_size;
extern ulong wsrep_max_ws_rows;
extern const char* wsrep_notify_cmd;
-extern long wsrep_max_protocol_version;
+extern my_bool wsrep_certify_nonPK;
+extern long int wsrep_protocol_version;
extern ulong wsrep_forced_binlog_format;
extern my_bool wsrep_desync;
extern ulong wsrep_reject_queries;
+extern my_bool wsrep_recovery;
extern my_bool wsrep_replicate_myisam;
+extern my_bool wsrep_log_conflicts;
extern ulong wsrep_mysql_replication_bundle;
+extern my_bool wsrep_load_data_splitting;
extern my_bool wsrep_restart_slave;
extern my_bool wsrep_restart_slave_activated;
extern my_bool wsrep_slave_FK_checks;
extern my_bool wsrep_slave_UK_checks;
+extern ulong wsrep_trx_fragment_size;
+extern ulong wsrep_trx_fragment_unit;
+extern ulong wsrep_SR_store_type;
+extern uint wsrep_ignore_apply_errors;
extern ulong wsrep_running_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
@@ -101,6 +104,7 @@ enum enum_wsrep_reject_types {
enum enum_wsrep_OSU_method {
WSREP_OSU_TOI,
WSREP_OSU_RSU,
+ WSREP_OSU_NBO,
WSREP_OSU_NONE,
};
@@ -114,6 +118,14 @@ enum enum_wsrep_sync_wait {
WSREP_SYNC_WAIT_MAX = 0xF
};
+enum enum_wsrep_ignore_apply_error {
+ WSREP_IGNORE_ERRORS_NONE = 0x0,
+ WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL = 0x1,
+ WSREP_IGNORE_ERRORS_ON_RECONCILING_DML = 0x2,
+ WSREP_IGNORE_ERRORS_ON_DDL = 0x4,
+ WSREP_IGNORE_ERRORS_MAX = 0x7
+};
+
// MySQL status variables
extern my_bool wsrep_connected;
extern my_bool wsrep_ready;
@@ -126,11 +138,22 @@ extern long long wsrep_local_bf_aborts;
extern const char* wsrep_provider_name;
extern const char* wsrep_provider_version;
extern const char* wsrep_provider_vendor;
+extern char* wsrep_provider_capabilities;
+extern char* wsrep_cluster_capabilities;
+
+//int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff,
+// enum enum_var_type scope);
+int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff);
+int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff);
+void wsrep_free_status(THD *thd);
+void wsrep_update_cluster_state_uuid(const char* str);
+
+/* Filters out --wsrep-new-cluster oprtion from argv[]
+ * should be called in the very beginning of main() */
+void wsrep_filter_new_cluster (int* argc, char* argv[]);
-int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff,
- enum enum_var_type scope);
int wsrep_init();
-void wsrep_deinit(bool free_options);
+void wsrep_deinit();
/* Initialize wsrep thread LOCKs and CONDs */
void wsrep_thr_init();
@@ -147,51 +170,60 @@ void wsrep_init_startup(bool before);
// Other wsrep global variables
extern my_bool wsrep_inited; // whether wsrep is initialized ?
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state);
-
-extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
-
+extern "C" void wsrep_fire_rollbacker(THD *thd);
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
extern "C" time_t wsrep_thd_query_start(THD *thd);
-extern "C" query_id_t wsrep_thd_query_id(THD *thd);
+extern void wsrep_close_client_connections(my_bool wait_to_end,
+ THD *except_caller_thd = NULL);
+//extern "C" query_id_t wsrep_thd_query_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-extern void wsrep_close_client_connections(my_bool wait_to_end);
extern int wsrep_wait_committing_connections_close(int wait_time);
extern void wsrep_close_applier(THD *thd);
extern void wsrep_wait_appliers_close(THD *thd);
extern void wsrep_close_applier_threads(int count);
extern void wsrep_kill_mysql(THD *thd);
+
/* new defines */
extern void wsrep_stop_replication(THD *thd);
extern bool wsrep_start_replication();
-extern bool wsrep_must_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
-extern bool wsrep_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
+extern void wsrep_shutdown_replication();
+extern bool wsrep_must_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
+extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
+extern enum wsrep::provider::status
+wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
+extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path);
+
+
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
-
#define WSREP_ON \
- (global_system_variables.wsrep_on)
-
-#define WSREP_ON_NEW \
((global_system_variables.wsrep_on) && \
wsrep_provider && \
strcmp(wsrep_provider, WSREP_NONE))
-#define WSREP(thd) \
+/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to
+ * avoid compiler warnings (GCC 6 and later) */
+#define WSREP_NNULL(thd) \
(WSREP_ON && thd->variables.wsrep_on)
+#define WSREP(thd) \
+ (thd && WSREP_NNULL(thd))
+
+#define WSREP_CLIENT_NNULL(thd) \
+ (WSREP_NNULL(thd) && thd->wsrep_client_thread)
+
#define WSREP_CLIENT(thd) \
(WSREP(thd) && thd->wsrep_client_thread)
+#define WSREP_EMULATE_BINLOG_NNULL(thd) \
+ (WSREP_NNULL(thd) && wsrep_emulate_bin_log)
+
#define WSREP_EMULATE_BINLOG(thd) \
(WSREP(thd) && wsrep_emulate_bin_log)
@@ -200,27 +232,42 @@ extern wsrep_seqno_t wsrep_locked_seqno;
? wsrep_forced_binlog_format : (ulong)(my_format))
// prefix all messages with "WSREP"
-void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
-#define WSREP_LOG(fun, ...) wsrep_log(fun, ## __VA_ARGS__)
-#define WSREP_LOG_CONFLICT_THD(thd, role) \
- WSREP_LOG(sql_print_information, \
- "%s: \n " \
- " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \
- " SQL: %s", \
- role, thd_get_thread_id(thd), wsrep_thd_exec_mode_str(thd), \
- wsrep_thd_query_state_str(thd), \
- wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \
- wsrep_thd_query(thd) \
- );
-
-#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \
- if (wsrep_debug || wsrep_log_conflicts) \
- { \
- WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:",\
- (bf_abort) ? "high priority abort" : "certification failure" \
- ); \
- if (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \
- if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \
+#define WSREP_LOG(fun, ...) \
+ do { \
+ char msg[1024] = {'\0'}; \
+ snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \
+ fun("WSREP: %s", msg); \
+ } while(0)
+
+#define WSREP_DEBUG(...) \
+ if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
+#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
+#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__)
+#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__)
+
+#define WSREP_LOG_CONFLICT_THD(thd, role) \
+ WSREP_LOG(sql_print_information, \
+ "%s: \n " \
+ " THD: %llu, mode: %s, state: %s, conflict: %s, seqno: %ld\n " \
+ " SQL: %s", \
+ role, \
+ wsrep_thd_thread_id(thd), \
+ wsrep_thd_client_mode_str(thd), \
+ wsrep_thd_client_state_str(thd), \
+ wsrep_thd_transaction_state_str(thd), \
+ wsrep_thd_trx_seqno(thd), \
+ wsrep_thd_query(thd) \
+ );
+
+#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \
+ if (wsrep_debug || wsrep_log_conflicts) \
+ { \
+ WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:", \
+ (bf_abort) ? "high priority abort" : "certification failure" \
+ ); \
+ if (bf_thd) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \
+ if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \
+ WSREP_LOG(sql_print_information, "context: %s:%d", __FILE__, __LINE__); \
}
#define WSREP_PROVIDER_EXISTS \
@@ -231,17 +278,34 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
extern my_bool wsrep_ready_get();
extern void wsrep_ready_wait();
+#ifdef OUT
+enum wsrep_trx_status {
+ WSREP_TRX_OK,
+ WSREP_TRX_CERT_FAIL, /* certification failure, must abort */
+ WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */
+ WSREP_TRX_ERROR, /* native mysql error */
+};
+#endif
+static inline
+wsrep_status_t wsrep_trx_status_to_wsrep_status(wsrep_trx_status status)
+{
+ switch (status)
+ {
+ case WSREP_TRX_OK:
+ return WSREP_OK;
+ case WSREP_TRX_CERT_FAIL:
+ case WSREP_TRX_ERROR:
+ return WSREP_TRX_FAIL;
+ case WSREP_TRX_SIZE_EXCEEDED:
+ return WSREP_SIZE_EXCEEDED;
+ }
+ return WSREP_NOT_IMPLEMENTED;
+}
+
class Ha_trx_info;
struct THD_TRANS;
-void wsrep_register_hton(THD* thd, bool all);
-void wsrep_brute_force_killer(THD *thd);
-int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id);
-/* this is visible for client build so that innodb plugin gets this */
-typedef struct wsrep_aborting_thd {
- struct wsrep_aborting_thd *next;
- THD *aborting_thd;
-} *wsrep_aborting_thd_t;
+//extern "C" bool wsrep_consistency_check(void *thd_ptr);
extern mysql_mutex_t LOCK_wsrep_ready;
extern mysql_cond_t COND_wsrep_ready;
@@ -249,15 +313,15 @@ extern mysql_mutex_t LOCK_wsrep_sst;
extern mysql_cond_t COND_wsrep_sst;
extern mysql_mutex_t LOCK_wsrep_sst_init;
extern mysql_cond_t COND_wsrep_sst_init;
-extern mysql_mutex_t LOCK_wsrep_rollback;
-extern mysql_cond_t COND_wsrep_rollback;
extern int wsrep_replaying;
extern mysql_mutex_t LOCK_wsrep_replaying;
extern mysql_cond_t COND_wsrep_replaying;
extern mysql_mutex_t LOCK_wsrep_slave_threads;
extern mysql_mutex_t LOCK_wsrep_desync;
+extern mysql_mutex_t LOCK_wsrep_SR_pool;
+extern mysql_mutex_t LOCK_wsrep_SR_store;
+extern mysql_mutex_t LOCK_wsrep_thd_pool;
extern mysql_mutex_t LOCK_wsrep_config_state;
-extern wsrep_aborting_thd_t wsrep_aborting_thd;
extern my_bool wsrep_emulate_bin_log;
extern int wsrep_to_isolation;
#ifdef GTID_SUPPORT
@@ -267,6 +331,9 @@ extern my_bool wsrep_preordered_opt;
extern handlerton *wsrep_hton;
#ifdef HAVE_PSI_INTERFACE
+
+extern PSI_cond_key key_COND_wsrep_thd;
+
extern PSI_mutex_key key_LOCK_wsrep_ready;
extern PSI_mutex_key key_COND_wsrep_ready;
extern PSI_mutex_key key_LOCK_wsrep_sst;
@@ -275,12 +342,18 @@ extern PSI_mutex_key key_LOCK_wsrep_sst_init;
extern PSI_cond_key key_COND_wsrep_sst_init;
extern PSI_mutex_key key_LOCK_wsrep_sst_thread;
extern PSI_cond_key key_COND_wsrep_sst_thread;
-extern PSI_mutex_key key_LOCK_wsrep_rollback;
-extern PSI_cond_key key_COND_wsrep_rollback;
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_mutex_key key_LOCK_wsrep_desync;
+extern PSI_mutex_key key_LOCK_wsrep_SR_pool;
+extern PSI_mutex_key key_LOCK_wsrep_SR_store;
+extern PSI_mutex_key key_LOCK_wsrep_thd_pool;
+extern PSI_mutex_key key_LOCK_wsrep_nbo;
+extern PSI_cond_key key_COND_wsrep_nbo;
+extern PSI_mutex_key key_LOCK_wsrep_global_seqno;
+extern PSI_mutex_key key_LOCK_wsrep_thd_queue;
+extern PSI_cond_key key_COND_wsrep_thd_queue;
extern PSI_file_key key_file_wsrep_gra_log;
#endif /* HAVE_PSI_INTERFACE */
@@ -289,12 +362,141 @@ class Alter_info;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
Alter_info* alter_info = NULL);
+
+void wsrep_begin_nbo_unlock(THD*);
+void wsrep_end_nbo_lock(THD*, const TABLE_LIST *table_list);
+
void wsrep_to_isolation_end(THD *thd);
+
void wsrep_cleanup_transaction(THD *thd);
+bool wsrep_append_SR_keys(THD *thd);
int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len);
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len);
+bool wsrep_stmt_rollback_is_safe(THD* thd);
+
+void wsrep_init_sidno(const wsrep_uuid_t&);
+bool wsrep_node_is_donor();
+bool wsrep_node_is_synced();
+
+// void wsrep_init_schema();
+void wsrep_init_SR();
+void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno);
+int wsrep_replay_from_SR_store(THD*, const wsrep_trx_meta_t&);
+void wsrep_node_uuid(wsrep_uuid_t&);
+
+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);
+
+/*
+ * Helper class for non-blocking operations.
+ */
+class Wsrep_nbo_ctx
+{
+ public:
+ Wsrep_nbo_ctx(const void* buf, size_t buf_len,
+ uint32_t flags, const wsrep_trx_meta_t& meta) :
+ buf_ (0),
+ buf_len_(buf_len),
+ flags_ (flags),
+ meta_ (meta),
+ mutex_ (),
+ cond_ (),
+ ready_ (false),
+ executing_(false),
+ toi_released_(false)
+ {
+ mysql_mutex_init(key_LOCK_wsrep_nbo, &mutex_, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_nbo, &cond_, NULL);
+
+ if ((buf_ = malloc(buf_len_)) == 0) {
+ throw std::exception();
+ }
+ memcpy(buf_, buf, buf_len);
+ }
+
+
+ ~Wsrep_nbo_ctx() {
+ free(buf_);
+ }
+
+ const void* buf() { return buf_; }
+ size_t buf_len() { return buf_len_; }
+ uint32_t flags() { return flags_; }
+ const wsrep_trx_meta_t& meta() { return meta_; }
+
+ void wait_sync()
+ {
+ mysql_mutex_lock(&mutex_);
+ while (ready_ == false)
+ {
+ mysql_cond_wait(&cond_, &mutex_);
+ }
+ mysql_mutex_unlock(&mutex_);
+ }
+
+ void signal()
+ {
+ mysql_mutex_lock(&mutex_);
+ ready_ = true;
+ mysql_cond_signal(&cond_);
+ mysql_mutex_unlock(&mutex_);
+ }
+
+ bool ready() const { return ready_; }
+
+ void set_executing(bool val) { executing_ = val; }
+
+ bool executing() const { return executing_; }
+
+ void set_toi_released(bool val) { toi_released_ = true; }
+
+ bool toi_released() const { return toi_released_; }
+
+ private:
+ void* buf_;
+ size_t buf_len_;
+ uint32_t flags_;
+ wsrep_trx_meta_t meta_;
+ mysql_mutex_t mutex_;
+ mysql_cond_t cond_;
+ bool ready_;
+ bool executing_;
+ bool toi_released_;
+};
+
+/*
+ Convenience macros for determining NBO start and END
+*/
+#define WSREP_NBO_START(flags_) \
+((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \
+ !(flags_ & WSREP_FLAG_TRX_END))
+
+#define WSREP_NBO_END(flags_) \
+ ((flags_ & WSREP_FLAG_ISOLATION) && !(flags_ & WSREP_FLAG_TRX_START) && \
+ (flags_ & WSREP_FLAG_TRX_END))
+
+#define WSREP_TOI(flags_) \
+ ((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \
+ (flags_ & WSREP_FLAG_TRX_END))
+
+typedef struct wsrep_key_arr
+{
+ wsrep_key_t* keys;
+ size_t keys_len;
+} wsrep_key_arr_t;
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka);
+void wsrep_keys_free(wsrep_key_arr_t* key_arr);
+
extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket,
@@ -305,16 +507,33 @@ void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end);
void thd_binlog_rollback_stmt(THD * thd);
void thd_binlog_trx_reset(THD * thd);
-typedef void (*wsrep_thd_processor_fun)(THD *);
-pthread_handler_t start_wsrep_THD(void *arg);
-int wsrep_wait_committing_connections_close(int wait_time);
-void wsrep_close_client_connections(my_bool wait_to_end);
-void wsrep_close_applier(THD *thd);
-void wsrep_close_applier_threads(int count);
-void wsrep_wait_appliers_close(THD *thd);
-void wsrep_kill_mysql(THD *thd);
+typedef void (*wsrep_thd_processor_fun)(THD*, void *);
+class Wsrep_thd_args
+{
+ public:
+ Wsrep_thd_args(wsrep_thd_processor_fun fun, void* args)
+ :
+ fun_ (fun),
+ args_(args)
+ { }
+
+ wsrep_thd_processor_fun fun() { return fun_; }
+
+ void* args() { return args_; }
+
+ private:
+
+ Wsrep_thd_args(const Wsrep_thd_args&);
+ Wsrep_thd_args& operator=(const Wsrep_thd_args&);
+
+ wsrep_thd_processor_fun fun_;
+ void* args_;
+};
+
+void* start_wsrep_THD(void*);
+
void wsrep_close_threads(THD *thd);
-void wsrep_copy_query(THD *thd);
+//void wsrep_copy_query(THD *thd);
bool wsrep_is_show_query(enum enum_sql_command command);
void wsrep_replay_transaction(THD *thd);
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
@@ -323,24 +542,11 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
bool wsrep_node_is_donor();
bool wsrep_node_is_synced();
-typedef struct wsrep_key_arr
-{
- wsrep_key_t* keys;
- size_t keys_len;
-} wsrep_key_arr_t;
-bool wsrep_prepare_keys_for_isolation(THD* thd,
- const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- wsrep_key_arr_t* ka);
-void wsrep_keys_free(wsrep_key_arr_t* key_arr);
-
#define WSREP_BINLOG_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
-#else /* WITH_WSREP */
-
+#ifdef WITH_WSREP_OUT
#define WSREP(T) (0)
#define WSREP_ON (0)
#define WSREP_EMULATE_BINLOG(thd) (0)
@@ -368,5 +574,55 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr);
#define wsrep_thr_deinit() do {} while(0)
#define wsrep_running_threads (0)
#define WSREP_BINLOG_FORMAT(my_format) my_format
-#endif /* WITH_WSREP */
+#endif
+/**
+ * Check if the wsrep provider (ie the Galera library) is capable of
+ * doing streaming replication.
+ * @return true if SR capable
+ */
+bool wsrep_provider_is_SR_capable();
+
+/**
+ * Mark current commit ordered if binlogging is not enabled.
+ *
+ * The purpose of this function is to leave commit order critical
+ * section if binlog is not enabled.
+ *
+ * The function can be called from inside storage engine during commit.
+ * Binlog options are checked inside the function.
+ *
+ * @return Zero in case of success, non-zero in case of failure.
+ */
+int wsrep_ordered_commit_if_no_binlog(THD*, bool);
+
+/**
+ * Commit the current transaction with the
+ * MySQL "Transaction Coordinator Log" (see `class TC_LOG` in sql/log.h).
+ * Calling this function will generate and assign a new wsrep transaction id
+ * for `thd`.
+ * @return WSREP_OK on success or other WSREP_* error code on failure
+ */
+wsrep_status_t wsrep_tc_log_commit(THD* thd);
+
+#include "wsrep_server_state.h"
+// #include "mysql/service_wsrep.h"
+
+/**
+ * Initialize WSREP server instance.
+ *
+ * @return Zero on success, non-zero on error.
+ */
+int wsrep_init_server();
+
+/**
+ * Initialize WSREP globals. This should be done after server initialization
+ * is complete and the server has joined to the cluster.
+ *
+ */
+void wsrep_init_globals();
+
+/**
+ * Deinit and release WSREP resources.
+ */
+void wsrep_deinit_server();
#endif /* WSREP_MYSQLD_H */
diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc
index 92bcc8eda43..8a47597ae65 100644
--- a/sql/wsrep_notify.cc
+++ b/sql/wsrep_notify.cc
@@ -15,6 +15,7 @@
#include "mariadb.h"
#include <mysqld.h>
+#include "wsrep_api.h"
#include "wsrep_priv.h"
#include "wsrep_utils.h"
diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc
new file mode 100644
index 00000000000..dd8095e3843
--- /dev/null
+++ b/sql/wsrep_plugin.cc
@@ -0,0 +1,53 @@
+/* Copyright 2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "wsrep_trans_observer.h"
+#include "wsrep_mysqld.h"
+
+#include <mysql/plugin.h>
+
+static int wsrep_plugin_init(void *p)
+{
+ WSREP_INFO("wsrep_plugin_init()");
+ return 0;
+}
+
+static int wsrep_plugin_deinit(void *p)
+{
+ WSREP_INFO("wsrep_plugin_deinit()");
+ return 0;
+}
+
+struct Mysql_replication wsrep_plugin= {
+ MYSQL_REPLICATION_INTERFACE_VERSION
+};
+
+mysql_declare_plugin(wsrep)
+{
+ MYSQL_REPLICATION_PLUGIN,
+ &wsrep_plugin,
+ "wsrep",
+ "Codership Oy",
+ "Wsrep replication plugin",
+ PLUGIN_LICENSE_GPL,
+ wsrep_plugin_init,
+ wsrep_plugin_deinit,
+ 0x0100,
+ NULL, /* Status variables */
+ NULL, /* System variables */
+ NULL, /* Config options */
+ 0 /* Flags */
+}
+mysql_declare_plugin_end;
diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h
index 222a49cc2ab..65022396cd2 100644
--- a/sql/wsrep_priv.h
+++ b/sql/wsrep_priv.h
@@ -19,6 +19,7 @@
#ifndef WSREP_PRIV_H
#define WSREP_PRIV_H
+#include <my_global.h>
#include "wsrep_mysqld.h"
#include "../wsrep/wsrep_api.h"
@@ -31,21 +32,17 @@ my_bool wsrep_ready_set (my_bool x);
ssize_t wsrep_sst_prepare (void** msg);
wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx,
void* recv_ctx,
- const void* msg, size_t msg_len,
+ const wsrep_buf_t* msg,
const wsrep_gtid_t* state_id,
- const char* state, size_t state_len,
+ const wsrep_buf_t* state,
bool bypass);
extern wsrep_uuid_t local_uuid;
extern wsrep_seqno_t local_seqno;
// a helper function
-bool wsrep_sst_received (wsrep_t* const wsrep,
- const wsrep_uuid_t& uuid,
- const wsrep_seqno_t seqno,
- const void* const state,
- const size_t state_len,
- const bool implicit);
+void wsrep_sst_received(THD*, const wsrep_uuid_t&, wsrep_seqno_t,
+ const void*, size_t);
/*! SST thread signals init thread about sst completion */
void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool);
diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc
new file mode 100644
index 00000000000..f209e1c8812
--- /dev/null
+++ b/sql/wsrep_schema.cc
@@ -0,0 +1,1319 @@
+/* Copyright (C) 2015-2017 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "mariadb.h"
+
+#include "table.h"
+#include "key.h"
+#include "sql_base.h"
+#include "sql_parse.h"
+#include "sql_update.h"
+#include "transaction.h"
+
+#include "mysql/service_wsrep.h"
+#include "wsrep_thd_pool.h"
+#include "wsrep_schema.h"
+#include "wsrep_applier.h"
+#include "wsrep_xid.h"
+#include "wsrep_binlog.h"
+#include "wsrep_high_priority_service.h"
+#include "wsrep_storage_service.h"
+
+#include <string>
+#include <sstream>
+
+
+const std::string wsrep_schema_str= "wsrep_schema";
+static const std::string create_wsrep_schema_str=
+ "CREATE DATABASE IF NOT EXISTS wsrep_schema";
+
+static const std::string create_cluster_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.cluster"
+ "("
+ "cluster_uuid CHAR(36) PRIMARY KEY,"
+ "view_id BIGINT NOT NULL,"
+ "view_seqno BIGINT NOT NULL,"
+ "protocol_version INT NOT NULL"
+ ") ENGINE=InnoDB";
+
+static const std::string create_members_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.members"
+ "("
+ "node_uuid CHAR(36) PRIMARY KEY,"
+ "cluster_uuid CHAR(36) NOT NULL,"
+ "node_name CHAR(32) NOT NULL,"
+ "node_incoming_address VARCHAR(256) NOT NULL"
+ ") ENGINE=InnoDB";
+
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+static const std::string create_members_history_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.members_history"
+ "("
+ "node_uuid CHAR(36) PRIMARY KEY,"
+ "cluster_uuid CHAR(36) NOT NULL,"
+ "last_view_id BIGINT NOT NULL,"
+ "last_view_seqno BIGINT NOT NULL,"
+ "node_name CHAR(32) NOT NULL,"
+ "node_incoming_address VARCHAR(256) NOT NULL"
+ ") ENGINE=InnoDB";
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+
+static const std::string sr_table_str= "SR";
+const std::string sr_table_name_full_str= wsrep_schema_str + "/" + sr_table_str;
+static const std::string create_frag_table_str=
+ "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + sr_table_str +
+ "("
+ "node_uuid CHAR(36), "
+ "trx_id BIGINT, "
+ "seqno BIGINT, "
+ "flags INT NOT NULL, "
+ "frag LONGBLOB NOT NULL, "
+ "PRIMARY KEY (node_uuid, trx_id, seqno)"
+ ") ENGINE=InnoDB";
+
+static const std::string delete_from_cluster_table=
+ "DELETE FROM wsrep_schema.cluster";
+
+static const std::string delete_from_members_table=
+ "DELETE FROM wsrep_schema.members";
+
+
+namespace Wsrep_schema_impl
+{
+
+class binlog_off
+{
+public:
+ binlog_off(THD* thd)
+ : m_thd(thd)
+ , m_option_bits(thd->variables.option_bits)
+ , m_sql_log_bin(thd->variables.sql_log_bin)
+ {
+ thd->variables.option_bits&= ~OPTION_BIN_LOG;
+ thd->variables.sql_log_bin= 0;
+ }
+ ~binlog_off()
+ {
+ m_thd->variables.option_bits= m_option_bits;
+ m_thd->variables.sql_log_bin= m_sql_log_bin;
+ }
+private:
+ THD* m_thd;
+ ulonglong m_option_bits;
+ my_bool m_sql_log_bin;
+};
+
+class wsrep_off
+{
+public:
+ wsrep_off(THD* thd)
+ : m_thd(thd)
+ , m_wsrep_on(thd->variables.wsrep_on)
+ {
+ thd->variables.wsrep_on= 0;
+ }
+ ~wsrep_off()
+ {
+ m_thd->variables.wsrep_on= m_wsrep_on;
+ }
+private:
+ THD* m_thd;
+ my_bool m_wsrep_on;
+};
+
+static int execute_SQL(THD* thd, const char* sql, uint length) {
+ DBUG_ENTER("Wsrep_schema::execute_SQL()");
+ int err= 0;
+
+ PSI_statement_locker *parent_locker= thd->m_statement_psi;
+ Parser_state parser_state;
+
+ WSREP_DEBUG("SQL: %d %s thd: %lld", length, sql, (long long)thd->thread_id);
+
+ if (parser_state.init(thd, (char*)sql, length) == 0) {
+ thd->reset_for_next_command();
+ lex_start(thd);
+
+ thd->m_statement_psi= NULL;
+
+ thd->set_query((char*)sql, length);
+ thd->set_query_id(next_query_id());
+
+ mysql_parse(thd, (char*)sql, length, & parser_state, FALSE, FALSE);
+
+ if (thd->is_error()) {
+ WSREP_WARN("Wsrep_schema::execute_sql() failed, %d %s\nSQL: %s",
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message(),
+ sql);
+ err= 1;
+ }
+ thd->m_statement_psi= parent_locker;
+ thd->end_statement();
+ thd->reset_query();
+ close_thread_tables(thd);
+ delete_explain_query(thd->lex);
+ }
+ else {
+ WSREP_WARN("SR init failure");
+ }
+ thd->cleanup_after_query();
+ DBUG_RETURN(err);
+}
+
+/*
+ Initialize thd for next "statement"
+ */
+static void init_stmt(THD* thd) {
+ lex_start(thd);
+ thd->reset_for_next_command();
+}
+
+static void finish_stmt(THD* thd) {
+ trans_commit_stmt(thd);
+ thd->lex->unit.cleanup();
+ close_thread_tables(thd);
+}
+
+static int open_table(THD* thd,
+ const LEX_CSTRING *schema_name,
+ const LEX_CSTRING *table_name,
+ enum thr_lock_type const lock_type,
+ TABLE** table) {
+ assert(table);
+ *table= NULL;
+
+ DBUG_ENTER("Wsrep_schema::open_table()");
+
+ TABLE_LIST tables;
+ uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |
+ MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_LOCK_IGNORE_TIMEOUT);
+
+ tables.init_one_table(schema_name,
+ table_name,
+ NULL, lock_type);
+
+ if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) {
+ close_thread_tables(thd);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), schema_name->str, table_name->str);
+ DBUG_RETURN(1);
+ }
+
+ *table= tables.table;
+ (*table)->use_all_columns();
+
+ DBUG_RETURN(0);
+}
+
+
+static int open_for_write(THD* thd, const char* table_name, TABLE** table) {
+ // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) };
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { table_name, strlen(table_name) };
+ if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_WRITE,
+ table)) {
+ WSREP_ERROR("Failed to open table %s.%s for writing",
+ schema_str.str, table_name);
+ return 1;
+ }
+ empty_record(*table);
+ (*table)->use_all_columns();
+ restore_record(*table, s->default_values);
+ return 0;
+}
+
+static void store(TABLE* table, uint field, const Wsrep_id& id) {
+ assert(field < table->s->fields);
+ std::ostringstream os;
+ os << id;
+ table->field[field]->store(os.str().c_str(),
+ os.str().size(),
+ &my_charset_bin);
+}
+
+
+template <typename INTTYPE>
+static void store(TABLE* table, uint field, const INTTYPE val) {
+ assert(field < table->s->fields);
+ table->field[field]->store(val);
+}
+
+template <typename CHARTYPE>
+static void store(TABLE* table, uint field, const CHARTYPE* str, size_t str_len) {
+ assert(field < table->s->fields);
+ table->field[field]->store((const char*)str,
+ str_len,
+ &my_charset_bin);
+}
+
+static void store(TABLE* table, uint field, const std::string& str)
+{
+ store(table, field, str.c_str(), str.size());
+}
+
+static int update_or_insert(TABLE* table) {
+ DBUG_ENTER("Wsrep_schema::update_or_insert()");
+ int ret= 0;
+ char* key;
+ int error;
+
+ /*
+ Verify that the table has primary key defined.
+ */
+ if (table->s->primary_key >= MAX_KEY ||
+ !table->s->keys_in_use.is_set(table->s->primary_key)) {
+ WSREP_ERROR("No primary key for %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ Find the record and update or insert a new one if not found.
+ */
+ if (!(key= (char*) my_safe_alloca(table->s->max_unique_length))) {
+ WSREP_ERROR("Error allocating %ud bytes for key",
+ table->s->max_unique_length);
+ DBUG_RETURN(1);
+ }
+
+ key_copy((uchar*) key, table->record[0],
+ table->key_info + table->s->primary_key, 0);
+
+ if ((error= table->file->ha_index_read_idx_map(table->record[1],
+ table->s->primary_key,
+ (uchar*) key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))) {
+ /*
+ Row not found, insert a new one.
+ */
+ if ((error= table->file->ha_write_row(table->record[0]))) {
+ WSREP_ERROR("Error writing into %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+ }
+ else if (!records_are_comparable(table) || compare_record(table)) {
+ /*
+ Record has changed
+ */
+ if ((error= table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME) {
+ WSREP_ERROR("Error updating record in %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+ }
+
+ my_safe_afree(key, table->s->max_unique_length);
+
+ DBUG_RETURN(ret);
+}
+
+static int insert(TABLE* table) {
+ DBUG_ENTER("Wsrep_schema::insert()");
+ int ret= 0;
+ int error;
+
+ /*
+ Verify that the table has primary key defined.
+ */
+ if (table->s->primary_key >= MAX_KEY ||
+ !table->s->keys_in_use.is_set(table->s->primary_key)) {
+ WSREP_ERROR("No primary key for %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ DBUG_RETURN(1);
+ }
+
+ if ((error= table->file->ha_write_row(table->record[0]))) {
+ WSREP_ERROR("Error writing into %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+
+ DBUG_RETURN(ret);
+}
+
+static int delete_row(TABLE* table) {
+ int error;
+ int retry= 3;
+
+ do {
+ error= table->file->ha_delete_row(table->record[0]);
+ retry--;
+ } while (error && retry);
+
+ if (error) {
+ WSREP_ERROR("Error deleting row from %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ return 1;
+ }
+ return 0;
+}
+
+static int open_for_read(THD* thd, const char* table_name, TABLE** table) {
+ // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) };
+
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { table_name, strlen(table_name) };
+ if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_READ,
+ table)) {
+ WSREP_ERROR("Failed to open table %s.%s for reading",
+ schema_str.str, table_name);
+ return 1;
+ }
+ empty_record(*table);
+ (*table)->use_all_columns();
+ restore_record(*table, s->default_values);
+ return 0;
+}
+
+/*
+ Init table for sequential scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int init_for_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_init(TRUE))) {
+ WSREP_ERROR("Failed to init table for scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+/*
+ Scan next record. For return codes see handler::ha_rnd_next()
+
+ @return 0 in case of success, error code in case of error
+ */
+static int next_record(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_next(table->record[0])) &&
+ error != HA_ERR_END_OF_FILE) {
+ WSREP_ERROR("Failed to read next record: %d", error);
+ }
+ return error;
+}
+
+/*
+ End scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int end_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_end())) {
+ WSREP_ERROR("Failed to end scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ Scan wsrep uuid from given field.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int scan(TABLE* table, uint field, wsrep_uuid_t& uuid)
+{
+ assert(field < table->s->fields);
+ int error;
+ String uuid_str;
+ (void)table->field[field]->val_str(&uuid_str);
+ if ((error= wsrep_uuid_scan((const char*)uuid_str.c_ptr(),
+ uuid_str.length(),
+ &uuid) < 0)) {
+ WSREP_ERROR("Failed to scan uuid: %d", -error);
+ return 1;
+ }
+ return 0;
+}
+
+static int scan(TABLE* table, uint field, wsrep::id& id)
+{
+ assert(field < table->s->fields);
+ String uuid_str;
+ (void)table->field[field]->val_str(&uuid_str);
+ id = wsrep::id(std::string(uuid_str.c_ptr(), uuid_str.length()));
+ return 0;
+}
+
+template <typename INTTYPE>
+static int scan(TABLE* table, uint field, INTTYPE& val)
+{
+ assert(field < table->s->fields);
+ val= table->field[field]->val_int();
+ return 0;
+}
+
+static int scan(TABLE* table, uint field, char* strbuf, uint strbuf_len)
+{
+ String str;
+ (void)table->field[field]->val_str(&str);
+ strncpy(strbuf, str.c_ptr(), std::min(str.length(), strbuf_len));
+ strbuf[strbuf_len - 1] = '\0';
+ return 0;
+}
+
+/*
+ Scan member
+ TODO: filter members by cluster UUID
+ */
+static int scan_member(TABLE* table,
+ wsrep_uuid_t const cluster_uuid,
+ std::vector<wsrep_member_info_t>& members)
+{
+ wsrep_member_info_t member;
+
+ memset(&member, 0, sizeof(member));
+
+ if (scan(table, 0, member.id) ||
+ scan(table, 2, member.name, sizeof(member.name)) ||
+ scan(table, 3, member.incoming, sizeof(member.incoming))) {
+ return 1;
+ }
+
+ if (members.empty() == false) {
+ assert(memcmp(&members.rbegin()->id, &member.id, sizeof(member.id)) < 0);
+ }
+
+ try {
+ members.push_back(member);
+ }
+ catch (...) {
+ WSREP_ERROR("Caught exception while scanning members table");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ Init table for index scan and retrieve first record
+
+ @return 0 in case of success, error code in case of error.
+ */
+static int init_for_index_scan(TABLE* table, const uchar* key,
+ key_part_map map) {
+ int error;
+ if ((error= table->file->ha_index_init(table->s->primary_key, true))) {
+ WSREP_ERROR("Failed to init table for index scan: %d", error);
+ return error;
+ }
+
+ error= table->file->ha_index_read_map(table->record[0],
+ key, map, HA_READ_KEY_EXACT);
+ switch(error) {
+ case 0:
+ case HA_ERR_END_OF_FILE:
+ case HA_ERR_KEY_NOT_FOUND:
+ break;
+ case -1:
+ WSREP_DEBUG("init_for_index_scan interrupted");
+ break;
+ default:
+ WSREP_ERROR("init_for_index_scan failed to read first record, error %d", error);
+ }
+ return error;
+}
+
+/*
+ Scan next index record. For return codes see handler::ha_index_next()
+
+ @return 0 in case of success, error code in case of error
+ */
+/*
+static int next_index_record(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_index_next(table->record[0])) &&
+ error != HA_ERR_END_OF_FILE) {
+ WSREP_ERROR("Failed to read next record: %d", error);
+ }
+ return error;
+}
+*/
+/*
+ End index scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int end_index_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_index_end())) {
+ WSREP_ERROR("Failed to end scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+
+static void make_key(TABLE* table, uchar* key, key_part_map* map, int parts) {
+ uint prefix_length= 0;
+ KEY_PART_INFO* key_part= table->key_info->key_part;
+ for (int i=0; i < parts; i++)
+ prefix_length += key_part[i].store_length;
+ *map = make_prev_keypart_map(parts);
+ key_copy(key, table->record[0], table->key_info, prefix_length);
+}
+} /* namespace Wsrep_schema_impl */
+
+
+Wsrep_schema::Wsrep_schema(Wsrep_thd_pool* thd_pool)
+ :
+ thd_pool_(thd_pool)
+{
+ assert(thd_pool_);
+}
+
+Wsrep_schema::~Wsrep_schema()
+{ }
+
+int Wsrep_schema::init()
+{
+ DBUG_ENTER("Wsrep_schema::init()");
+ int ret;
+ THD* thd= thd_pool_->get_thd(0);
+ if (!thd) {
+ WSREP_ERROR("Unable to get thd");
+ DBUG_RETURN(1);
+ }
+
+ if (Wsrep_schema_impl::execute_SQL(thd, create_wsrep_schema_str.c_str(),
+ create_wsrep_schema_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd, create_cluster_table_str.c_str(),
+ create_cluster_table_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd, create_members_table_str.c_str(),
+ create_members_table_str.size()) ||
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ Wsrep_schema_impl::execute_SQL(thd,
+ create_members_history_table_str.c_str(),
+ create_members_history_table_str.size()) ||
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+ Wsrep_schema_impl::execute_SQL(thd,
+ create_frag_table_str.c_str(),
+ create_frag_table_str.size())) {
+ ret= 1;
+ }
+ else {
+ ret= 0;
+ }
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view)
+{
+ DBUG_ENTER("Wsrep_schema::store_view()");
+ assert(view.status() == Wsrep_view::primary);
+ int ret= 1;
+ int error;
+ TABLE* cluster_table= 0;
+ TABLE* members_table= 0;
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ TABLE* members_history_table= 0;
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+
+ Wsrep_schema_impl::wsrep_off wsrep_off(thd);
+ Wsrep_schema_impl::binlog_off binlog_off(thd);
+
+ /*
+ Clean up cluster table and members table.
+ */
+ if (Wsrep_schema_impl::execute_SQL(thd,
+ delete_from_cluster_table.c_str(),
+ delete_from_cluster_table.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ delete_from_members_table.c_str(),
+ delete_from_members_table.size())) {
+ goto out;
+ }
+
+ /*
+ Store cluster view info
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "cluster", &cluster_table))
+ {
+ goto out;
+ }
+
+ Wsrep_schema_impl::store(cluster_table, 0, view.state_id().id());
+ Wsrep_schema_impl::store(cluster_table, 1, view.view_seqno().get());
+ Wsrep_schema_impl::store(cluster_table, 2, view.state_id().seqno().get());
+ Wsrep_schema_impl::store(cluster_table, 3, view.protocol_version());
+
+ if ((error= Wsrep_schema_impl::update_or_insert(cluster_table)))
+ {
+ WSREP_ERROR("failed to write to cluster table: %d", error);
+ goto out;
+ }
+
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ /*
+ Store info about current members
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "members", &members_table))
+ {
+ WSREP_ERROR("failed to open wsrep.members table");
+ goto out;
+ }
+
+ for (size_t i= 0; i < view.members().size(); ++i)
+ {
+ Wsrep_schema_impl::store(members_table, 0, view.members()[i].id());
+ Wsrep_schema_impl::store(members_table, 1, view.state_id().id());
+ Wsrep_schema_impl::store(members_table, 2,
+ view.members()[i].name());
+ Wsrep_schema_impl::store(members_table, 3, view.members()[i].incoming());
+ if ((error= Wsrep_schema_impl::update_or_insert(members_table)))
+ {
+ WSREP_ERROR("failed to write wsrep.members table: %d", error);
+ goto out;
+ }
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ /*
+ Store members history
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "members_history",
+ &members_history_table)) {
+ WSREP_ERROR("failed to open wsrep.members table");
+ goto out;
+ }
+
+ for (int i= 0; i < view->memb_num; ++i) {
+ Wsrep_schema_impl::store(members_history_table, 0, view->members[i].id);
+ Wsrep_schema_impl::store(members_history_table, 1, view->state_id.uuid);
+ Wsrep_schema_impl::store(members_history_table, 2, view->view);
+ Wsrep_schema_impl::store(members_history_table, 3,
+ view->state_id.seqno);
+ Wsrep_schema_impl::store(members_history_table, 4,
+ view->members[i].name,
+ strlen(view->members[i].name));
+ Wsrep_schema_impl::store(members_history_table, 5,
+ view->members[i].incoming,
+ strlen(view->members[i].incoming));
+ if ((error= Wsrep_schema_impl::update_or_insert(members_history_table))) {
+ WSREP_ERROR("failed to write wsrep.members table: %d", error);
+ goto out;
+ }
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+ ret= 0;
+ out:
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::restore_view(const wsrep_uuid_t& node_uuid,
+ wsrep_view_info_t** view_info) const {
+ DBUG_ENTER("Wsrep_schema::restore_view()");
+ assert(view_info);
+ int ret= 1;
+ int error;
+ THD* thd= thd_pool_->get_thd(0);
+
+ TABLE* cluster_table= 0;
+ TABLE* members_table=0;
+
+ wsrep_uuid_t cluster_uuid;
+ wsrep_seqno_t view_id;
+ wsrep_seqno_t view_seqno;
+ int my_idx= -1;
+ int proto_ver;
+ std::vector<wsrep_member_info_t> members;
+
+ if (!thd) {
+ WSREP_ERROR("Failed to allocate THD for restore view");
+ DBUG_RETURN(1);
+ }
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) {
+ WSREP_ERROR("Failed to start transaction");
+ goto out;
+ }
+
+ /*
+ Read cluster info from cluster table
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "cluster", &cluster_table) ||
+ Wsrep_schema_impl::init_for_scan(cluster_table) ||
+ Wsrep_schema_impl::next_record(cluster_table) ||
+ Wsrep_schema_impl::scan(cluster_table, 0, cluster_uuid) ||
+ Wsrep_schema_impl::scan(cluster_table, 1, view_id) ||
+ Wsrep_schema_impl::scan(cluster_table, 2, view_seqno) ||
+ Wsrep_schema_impl::scan(cluster_table, 3, proto_ver) ||
+ Wsrep_schema_impl::end_scan(cluster_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ /*
+ Read members from members table
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "members", &members_table) ||
+ Wsrep_schema_impl::init_for_scan(members_table)) {
+ goto out;
+ }
+
+ while (true) {
+ if ((error= Wsrep_schema_impl::next_record(members_table)) == 0) {
+ if (Wsrep_schema_impl::scan_member(members_table,
+ cluster_uuid,
+ members)) {
+ goto out;
+ }
+ }
+ else if (error == HA_ERR_END_OF_FILE) {
+ break;
+ }
+ else {
+ goto out;
+ }
+ }
+
+ if (Wsrep_schema_impl::end_scan(members_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ for (uint i= 0; i < members.size(); ++i) {
+ if (memcmp(&members[i].id, &node_uuid, sizeof(node_uuid)) == 0) {
+ my_idx= i;
+ }
+ }
+
+ *view_info= (wsrep_view_info_t*)
+ malloc(sizeof(wsrep_view_info_t)
+ + members.size() * sizeof(wsrep_member_info_t));
+ if (!view_info) {
+ WSREP_ERROR("Failed to allocate memory for view info");
+ goto out;
+ }
+
+ (*view_info)->state_id.uuid= cluster_uuid;
+ (*view_info)->state_id.seqno= view_seqno;
+ (*view_info)->view= view_id;
+ (*view_info)->status= WSREP_VIEW_PRIMARY;
+ (*view_info)->my_idx= my_idx;
+ (*view_info)->proto_ver= proto_ver;
+ (*view_info)->memb_num= members.size();
+ std::copy(members.begin(), members.end(), (*view_info)->members);
+
+ (void)trans_commit(thd);
+ ret= 0; /* Success*/
+ out:
+
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::append_fragment(THD* thd,
+ const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ wsrep::seqno seqno,
+ int flags,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_schema::append_fragment");
+ std::ostringstream os;
+ os << server_id;
+ WSREP_DEBUG("Append fragment(%llu) %s, %llu",
+ thd->thread_id,
+ os.str().c_str(),
+ transaction_id.get());
+ Wsrep_schema_impl::binlog_off binlog_off(thd);
+ Wsrep_schema_impl::init_stmt(thd);
+
+ TABLE* frag_table= 0;
+ if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table))
+ {
+ trans_rollback_stmt(thd);
+ DBUG_RETURN(1);
+ }
+
+ Wsrep_schema_impl::store(frag_table, 0, server_id);
+ Wsrep_schema_impl::store(frag_table, 1, transaction_id.get());
+ Wsrep_schema_impl::store(frag_table, 2, seqno.get());
+ Wsrep_schema_impl::store(frag_table, 3, flags);
+ Wsrep_schema_impl::store(frag_table, 4, data.data(), data.size());
+
+ int error;
+ if ((error= Wsrep_schema_impl::insert(frag_table))) {
+ WSREP_ERROR("Failed to write to frag table: %d", error);
+ trans_rollback_stmt(thd);
+ DBUG_RETURN(1);
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(0);
+}
+
+int Wsrep_schema::update_fragment_meta(THD* thd,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_schema::update_fragment_meta");
+ std::ostringstream os;
+ os << ws_meta.server_id();
+ WSREP_DEBUG("update_frag_seqno(%llu) %s, %llu, seqno %lld",
+ thd->thread_id,
+ os.str().c_str(),
+ ws_meta.transaction_id().get(),
+ ws_meta.seqno().get());
+ DBUG_ASSERT(ws_meta.seqno().is_undefined() == false);
+
+ Wsrep_schema_impl::binlog_off binlog_off(thd);
+ int error;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+ TABLE* frag_table= 0;
+
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table))
+ {
+ DBUG_RETURN(1);
+ }
+
+ /* Find record with the given uuid, trx id, and seqno -1 */
+ Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
+ Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
+ Wsrep_schema_impl::store(frag_table, 2, -1);
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
+ key, key_map)))
+ {
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
+ {
+ WSREP_WARN("Record not found in %s.%s: %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ error);
+ }
+ frag_table->file->print_error(error, MYF(0));
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(1);
+ }
+
+ /* Copy the original record to frag_table->record[1] */
+ store_record(frag_table, record[1]);
+
+ /* Store seqno in frag_table->record[0] and update the row */
+ Wsrep_schema_impl::store(frag_table, 2, ws_meta.seqno().get());
+ if ((error= frag_table->file->ha_update_row(frag_table->record[1],
+ frag_table->record[0]))) {
+ WSREP_ERROR("Error updating record in %s.%s: %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ error);
+ frag_table->file->print_error(error, MYF(0));
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(1);
+ }
+
+ int ret= Wsrep_schema_impl::end_index_scan(frag_table);
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(ret);
+}
+
+static int remove_fragment(THD* thd,
+ TABLE* frag_table,
+ const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ wsrep::seqno seqno)
+{
+ WSREP_DEBUG("remove_fragment(%llu) trx %llu, seqno %lld",
+ thd->thread_id,
+ transaction_id.get(),
+ seqno.get());
+ int ret= 0;
+ int error;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+
+ DBUG_ASSERT(server_id.is_undefined() == false);
+ DBUG_ASSERT(transaction_id.is_undefined() == false);
+ DBUG_ASSERT(seqno.is_undefined() == false);
+
+ /*
+ Remove record with the given uuid, trx id, and seqno.
+ Using a complete key here avoids gap locks.
+ */
+ Wsrep_schema_impl::store(frag_table, 0, server_id);
+ Wsrep_schema_impl::store(frag_table, 1, transaction_id.get());
+ Wsrep_schema_impl::store(frag_table, 2, seqno.get());
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
+ key,
+ key_map)))
+ {
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
+ {
+ WSREP_DEBUG("Record not found in %s.%s:trx %llu, seqno %lld, error %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ transaction_id.get(),
+ seqno.get(),
+ error);
+ }
+ frag_table->file->print_error(error, MYF(0));
+ ret= error;
+ }
+ else if (Wsrep_schema_impl::delete_row(frag_table))
+ {
+ ret= 1;
+ }
+
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ return ret;
+}
+
+int Wsrep_schema::remove_fragments(THD* thd,
+ const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ const std::vector<wsrep::seqno>& fragments)
+{
+ DBUG_ENTER("Wsrep_schema::remove_fragments");
+ int ret= 0;
+
+ Wsrep_schema_impl::wsrep_off wsrep_off(thd);
+ Wsrep_schema_impl::binlog_off binlog_off(thd);
+
+ /*
+ Open SR table for write.
+ Adopted from Rpl_info_table_access::open_table()
+ */
+ uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |
+ MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_LOCK_IGNORE_TIMEOUT);
+ Query_tables_list query_tables_list_backup;
+ Open_tables_backup open_tables_backup;
+ thd->lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
+ thd->reset_n_backup_open_tables_state(&open_tables_backup);
+ TABLE_LIST tables;
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { "SR", strlen("SR") };
+ tables.init_one_table(&schema_str,
+ &table_str, 0, TL_WRITE);
+
+ if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags))
+ {
+ WSREP_DEBUG("Failed to open SR table for access");
+ ret= 1;
+ }
+ else
+ {
+ tables.table->use_all_columns();
+ for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin();
+ i != fragments.end(); ++i)
+ {
+ if (remove_fragment(thd,
+ tables.table,
+ server_id,
+ transaction_id, *i))
+ {
+ ret= 1;
+ break;
+ }
+ }
+ }
+ close_thread_tables(thd);
+ thd->restore_backup_open_tables_state(&open_tables_backup);
+ thd->lex->restore_backup_query_tables_list(&query_tables_list_backup);
+
+ if (thd->wsrep_cs().mode() == wsrep::client_state::m_local &&
+ !thd->in_multi_stmt_transaction_mode())
+ {
+ /*
+ The ugly part: Locally executing autocommit statement is
+ committing and it has removed a fragment from stable storage.
+ Now calling finish_stmt() will call trans_commit_stmt(), which will
+ actually commit the transaction, what we really don't want
+ to do at this point.
+
+ Doing nothing at this point seems to work ok, this block is
+ intentionally no-op and for documentation purposes only.
+ */
+ }
+ else
+ {
+ Wsrep_schema_impl::finish_stmt(thd);
+ }
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::replay_transaction(THD* thd,
+ Relay_log_info* rli,
+ const wsrep::ws_meta& ws_meta,
+ const std::vector<wsrep::seqno>& fragments)
+{
+ DBUG_ENTER("Wsrep_schema::replay_transaction");
+ DBUG_ASSERT(!fragments.empty());
+
+ Wsrep_schema_impl::wsrep_off wsrep_off(thd);
+ Wsrep_schema_impl::binlog_off binlog_off(thd);
+
+ int ret= 1;
+ int error;
+ TABLE* frag_table= 0;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+
+ for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin();
+ i != fragments.end(); ++i)
+ {
+ Wsrep_schema_impl::init_stmt(thd);
+ if ((error= Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table)))
+ {
+ WSREP_WARN("Could not open SR table for read: %d", error);
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(1);
+ }
+
+ Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
+ Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
+ Wsrep_schema_impl::store(frag_table, 2, i->get());
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ int error= Wsrep_schema_impl::init_for_index_scan(frag_table,
+ key,
+ key_map);
+ if (error)
+ {
+ frag_table->file->print_error(error, MYF(0));
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ ret= 1;
+ break;
+ }
+
+ int flags;
+ Wsrep_schema_impl::scan(frag_table, 3, flags);
+ WSREP_DEBUG("replay_fragment(%llu): seqno: %lld flags: %x",
+ ws_meta.transaction_id().get(),
+ i->get(),
+ flags);
+ String buf;
+ frag_table->field[4]->val_str(&buf);
+
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ Wsrep_schema_impl::finish_stmt(thd);
+ ret= wsrep_apply_events(thd, rli, buf.c_ptr_safe(), buf.length());
+ if (ret)
+ {
+ WSREP_WARN("Wsrep_schema::replay_transaction: failed to apply fragments");
+ break;
+ }
+ Wsrep_schema_impl::init_stmt(thd);
+
+ if ((error= Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)))
+ {
+ WSREP_WARN("Could not open SR table for read: %d", error);
+ Wsrep_schema_impl::finish_stmt(thd);
+ DBUG_RETURN(1);
+ }
+ error= Wsrep_schema_impl::init_for_index_scan(frag_table,
+ key,
+ key_map);
+ if (error)
+ {
+ frag_table->file->print_error(error, MYF(0));
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ ret= 1;
+ break;
+ }
+
+ error= Wsrep_schema_impl::delete_row(frag_table);
+ if (error)
+ {
+ frag_table->file->print_error(error, MYF(0));
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ ret= 1;
+ break;
+ }
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ Wsrep_schema_impl::finish_stmt(thd);
+ }
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::recover_sr_transactions()
+{
+ DBUG_ENTER("Wsrep_schema::recover_sr_transactions");
+ THD storage_thd(true, true);
+ storage_thd.thread_stack= (char*)&storage_thd;
+ TABLE* frag_table= 0;
+ TABLE* cluster_table= 0;
+ Wsrep_storage_service storage_service(&storage_thd);
+ Wsrep_schema_impl::binlog_off binlog_off(&storage_thd);
+ Wsrep_schema_impl::wsrep_off binglog_off(&storage_thd);
+
+ Wsrep_server_state& server_state(Wsrep_server_state::instance());
+
+ int ret= 1;
+ int error;
+ wsrep::id cluster_id;
+
+ storage_thd.store_globals();
+ Wsrep_schema_impl::init_stmt(&storage_thd);
+ storage_thd.wsrep_skip_locking= FALSE;
+ if (Wsrep_schema_impl::open_for_read(&storage_thd,
+ "cluster", &cluster_table) ||
+ Wsrep_schema_impl::init_for_scan(cluster_table))
+ {
+ Wsrep_schema_impl::finish_stmt(&storage_thd);
+ DBUG_RETURN(1);
+ }
+
+ if ((error= Wsrep_schema_impl::next_record(cluster_table)))
+ {
+ Wsrep_schema_impl::end_scan(cluster_table);
+ Wsrep_schema_impl::finish_stmt(&storage_thd);
+ trans_commit(&storage_thd);
+ if (error == HA_ERR_END_OF_FILE)
+ {
+ WSREP_INFO("Cluster table is empty, not recovering transactions");
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ WSREP_ERROR("Failed to read cluster table: %d", error);
+ DBUG_RETURN(1);
+ }
+ }
+
+ Wsrep_schema_impl::scan(cluster_table, 0, cluster_id);
+ Wsrep_schema_impl::end_scan(cluster_table);
+ Wsrep_schema_impl::finish_stmt(&storage_thd);
+
+ std::ostringstream os;
+ os << cluster_id;
+ WSREP_INFO("Recovered cluster id %s", os.str().c_str());
+
+ storage_thd.wsrep_skip_locking= TRUE;
+ Wsrep_schema_impl::init_stmt(&storage_thd);
+ if (Wsrep_schema_impl::open_for_read(&storage_thd, "SR", &frag_table) ||
+ Wsrep_schema_impl::init_for_scan(frag_table))
+ {
+ WSREP_ERROR("Failed to open SR table for read");
+ goto out;
+ }
+
+ while (true)
+ {
+ if ((error= Wsrep_schema_impl::next_record(frag_table)) == 0)
+ {
+ wsrep::id server_id;
+ Wsrep_schema_impl::scan(frag_table, 0, server_id);
+ wsrep::client_id client_id;
+ unsigned long long transaction_id_ull;
+ Wsrep_schema_impl::scan(frag_table, 1, transaction_id_ull);
+ wsrep::transaction_id transaction_id(transaction_id_ull);
+ long long seqno_ll;
+ Wsrep_schema_impl::scan(frag_table, 2, seqno_ll);
+ wsrep::seqno seqno(seqno_ll);
+
+ if (seqno.is_undefined())
+ {
+ Wsrep_schema_impl::delete_row(frag_table);
+ continue;
+ }
+
+ wsrep::gtid gtid(cluster_id, seqno);
+ int flags;
+ Wsrep_schema_impl::scan(frag_table, 3, flags);
+ String data_str;
+
+ (void)frag_table->field[4]->val_str(&data_str);
+ wsrep::const_buffer data(data_str.c_ptr(), data_str.length());
+ wsrep::ws_meta ws_meta(gtid,
+ wsrep::stid(server_id,
+ transaction_id,
+ client_id),
+ wsrep::seqno::undefined(),
+ flags);
+
+ wsrep::high_priority_service* applier;
+ if (!(applier = server_state.find_streaming_applier(server_id,
+ transaction_id)))
+ {
+ DBUG_ASSERT(wsrep::starts_transaction(flags));
+ THD* thd= new THD(true, true);
+ thd->thread_stack= (char*)&storage_thd;
+
+ mysql_mutex_lock(&LOCK_thread_count);
+ thd->thread_id= next_thread_id();
+ thd->real_id= pthread_self();
+ mysql_mutex_unlock(&LOCK_thread_count);
+
+ applier= new Wsrep_applier_service(thd);
+ server_state.start_streaming_applier(server_id, transaction_id,
+ applier);
+ applier->start_transaction(wsrep::ws_handle(transaction_id, 0),
+ ws_meta);
+ }
+ applier->store_globals();
+ applier->apply_write_set(ws_meta, data);
+ applier->after_apply();
+ storage_service.store_globals();
+ }
+ else if (error == HA_ERR_END_OF_FILE)
+ {
+ ret= 0;
+ break;
+ }
+ else
+ {
+ WSREP_ERROR("SR table scan returned error %d", error);
+ break;
+ }
+ }
+ Wsrep_schema_impl::end_scan(frag_table);
+ Wsrep_schema_impl::finish_stmt(&storage_thd);
+ trans_commit(&storage_thd);
+out:
+ DBUG_RETURN(ret);
+}
diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h
new file mode 100644
index 00000000000..af42db459f3
--- /dev/null
+++ b/sql/wsrep_schema.h
@@ -0,0 +1,167 @@
+/* Copyright (C) 2015-2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#ifndef WSREP_SCHEMA_H
+#define WSREP_SCHEMA_H
+
+/* wsrep-lib */
+#include "wsrep_types.h"
+
+
+#include "mysqld.h"
+#include "thr_lock.h" /* enum thr_lock_type */
+#include "../wsrep/wsrep_api.h"
+#include "wsrep_mysqld.h"
+
+#include <string>
+
+/*
+ Forward decls
+*/
+class THD;
+class Relay_log_info;
+struct TABLE;
+struct TABLE_LIST;
+struct st_mysql_lex_string;
+typedef struct st_mysql_lex_string LEX_STRING;
+
+class Wsrep_thd_pool;
+
+/** Name of the system database (schema) used for WSREP related data. */
+extern const std::string wsrep_schema_str;
+
+/** Name of the table in `wsrep_schema_str` used for storing streaming
+replication data. In an InnoDB full format, e.g. "database/tablename". */
+extern const std::string sr_table_name_full_str;
+
+class Wsrep_schema
+{
+ public:
+
+ Wsrep_schema(Wsrep_thd_pool*);
+ ~Wsrep_schema();
+
+ /*
+ Initialize wsrep schema. Storage engines must be running before
+ calling this function.
+ */
+ int init();
+
+ /*
+ Store wsrep view info into wsrep schema.
+ */
+ int store_view(THD*, const Wsrep_view& view);
+
+ /*
+ Restore view info from stable storage.
+ */
+ int restore_view(const wsrep_uuid_t& node_uuid, wsrep_view_info_t**) const;
+
+ /*
+ Append transaction fragment to fragment storage.
+ Starts a trx using a THD from thd_pool, does not commit.
+ Should be followed by a call to update_frag_seqno(), or
+ release_SR_thd() if wsrep->certify() fails.
+ */
+ THD* append_frag(const wsrep_trx_meta_t&, uint32_t,
+ const unsigned char*, size_t);
+ /**
+ Append transaction fragment to fragment storage.
+ Transaction must have been started for THD before this call.
+ In order to make changes durable, transaction must be committed
+ separately after this call.
+
+ @param thd THD object
+ @param server_id Wsrep server identifier
+ @param transaction_id Transaction identifier
+ @param flags Flags for the fragment
+ @param data Fragment data buffer
+
+ @return Zero in case of success, non-zero on failure.
+ */
+ int append_fragment(THD* thd,
+ const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ wsrep::seqno seqno,
+ int flags,
+ const wsrep::const_buffer& data);
+ /**
+ Update existing fragment meta data. The fragment must have been
+ inserted before using append_fragment().
+
+ @param thd THD object
+ @param ws_meta Wsrep meta data
+
+ @return Zero in case of success, non-zero on failure.
+ */
+ int update_fragment_meta(THD* thd,
+ const wsrep::ws_meta& ws_meta);
+
+ /**
+ Remove fragments from storage. This method must be called
+ inside active transaction. Fragment removal will be committed
+ once the transaction commits.
+
+ @param thd Pointer to THD object
+ @param server_id Identifier of the running server
+ @param transaction_id Identifier of the current transaction
+ @param fragments Vector of fragment seqnos to be removed
+ */
+ int remove_fragments(THD* thd,
+ const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ const std::vector<wsrep::seqno>& fragments);
+
+ /**
+ Replay a transaction from stored fragments. The caller must have
+ started a transaction for a thd.
+
+ @param thd Pointer to THD object
+ @param ws_meta Write set meta data for commit fragment.
+ @param fragments Vector of fragments to be replayed
+
+ @return Zero on success, non-zero on failure.
+ */
+ int replay_transaction(THD* thd,
+ Relay_log_info* rli,
+ const wsrep::ws_meta& ws_meta,
+ const std::vector<wsrep::seqno>& fragments);
+
+ /**
+ Recover streaming transactions from SR table.
+ This method should be called after storage enignes are initialized.
+ It will scan SR table and replay found streaming transactions.
+
+ @return Zero on success, non-zero on failure.
+ */
+ int recover_sr_transactions();
+
+ /*
+ Close wsrep schema.
+ */
+ void close();
+
+ private:
+ /* Non-copyable */
+ Wsrep_schema(const Wsrep_schema&);
+ Wsrep_schema& operator=(const Wsrep_schema&);
+
+ Wsrep_thd_pool* thd_pool_;
+};
+
+extern Wsrep_schema* wsrep_schema;
+
+#endif /* !WSREP_SCHEMA_H */
diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc
new file mode 100644
index 00000000000..f22d3d1b1e5
--- /dev/null
+++ b/sql/wsrep_server_service.cc
@@ -0,0 +1,277 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "my_global.h"
+//#include "mysql/service_wsrep.h"
+#include "wsrep_server_service.h"
+#include "wsrep_server_state.h"
+#include "wsrep_client_state.h"
+#include "wsrep_client_service.h"
+#include "wsrep_storage_service.h"
+#include "wsrep_high_priority_service.h"
+
+#include "wsrep_sst.h"
+#include "wsrep_xid.h"
+#include "wsrep_mysqld.h"
+#include "wsrep_schema.h"
+
+#include "log.h" /* sql_print_xxx() */
+#include "sql_class.h" /* system variables */
+//#include "global_threads.h" /* LOCK_thread_count */
+#include "transaction.h" /* trans_xxx */
+#include "sql_base.h" /* close_thread_tables */
+
+static void init_service_thd(THD* thd, char* thread_stack)
+{
+ thd->thread_stack= thread_stack;
+ //thd->thread_id= 0;
+ thd->real_id= pthread_self();
+ thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
+ thd->set_command(COM_SLEEP);
+ thd->reset_for_next_command(true);
+}
+
+wsrep::storage_service* Wsrep_server_service::storage_service(
+ wsrep::client_service& client_service)
+{
+ Wsrep_client_service& cs=
+ static_cast<Wsrep_client_service&>(client_service);
+ THD* thd = new THD(next_thread_id(), true, true);
+ init_service_thd(thd, cs.m_thd->thread_stack);
+ WSREP_DEBUG("Created storage service with thread id %lu",
+ thd->thread_id);
+ return new Wsrep_storage_service(thd);
+}
+
+wsrep::storage_service* Wsrep_server_service::storage_service(
+ wsrep::high_priority_service& high_priority_service)
+{
+ Wsrep_high_priority_service& hps=
+ static_cast<Wsrep_high_priority_service&>(high_priority_service);
+ THD* thd = new THD(next_thread_id(), true, true);
+ init_service_thd(thd, hps.m_thd->thread_stack);
+ WSREP_DEBUG("Created high priority storage service with thread id %lu",
+ thd->thread_id);
+ return new Wsrep_storage_service(thd);
+}
+
+void Wsrep_server_service::release_storage_service(
+ wsrep::storage_service* storage_service)
+{
+ Wsrep_storage_service* ss=
+ static_cast<Wsrep_storage_service*>(storage_service);
+ THD* thd= ss->m_thd;
+ delete ss;
+ delete thd;
+}
+
+wsrep::high_priority_service*
+Wsrep_server_service::streaming_applier_service(
+ wsrep::client_service& orig_client_service)
+{
+ Wsrep_client_service& orig_cs=
+ static_cast<Wsrep_client_service&>(orig_client_service);
+ THD* thd= new THD(next_thread_id(), true, true);
+ init_service_thd(thd, orig_cs.m_thd->thread_stack);
+ WSREP_DEBUG("Created streaming applier service in local context with "
+ "thread id %lu", thd->thread_id);
+ return new Wsrep_applier_service(thd);
+}
+
+wsrep::high_priority_service*
+Wsrep_server_service::streaming_applier_service(
+ wsrep::high_priority_service& orig_high_priority_service)
+{
+ Wsrep_high_priority_service&
+ orig_hps(static_cast<Wsrep_high_priority_service&>(orig_high_priority_service));
+ THD* thd= new THD(next_thread_id(), true, true);
+ init_service_thd(thd, orig_hps.m_thd->thread_stack);
+ WSREP_DEBUG("Created streaming applier service in high priority "
+ "context with thread id %lu", thd->thread_id);
+ return new Wsrep_applier_service(thd);
+}
+
+void Wsrep_server_service::release_high_priority_service(wsrep::high_priority_service* high_priority_service)
+{
+ Wsrep_high_priority_service* hps=
+ static_cast<Wsrep_high_priority_service*>(high_priority_service);
+ THD* thd= hps->m_thd;
+ delete hps;
+ delete thd;
+}
+
+void Wsrep_server_service::background_rollback(wsrep::client_state& client_state)
+{
+ Wsrep_client_state& cs= static_cast<Wsrep_client_state&>(client_state);
+ wsrep_fire_rollbacker(cs.thd());
+}
+
+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());
+}
+
+void Wsrep_server_service::log_message(enum wsrep::log::level level,
+ const char* message)
+{
+ switch (level)
+ {
+ case wsrep::log::debug:
+ sql_print_information("debug: %s", message);
+ break;
+ case wsrep::log::info:
+ sql_print_information("%s", message);
+ break;
+ case wsrep::log::warning:
+ sql_print_warning("%s", message);
+ break;
+ case wsrep::log::error:
+ sql_print_error("%s", message);
+ break;
+ }
+}
+
+void Wsrep_server_service::log_view(
+ wsrep::high_priority_service* high_priority_service,
+ const wsrep::view& view)
+{
+ Wsrep_high_priority_service* applier=
+ static_cast<Wsrep_high_priority_service*>(high_priority_service);
+ /* Update global system variables */
+ mysql_mutex_lock(&LOCK_global_system_variables);
+ if (wsrep_auto_increment_control && view.own_index() >= 0)
+ {
+ global_system_variables.auto_increment_offset= view.own_index() + 1;
+ global_system_variables.auto_increment_increment= view.members().size();
+ wsrep_protocol_version = view.protocol_version();
+ }
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+
+ /* Update wsrep status variables */
+ mysql_mutex_lock(&LOCK_status);
+ wsrep_cluster_size= view.members().size();
+ wsrep_local_index= view.own_index();
+ std::ostringstream os;
+ os << view.state_id().id();
+ wsrep_update_cluster_state_uuid(os.str().c_str());
+ mysql_mutex_unlock(&LOCK_status);
+
+ if (view.status() == wsrep::view::primary)
+ {
+ if (applier)
+ {
+ if (trans_begin(applier->m_thd, MYSQL_START_TRANS_OPT_READ_WRITE))
+ {
+ WSREP_WARN("Failed to start transaction for store view");
+ }
+ else
+ {
+ if (wsrep_schema->store_view(applier->m_thd, view))
+ {
+ WSREP_WARN("Failed to store view");
+ trans_rollback_stmt(applier->m_thd);
+ if (!trans_rollback(applier->m_thd))
+ {
+ close_thread_tables(applier->m_thd);
+ }
+ }
+ else
+ {
+ if (trans_commit(applier->m_thd))
+ {
+ WSREP_WARN("Failed to commit transaction for store view");
+ }
+ }
+ applier->m_thd->mdl_context.release_transactional_locks();
+ }
+ }
+ else
+ {
+ WSREP_WARN("No applier in Wsrep_server_service::log_view(), "
+ "skipping write to wsrep_schema");
+ }
+ }
+
+ if (view.status() == wsrep::view::primary &&
+ m_server_state.provider().last_committed_gtid().seqno() !=
+ view.state_id().seqno())
+ {
+ wsrep_set_SE_checkpoint(view.state_id());
+ }
+}
+
+void Wsrep_server_service::log_state_change(
+ enum Wsrep_server_state::state prev_state,
+ enum Wsrep_server_state::state current_state)
+{
+ WSREP_INFO("Server status change %s -> %s",
+ wsrep::to_c_string(prev_state),
+ wsrep::to_c_string(current_state));
+ mysql_mutex_lock(&LOCK_status);
+ switch (current_state)
+ {
+ case Wsrep_server_state::s_synced:
+ wsrep_ready= TRUE;
+ /* fall through */
+ case Wsrep_server_state::s_joined:
+ case Wsrep_server_state::s_donor:
+ wsrep_cluster_status= "Primary";
+ break;
+ case Wsrep_server_state::s_connected:
+ wsrep_cluster_status= "non-Primary";
+ wsrep_ready= FALSE;
+ wsrep_connected= TRUE;
+ break;
+ case Wsrep_server_state::s_disconnected:
+ wsrep_ready= FALSE;
+ wsrep_connected= FALSE;
+ wsrep_cluster_status= "Disconnected";
+ break;
+ default:
+ wsrep_ready= FALSE;
+ wsrep_cluster_status= "non-Primary";
+ break;
+ }
+ mysql_mutex_unlock(&LOCK_status);
+}
+
+bool Wsrep_server_service::sst_before_init() const
+{
+ return wsrep_before_SE();
+}
+
+std::string Wsrep_server_service::sst_request()
+{
+ return wsrep_sst_prepare();
+}
+
+int Wsrep_server_service::start_sst(const std::string& sst_request,
+ const wsrep::gtid& gtid,
+ bool bypass)
+{
+ return wsrep_sst_donate(sst_request, gtid, bypass);
+}
+
+int Wsrep_server_service::wait_committing_transactions(int timeout)
+{
+ return wsrep_wait_committing_connections_close(timeout);
+}
+
+void Wsrep_server_service::debug_sync(const char*)
+{
+}
diff --git a/sql/wsrep_server_service.h b/sql/wsrep_server_service.h
new file mode 100644
index 00000000000..c3a41829e67
--- /dev/null
+++ b/sql/wsrep_server_service.h
@@ -0,0 +1,75 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_SERVER_SERVICE_H
+#define WSREP_SERVER_SERVICE_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/server_service.hpp"
+#include "../wsrep-lib/include/wsrep/exception.hpp" // not_impemented_error(), remove when finished
+#include "../wsrep-lib/include/wsrep/storage_service.hpp"
+
+class Wsrep_server_state;
+
+
+/* wsrep::server_service interface implementation */
+class Wsrep_server_service : public wsrep::server_service
+{
+public:
+ Wsrep_server_service(Wsrep_server_state& server_state)
+ : m_server_state(server_state)
+ { }
+
+ wsrep::storage_service* storage_service(wsrep::client_service&);
+
+ wsrep::storage_service* storage_service(wsrep::high_priority_service&);
+
+ void release_storage_service(wsrep::storage_service*);
+
+ wsrep::high_priority_service*
+ streaming_applier_service(wsrep::client_service&);
+
+ wsrep::high_priority_service*
+ streaming_applier_service(wsrep::high_priority_service&);
+
+ void release_high_priority_service(wsrep::high_priority_service*);
+
+ void background_rollback(wsrep::client_state&);
+
+ void bootstrap();
+ void log_message(enum wsrep::log::level, const char*);
+
+ void log_dummy_write_set(wsrep::client_state&, const wsrep::ws_meta&)
+ { throw wsrep::not_implemented_error(); }
+
+ void log_view(wsrep::high_priority_service*, const wsrep::view&);
+
+ void log_state_change(enum wsrep::server_state::state,
+ enum wsrep::server_state::state);
+
+ bool sst_before_init() const;
+
+ std::string sst_request();
+ int start_sst(const std::string&, const wsrep::gtid&, bool);
+
+ int wait_committing_transactions(int);
+
+ void debug_sync(const char*);
+private:
+ Wsrep_server_state& m_server_state;
+};
+
+
+#endif /* WSREP_SERVER_SERVICE */
diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc
new file mode 100644
index 00000000000..472be8b8169
--- /dev/null
+++ b/sql/wsrep_server_state.cc
@@ -0,0 +1,78 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "my_global.h"
+#include "wsrep_api.h"
+#include "wsrep_server_state.h"
+
+mysql_mutex_t LOCK_wsrep_server_state;
+PSI_mutex_key key_LOCK_wsrep_server_state;
+mysql_cond_t COND_wsrep_server_state;
+PSI_cond_key key_COND_wsrep_server_state;
+
+Wsrep_server_state::Wsrep_server_state(const std::string& name,
+ const std::string& id,
+ const std::string& incoming_address,
+ const std::string& address,
+ const std::string& working_dir,
+ const wsrep::gtid& initial_position,
+ int max_protocol_version)
+ : wsrep::server_state(m_mutex,
+ m_cond,
+ m_service,
+ name,
+ id,
+ incoming_address,
+ address,
+ working_dir,
+ initial_position,
+ max_protocol_version,
+ wsrep::server_state::rm_sync)
+ , m_mutex(LOCK_wsrep_server_state)
+ , m_cond(COND_wsrep_server_state)
+ , m_service(*this)
+{
+
+}
+
+void Wsrep_server_state::init_once(const std::string& name,
+ const std::string& id,
+ const std::string& incoming_address,
+ const std::string& address,
+ const std::string& working_dir,
+ const wsrep::gtid& initial_position,
+ int max_protocol_version)
+{
+ if (m_instance == 0)
+ {
+ mysql_mutex_init(key_LOCK_wsrep_server_state, &LOCK_wsrep_server_state,
+ MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_server_state, &COND_wsrep_server_state, 0);
+ m_instance = new Wsrep_server_state(name,
+ id,
+ incoming_address,
+ address,
+ working_dir,
+ initial_position,
+ max_protocol_version);
+ }
+}
+
+void Wsrep_server_state::destroy()
+{
+ delete m_instance;
+ mysql_mutex_destroy(&LOCK_wsrep_server_state);
+ mysql_cond_destroy(&COND_wsrep_server_state);
+}
diff --git a/sql/wsrep_server_state.h b/sql/wsrep_server_state.h
new file mode 100644
index 00000000000..5f99259edc7
--- /dev/null
+++ b/sql/wsrep_server_state.h
@@ -0,0 +1,68 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_SERVER_STATE_H
+#define WSREP_SERVER_STATE_H
+
+/* wsrep-lib */
+#include "../wsrep-lib/include/wsrep/server_state.hpp"
+#include "../wsrep-lib/include/wsrep/provider.hpp"
+
+/* implementation */
+#include "wsrep_server_service.h"
+#include "wsrep_mutex.h"
+#include "wsrep_condition_variable.h"
+
+class Wsrep_server_state : public wsrep::server_state
+{
+public:
+ static void init_once(const std::string& name,
+ const std::string& id,
+ const std::string& incoming_address,
+ const std::string& address,
+ const std::string& working_dir,
+ const wsrep::gtid& initial_position,
+ int max_protocol_version);
+ static void destroy();
+ static Wsrep_server_state& instance()
+ {
+ return *m_instance;
+ }
+
+ static wsrep::provider& get_provider()
+ {
+ return instance().provider();
+ }
+
+ static bool has_capability(int capability)
+ {
+ return (get_provider().capabilities() & capability);
+ }
+private:
+ Wsrep_server_state(const std::string& name,
+ const std::string& id,
+ const std::string& incoming_address,
+ const std::string& address,
+ const std::string& working_dir,
+ const wsrep::gtid& initial_position,
+ int max_protocol_version);
+ Wsrep_mutex m_mutex;
+ Wsrep_condition_variable m_cond;
+ Wsrep_server_service m_service;
+
+ static Wsrep_server_state* m_instance;
+};
+
+#endif // WSREP_SERVER_STATE_H
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index e648a7f4c69..63fa699f24c 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -1,4 +1,4 @@
-/* Copyright 2008-2015 Codership Oy <http://www.codership.com>
+/* Copyright 2008-2017 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
#include <cstdio>
#include <cstdlib>
+const char wsrep_defaults_group_suffix[256] = {0};
#include <my_service_manager.h>
static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 +
@@ -180,6 +181,7 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type)
return 0;
}
+
bool wsrep_before_SE()
{
return (wsrep_provider != NULL
@@ -188,90 +190,17 @@ bool wsrep_before_SE()
&& strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP));
}
-static bool sst_complete = false;
-static bool sst_needed = false;
-
-#define WSREP_EXTEND_TIMEOUT_INTERVAL 30
-#define WSREP_TIMEDWAIT_SECONDS 10
-
-void wsrep_sst_grab ()
-{
- WSREP_INFO("wsrep_sst_grab()");
- if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort();
- sst_complete = false;
- mysql_mutex_unlock (&LOCK_wsrep_sst);
-}
-
-// Wait for end of SST
-bool wsrep_sst_wait ()
-{
- double total_wtime = 0;
-
- if (mysql_mutex_lock (&LOCK_wsrep_sst))
- abort();
-
- WSREP_INFO("Waiting for SST to complete.");
-
- while (!sst_complete)
- {
- struct timespec wtime;
- set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS);
- time_t start_time = time(NULL);
- mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime);
- time_t end_time = time(NULL);
-
- if (!sst_complete)
- {
- total_wtime += difftime(end_time, start_time);
- WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime);
- service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
- "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
- }
- }
-
- if (local_seqno >= 0)
- {
- WSREP_INFO("SST complete, seqno: %lld", (long long) local_seqno);
- }
- else
- {
- WSREP_ERROR("SST failed: %d (%s)",
- int(-local_seqno), strerror(-local_seqno));
- }
-
- mysql_mutex_unlock (&LOCK_wsrep_sst);
-
- return (local_seqno >= 0);
-}
-
// Signal end of SST
void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
wsrep_seqno_t sst_seqno,
bool needed)
{
- if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort();
- if (!sst_complete)
- {
- sst_complete = true;
- sst_needed = needed;
- local_uuid = *sst_uuid;
- local_seqno = sst_seqno;
- mysql_cond_signal (&COND_wsrep_sst);
- }
- else
- {
- /* This can happen when called from wsrep_synced_cb().
- At the moment there is no way to check there
- if main thread is still waiting for signal,
- so wsrep_sst_complete() is called from there
- each time wsrep_ready changes from FALSE -> TRUE.
- */
- WSREP_DEBUG("Nobody is waiting for SST.");
- }
- mysql_mutex_unlock (&LOCK_wsrep_sst);
+ wsrep::gtid gtid(wsrep::id(sst_uuid->data, sizeof(sst_uuid->data)),
+ wsrep::seqno(sst_seqno));
+ Wsrep_server_state::instance().sst_received(gtid, 0);
}
-/*
+ /*
If wsrep provider is loaded, inform that the new state snapshot
has been received. Also update the local checkpoint.
@@ -287,12 +216,11 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
true Error
*/
-bool wsrep_sst_received (wsrep_t* const wsrep,
- const wsrep_uuid_t& uuid,
- const wsrep_seqno_t seqno,
- const void* const state,
- const size_t state_len,
- const bool implicit)
+void wsrep_sst_received (THD* thd,
+ const wsrep_uuid_t& uuid,
+ wsrep_seqno_t const seqno,
+ const void* const state,
+ size_t const state_len)
{
/*
To keep track of whether the local uuid:seqno should be updated. Also, note
@@ -300,81 +228,50 @@ bool wsrep_sst_received (wsrep_t* const wsrep,
OK from wsrep provider. By doing so, the values remain consistent across
the server & wsrep provider.
*/
- bool do_update= false;
-
- // Get the locally stored uuid:seqno.
- if (wsrep_get_SE_checkpoint(local_uuid, local_seqno))
- {
- return true;
- }
-
- if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) ||
- local_seqno < seqno || seqno < 0)
- {
- do_update= true;
- }
- else if (local_seqno > seqno)
- {
- WSREP_WARN("SST position can't be set in past. Requested: %lld, Current: "
- " %lld.", (long long)seqno, (long long)local_seqno);
/*
- If we are here because of SET command, simply return true (error) instead of
- aborting.
+ TODO: Handle backwards compatibility. WSREP API v25 does not have
+ wsrep schema.
*/
- if (implicit)
- {
- WSREP_WARN("Can't continue.");
- unireg_abort(1);
- }
- else
- {
- return true;
+ /*
+ If thd is non-NULL, this thread is holding LOCK_global_system_variables.
+ It needs to be released temporarily since wsrep_init_schema()
+ does THD pool initialization, which will lock this lock in
+ THD allocation.
+ */
+ if (thd) mysql_mutex_unlock(&LOCK_global_system_variables);
+ // wsrep_init_schema();
+ /*
+ Logical SST methods (mysqldump etc) don't update InnoDB sys header.
+ Reset the SE checkpoint before recovering view in order to avoid
+ sanity check failure.
+ */
+ if (!wsrep_before_SE()) {
+ // wsrep_seqno_t se_seqno= -1;
+ // wsrep_uuid_t se_uuid= WSREP_UUID_UNDEFINED;
+ wsrep_set_SE_checkpoint(wsrep::gtid::undefined());
+ wsrep_set_SE_checkpoint(wsrep::gtid(wsrep::id(uuid.data,
+ sizeof(uuid.data)),
+ wsrep::seqno(seqno)));
}
- }
-
-#ifdef GTID_SUPPORT
- wsrep_init_sidno(uuid);
-#endif /* GTID_SUPPORT */
+ wsrep_verify_SE_checkpoint(uuid, seqno);
+ // wsrep_init_SR();
+ if (thd) mysql_mutex_lock(&LOCK_global_system_variables);
- if (wsrep)
- {
- int const rcode(seqno < 0 ? seqno : 0);
- wsrep_gtid_t const state_id= {uuid,
- (rcode ? WSREP_SEQNO_UNDEFINED : seqno)};
-
- wsrep_status_t ret= wsrep->sst_received(wsrep, &state_id, state,
- state_len, rcode);
-
- if (ret != WSREP_OK)
- {
- return true;
+ /*
+ Both wsrep_init_SR() and wsrep_recover_view() may use
+ wsrep thread pool. Restore original thd context before returning.
+ */
+ if (thd) {
+ thd->store_globals();
}
- }
-
- // Now is the good time to update the local state and checkpoint.
- if (do_update)
- {
- if (wsrep_set_SE_checkpoint(uuid, seqno))
- {
- return true;
+ else {
+ my_pthread_setspecific_ptr(THR_THD, NULL);
}
- local_uuid= uuid;
- local_seqno= seqno;
- }
-
- return false;
-}
-
-// Let applier threads to continue
-bool wsrep_sst_continue ()
-{
- if (sst_needed)
- {
- WSREP_INFO("Signalling provider to continue.");
- return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true);
- }
- return false;
+ int const rcode(seqno < 0 ? seqno : 0);
+ wsrep::gtid gtid(wsrep::id(uuid.data, sizeof(uuid.data)),
+ wsrep::seqno(seqno));
+ Wsrep_server_state::instance().sst_received(gtid, rcode);
}
struct sst_thread_arg
@@ -799,29 +696,21 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in,
static bool SE_initialized = false;
-ssize_t wsrep_sst_prepare (void** msg)
+std::string wsrep_sst_prepare()
{
+ const ssize_t ip_max= 256;
+ char ip_buf[ip_max];
const char* addr_in= NULL;
const char* addr_out= NULL;
if (!strcmp(wsrep_sst_method, WSREP_SST_SKIP))
{
- ssize_t ret = strlen(WSREP_STATE_TRANSFER_TRIVIAL) + 1;
- *msg = strdup(WSREP_STATE_TRANSFER_TRIVIAL);
- if (!msg)
- {
- WSREP_ERROR("Could not allocate %zd bytes for state request", ret);
- unireg_abort(1);
- }
- return ret;
+ return WSREP_STATE_TRANSFER_TRIVIAL;
}
/*
Figure out SST receive address. Common for all SST methods.
*/
- char ip_buf[256];
- const ssize_t ip_max= sizeof(ip_buf);
-
// Attempt 1: wsrep_sst_receive_address
if (wsrep_sst_receive_address &&
strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO))
@@ -838,7 +727,7 @@ ssize_t wsrep_sst_prepare (void** msg)
{
WSREP_ERROR("Could not parse wsrep_node_address : %s",
wsrep_node_address);
- unireg_abort(1);
+ throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable");
}
memcpy(ip_buf, addr.get_address(), addr.get_address_len());
addr_in= ip_buf;
@@ -856,7 +745,7 @@ ssize_t wsrep_sst_prepare (void** msg)
{
WSREP_ERROR("Failed to guess address to accept state transfer. "
"wsrep_sst_receive_address must be set manually.");
- unireg_abort(1);
+ throw wsrep::runtime_error("Could not prepare state transfer request");
}
}
@@ -864,12 +753,16 @@ ssize_t wsrep_sst_prepare (void** msg)
if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP))
{
addr_len= sst_prepare_mysqldump (addr_in, &addr_out);
- if (addr_len < 0) unireg_abort(1);
+ if (addr_len < 0)
+ {
+ throw wsrep::runtime_error("Could not prepare mysqldimp address");
+ }
}
else
{
/*! A heuristic workaround until we learn how to stop and start engines */
- if (SE_initialized)
+ if (Wsrep_server_state::instance().is_initialized() &&
+ Wsrep_server_state::instance().state() == Wsrep_server_state::s_joiner)
{
// we already did SST at initializaiton, now engines are running
// sql_print_information() is here because the message is too long
@@ -881,8 +774,7 @@ ssize_t wsrep_sst_prepare (void** msg)
"if other means of state transfer are unavailable. "
"In that case you will need to restart the server.",
wsrep_sst_method);
- *msg = 0;
- return 0;
+ return "";
}
addr_len = sst_prepare_other (wsrep_sst_method, sst_auth_real,
@@ -891,31 +783,22 @@ ssize_t wsrep_sst_prepare (void** msg)
{
WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.",
wsrep_sst_method);
- unireg_abort(1);
+ throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable");
}
}
- size_t const method_len(strlen(wsrep_sst_method));
- size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/);
-
- *msg = malloc (msg_len);
- if (NULL != *msg) {
- char* const method_ptr(reinterpret_cast<char*>(*msg));
- strcpy (method_ptr, wsrep_sst_method);
- char* const addr_ptr(method_ptr + method_len + 1);
- strcpy (addr_ptr, addr_out);
+ std::string ret;
+ ret += wsrep_sst_method;
+ ret.push_back('\0');
+ ret += addr_out;
- WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr);
- }
- else {
- WSREP_ERROR("Failed to allocate SST request of size %zu. Can't continue.",
- msg_len);
- unireg_abort(1);
- }
+ const char* method_ptr(ret.data());
+ const char* addr_ptr(ret.data() + strlen(method_ptr) + 1);
+ WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr);
if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out);
- return msg_len;
+ return ret;
}
// helper method for donors
@@ -950,15 +833,13 @@ static int sst_run_shell (const char* cmd_str, char** env, int max_tries)
static void sst_reject_queries(my_bool close_conn)
{
- wsrep_ready_set (FALSE); // this will be resotred when donor becomes synced
- WSREP_INFO("Rejecting client queries for the duration of SST.");
- if (TRUE == close_conn) wsrep_close_client_connections(FALSE);
+ // wsrep_ready_set (FALSE); // this will be resotred when donor becomes synced
+ WSREP_INFO("Rejecting client queries for the duration of SST.");
+ if (TRUE == close_conn) wsrep_close_client_connections(FALSE);
}
static int sst_donate_mysqldump (const char* addr,
- const wsrep_uuid_t* uuid,
- const char* uuid_str,
- wsrep_seqno_t seqno,
+ const wsrep::gtid& gtid,
bool bypass,
char** env) // carries auth info
{
@@ -981,10 +862,15 @@ static int sst_donate_mysqldump (const char* addr,
return -ENOMEM;
}
+ /*
+ we enable new client connections so that mysqldump donation can connect in,
+ but we reject local connections from modifyingcdata during SST, to keep
+ data intact
+ */
if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE);
- make_wsrep_defaults_file();
-
+ std::ostringstream uuid_oss;
+ uuid_oss << gtid.id();
int ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_mysqldump "
WSREP_SST_OPT_ADDR " '%s' "
@@ -995,10 +881,9 @@ static int sst_donate_mysqldump (const char* addr,
WSREP_SST_OPT_GTID " '%s:%lld' "
WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
- addr, port, mysqld_port, mysqld_unix_port,
- wsrep_defaults_file, uuid_str,
- (long long)seqno, wsrep_gtid_domain_id,
- bypass ? " " WSREP_SST_OPT_BYPASS : "");
+ addr, mysqld_port, mysqld_unix_port,
+ wsrep_defaults_file, uuid_oss.str().c_str(),
+ gtid.seqno().get(), bypass ? " " WSREP_SST_OPT_BYPASS : "");
if (ret < 0 || ret >= cmd_len)
{
@@ -1010,16 +895,17 @@ static int sst_donate_mysqldump (const char* addr,
ret= sst_run_shell (cmd_str(), env, 3);
- wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)};
-
- wsrep->sst_sent (wsrep, &state_id, ret);
+ wsrep::gtid sst_sent_gtid(ret == 0 ?
+ gtid :
+ wsrep::gtid(gtid.id(),
+ wsrep::seqno::undefined()));
+ Wsrep_server_state::instance().sst_sent(sst_sent_gtid, ret);
return ret;
}
wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
-
/*
Create a file under data directory.
*/
@@ -1068,7 +954,6 @@ static int sst_create_file(const char *name, const char *content)
return err;
}
-
static int run_sql_command(THD *thd, const char *query)
{
thd->set_query((char *)query, strlen(query));
@@ -1155,7 +1040,6 @@ static int sst_flush_tables(THD* thd)
else
{
WSREP_INFO("Tables flushed.");
-
/*
Tables have been flushed. Create a file with cluster state ID and
wsrep_gtid_domain_id.
@@ -1164,6 +1048,40 @@ static int sst_flush_tables(THD* thd)
snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid,
(long long)wsrep_locked_seqno, wsrep_gtid_domain_id);
err= sst_create_file(flush_success, content);
+
+ const char base_name[]= "tables_flushed";
+ ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2;
+ char *real_name = (char*) malloc(full_len);
+ sprintf(real_name, "%s/%s", mysql_real_data_home, base_name);
+ char *tmp_name = (char*) malloc(full_len + 4);
+ sprintf(tmp_name, "%s.tmp", real_name);
+
+ FILE* file= fopen(tmp_name, "w+");
+ if (0 == file)
+ {
+ err= errno;
+ WSREP_ERROR("Failed to open '%s': %d (%s)", tmp_name, err,strerror(err));
+ }
+ else
+ {
+ Wsrep_server_state& server_state= Wsrep_server_state::instance();
+ std::ostringstream uuid_oss;
+
+ uuid_oss << server_state.current_view().state_id().id();
+
+ fprintf(file, "%s:%lld\n",
+ uuid_oss.str().c_str(), server_state.pause_seqno().get());
+ fsync(fileno(file));
+ fclose(file);
+ if (rename(tmp_name, real_name) == -1)
+ {
+ err= errno;
+ WSREP_ERROR("Failed to rename '%s' to '%s': %d (%s)",
+ tmp_name, real_name, err,strerror(err));
+ }
+ }
+ free(real_name);
+ free(tmp_name);
}
return err;
@@ -1306,24 +1224,20 @@ static void* sst_donor_thread (void* a)
thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr);
}
- // signal to donor that SST is over
- struct wsrep_gtid const state_id = {
- ret_uuid, err ? WSREP_SEQNO_UNDEFINED : ret_seqno
- };
- wsrep->sst_sent (wsrep, &state_id, -err);
+ wsrep::gtid gtid(wsrep::id(ret_uuid.data, sizeof(ret_uuid.data)),
+ wsrep::seqno(err ? wsrep::seqno::undefined() :
+ wsrep::seqno(ret_seqno)));
+ Wsrep_server_state::instance().sst_sent(gtid, err);
proc.wait();
return NULL;
}
-
-
-static int sst_donate_other (const char* method,
- const char* addr,
- const char* uuid,
- wsrep_seqno_t seqno,
- bool bypass,
- char** env) // carries auth info
+static int sst_donate_other (const char* method,
+ const char* addr,
+ const wsrep::gtid& gtid,
+ bool bypass,
+ char** env) // carries auth info
{
int const cmd_len= 4096;
wsp::string cmd_str(cmd_len);
@@ -1346,8 +1260,8 @@ static int sst_donate_other (const char* method,
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
- make_wsrep_defaults_file();
-
+ std::ostringstream uuid_oss;
+ uuid_oss << gtid.id();
ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE " 'donor' "
@@ -1362,7 +1276,7 @@ static int sst_donate_other (const char* method,
method, addr, mysqld_unix_port, mysql_real_data_home,
wsrep_defaults_file,
binlog_opt, binlog_opt_val,
- uuid, (long long) seqno, wsrep_gtid_domain_id,
+ uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id,
bypass ? " " WSREP_SST_OPT_BYPASS : "");
my_free(binlog_opt_val);
@@ -1390,24 +1304,20 @@ static int sst_donate_other (const char* method,
return arg.err;
}
-wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
- const void* msg, size_t msg_len,
- const wsrep_gtid_t* current_gtid,
- const char* state, size_t state_len,
- bool bypass)
+int wsrep_sst_donate(const std::string& msg,
+ const wsrep::gtid& current_gtid,
+ const bool bypass)
{
/* This will be reset when sync callback is called.
* Should we set wsrep_ready to FALSE here too? */
wsrep_config_state->set(WSREP_MEMBER_DONOR);
+ local_status.set(WSREP_MEMBER_DONOR);
- const char* method = (char*)msg;
+ const char* method = msg.data();
size_t method_len = strlen (method);
const char* data = method + method_len + 1;
- char uuid_str[37];
- wsrep_uuid_print (¤t_gtid->uuid, uuid_str, sizeof(uuid_str));
-
wsp::env env(NULL);
if (env.error())
{
@@ -1434,54 +1344,13 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
if (!strcmp (WSREP_SST_MYSQLDUMP, method))
{
- ret = sst_donate_mysqldump(data, ¤t_gtid->uuid, uuid_str,
- current_gtid->seqno, bypass, env());
+ ret = sst_donate_mysqldump(data, current_gtid, bypass, env());
}
else
{
- ret = sst_donate_other(method, data, uuid_str,
- current_gtid->seqno, bypass, env());
+ ret = sst_donate_other(method, data, current_gtid, bypass, env());
}
- return (ret >= 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE);
-}
-
-void wsrep_SE_init_grab()
-{
- if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort();
-}
-
-void wsrep_SE_init_wait()
-{
- double total_wtime=0;
-
- while (SE_initialized == false)
- {
- struct timespec wtime;
- set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS);
- time_t start_time = time(NULL);
- mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime);
- time_t end_time = time(NULL);
-
- if (!SE_initialized)
- {
- total_wtime += difftime(end_time, start_time);
- WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime);
- service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
- "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
- }
- }
-
- mysql_mutex_unlock (&LOCK_wsrep_sst_init);
-}
-
-void wsrep_SE_init_done()
-{
- mysql_cond_signal (&COND_wsrep_sst_init);
- mysql_mutex_unlock (&LOCK_wsrep_sst_init);
-}
-
-void wsrep_SE_initialized()
-{
- SE_initialized = true;
+ return (ret >= 0 ? 0 : 1);
}
+
diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h
index cc0f1f5389d..79d0d9e8a1e 100644
--- a/sql/wsrep_sst.h
+++ b/sql/wsrep_sst.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Codership Oy <info(a)codership.com>
+/* Copyright (C) 2013-2018 Codership Oy <info(a)codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,9 +18,9 @@
#ifndef WSREP_SST_H
#define WSREP_SST_H
-#ifdef WITH_WSREP
-
-#include <mysql.h> // my_bool
+#include "wsrep/gtid.hpp"
+#include <my_global.h>
+#include <string>
#define WSREP_SST_OPT_ROLE "--role"
#define WSREP_SST_OPT_ADDR "--address"
@@ -74,11 +74,29 @@ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */
extern void wsrep_SE_init_done(); /*! signal that SE init is complte */
extern void wsrep_SE_initialized(); /*! mark SE initialization complete */
+/**
+ Return a string containing the state transfer request string.
+ Note that the string may contain a '\0' in the middle.
+*/
+std::string wsrep_sst_prepare();
+
+/**
+ Donate a SST.
+
+ @param request SST request string received from the joiner. Note that
+ the string may contain a '\0' in the middle.
+ @param gtid Current position of the donor
+ @param bypass If true, full SST is not needed. Joiner needs to be
+ notified that it can continue starting from gtid.
+ */
+int wsrep_sst_donate(const std::string& request,
+ const wsrep::gtid& gtid,
+ bool bypass);
+
#else
#define wsrep_SE_initialized() do { } while(0)
#define wsrep_SE_init_grab() do { } while(0)
#define wsrep_SE_init_done() do { } while(0)
#define wsrep_sst_continue() (0)
-#endif /* WITH_WSREP */
#endif /* WSREP_SST_H */
diff --git a/sql/wsrep_storage_service.cc b/sql/wsrep_storage_service.cc
new file mode 100644
index 00000000000..63c8771ea5c
--- /dev/null
+++ b/sql/wsrep_storage_service.cc
@@ -0,0 +1,244 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "my_global.h"
+#include "wsrep_storage_service.h"
+#include "wsrep_trans_observer.h" /* wsrep_open() */
+#include "wsrep_schema.h"
+#include "wsrep_binlog.h"
+
+#include "sql_class.h"
+//#include "global_threads.h" /* LOCK_thread_count */
+#include "mysqld.h" /* next_query_id() */
+#include "slave.h" /* opt_log_slave_updates() */
+#include "transaction.h" /* trans_commit(), trans_rollback() */
+
+/*
+ Temporarily enable wsrep on thd
+ */
+class Wsrep_on
+{
+public:
+ Wsrep_on(THD* thd)
+ : m_thd(thd)
+ , m_wsrep_on(thd->variables.wsrep_on)
+ {
+ thd->variables.wsrep_on= TRUE;
+ }
+ ~Wsrep_on()
+ {
+ m_thd->variables.wsrep_on= m_wsrep_on;
+ }
+private:
+ THD* m_thd;
+ my_bool m_wsrep_on;
+};
+
+Wsrep_storage_service::Wsrep_storage_service(THD* thd)
+ : wsrep::storage_service()
+ , wsrep::high_priority_context(thd->wsrep_cs())
+ , m_thd(thd)
+{
+ thd->security_ctx->skip_grants();
+ thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
+
+ /* No binlogging */
+ // thd->variables.sql_log_bin = 0;
+ // thd->variables.option_bits &= ~OPTION_BIN_LOG;
+
+ /* No general log */
+ thd->variables.option_bits |= OPTION_LOG_OFF;
+
+ /* Read committed isolation to avoid gap locking */
+ thd->variables.tx_isolation = ISO_READ_COMMITTED;
+
+ /* */
+ // thd->variables.wsrep_on= 0;
+ /* Keep wsrep on to enter commit ordering hooks */
+ thd->variables.wsrep_on= 1;
+ thd->wsrep_skip_locking= true;
+
+ wsrep_open(thd);
+ wsrep_before_command(thd);
+}
+
+Wsrep_storage_service::~Wsrep_storage_service()
+{
+ wsrep_after_command_ignore_result(m_thd);
+ wsrep_close(m_thd);
+ m_thd->wsrep_skip_locking= false;
+}
+
+int Wsrep_storage_service::start_transaction(const wsrep::ws_handle& ws_handle)
+{
+ DBUG_ENTER("Wsrep_storage_service::start_transaction");
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_PRINT("info", ("Wsrep_storage_service::start_transcation(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ m_thd->set_wsrep_next_trx_id(ws_handle.transaction_id().get());
+ // DBUG_RETURN(wsrep_start_transaction(m_thd, m_thd->wsrep_next_trx_id()));
+ DBUG_RETURN(m_thd->wsrep_cs().start_transaction(
+ wsrep::transaction_id(m_thd->wsrep_next_trx_id())) ||
+ trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE));
+}
+
+void Wsrep_storage_service::adopt_transaction(const wsrep::transaction& transaction)
+{
+ DBUG_ENTER("Wsrep_Storage_server::adopt_transaction");
+ DBUG_ASSERT(m_thd == current_thd);
+ m_thd->wsrep_cs().adopt_transaction(transaction);
+ trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE);
+ DBUG_VOID_RETURN;
+}
+
+int Wsrep_storage_service::append_fragment(const wsrep::id& server_id,
+ wsrep::transaction_id transaction_id,
+ int flags,
+ const wsrep::const_buffer& data)
+{
+ DBUG_ENTER("Wsrep_storage_service::append_fragment");
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_PRINT("info", ("Wsrep_storage_service::append_fragment(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ int ret= wsrep_schema->append_fragment(m_thd,
+ server_id,
+ transaction_id,
+ wsrep::seqno(-1),
+ flags,
+ data);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_storage_service::update_fragment_meta(const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_storage_service::update_fragment_meta");
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_PRINT("info", ("Wsrep_storage_service::update_fragment_meta(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ int ret= wsrep_schema->update_fragment_meta(m_thd, ws_meta);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_storage_service::remove_fragments()
+{
+ DBUG_ENTER("Wsrep_storage_service::remove_fragments");
+ DBUG_ASSERT(m_thd == current_thd);
+
+ int ret= wsrep_schema->remove_fragments(m_thd,
+ m_thd->wsrep_trx().server_id(),
+ m_thd->wsrep_trx().id(),
+ m_thd->wsrep_sr().fragments());
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_storage_service::commit(const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_storage_service::commit");
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_PRINT("info", ("Wsrep_storage_service::commit(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ WSREP_DEBUG("Storage service commit: %llu, %lld",
+ ws_meta.transaction_id().get(), ws_meta.seqno().get());
+ int ret= 0;
+ const bool do_binlog_commit= (opt_log_slave_updates && wsrep_gtid_mode);
+ const bool is_ordered= !ws_meta.seqno().is_undefined();
+ /*
+ Write skip event into binlog if gtid_mode is on. This is to
+ maintain gtid continuity.
+ */
+ if (do_binlog_commit && is_ordered)
+ {
+ ret= wsrep_write_skip_event(m_thd);
+ }
+
+ if (!ret && is_ordered)
+ {
+ ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle,
+ ws_meta, true);
+ }
+
+ if (!ret)
+ {
+ if (!do_binlog_commit && is_ordered)
+ {
+ ret= wsrep_before_commit(m_thd, true);
+ }
+ ret= ret || trans_commit(m_thd);
+ if (!do_binlog_commit && is_ordered)
+ {
+ if (opt_log_slave_updates)
+ {
+ ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error());
+ }
+ ret= ret || wsrep_after_commit(m_thd, true);
+ }
+ }
+
+ if (!is_ordered)
+ {
+ /* Wsrep commit was not ordered so it does not go through commit time
+ hooks and remains active. Roll it back to make cleanup happen
+ in after_applying() call. */
+ m_thd->wsrep_cs().before_rollback();
+ m_thd->wsrep_cs().after_rollback();
+ }
+ else if (ret)
+ {
+ /* Commit failed, this probably means that the parent SR transaction
+ was BF aborted. Roll back out of order, the parent
+ transaction will release commit order after it has rolled back. */
+ m_thd->wsrep_cs().prepare_for_ordering(wsrep::ws_handle(),
+ wsrep::ws_meta(),
+ false);
+ trans_rollback(m_thd);
+ }
+ m_thd->wsrep_cs().after_applying();
+ m_thd->mdl_context.release_transactional_locks();
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_storage_service::rollback(const wsrep::ws_handle& ws_handle,
+ const wsrep::ws_meta& ws_meta)
+{
+ DBUG_ENTER("Wsrep_storage_service::rollback");
+ DBUG_ASSERT(m_thd == current_thd);
+ DBUG_PRINT("info", ("Wsrep_storage_service::rollback(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ int ret= (m_thd->wsrep_cs().prepare_for_ordering(
+ ws_handle, ws_meta, false) ||
+ trans_rollback(m_thd));
+ m_thd->wsrep_cs().after_applying();
+ m_thd->mdl_context.release_transactional_locks();
+ DBUG_RETURN(ret);
+}
+
+void Wsrep_storage_service::store_globals()
+{
+ DBUG_ENTER("Wsrep_storage_service::store_globals");
+ DBUG_PRINT("info", ("Wsrep_storage_service::store_globals(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ m_thd->store_globals();
+ DBUG_VOID_RETURN;
+}
+
+void Wsrep_storage_service::reset_globals()
+{
+ DBUG_ENTER("Wsrep_storage_service::reset_globals");
+ DBUG_PRINT("info", ("Wsrep_storage_service::reset_globals(%lu, %p)",
+ m_thd->thread_id, m_thd));
+ m_thd->reset_globals();
+ DBUG_VOID_RETURN;
+}
diff --git a/sql/wsrep_storage_service.h b/sql/wsrep_storage_service.h
new file mode 100644
index 00000000000..6208300930f
--- /dev/null
+++ b/sql/wsrep_storage_service.h
@@ -0,0 +1,48 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef WSREP_STORAGE_SERVICE_H
+#define WSREP_STORAGE_SERVICE_H
+
+#include "wsrep/storage_service.hpp"
+#include "wsrep/client_state.hpp"
+
+class THD;
+class Wsrep_server_service;
+class Wsrep_storage_service :
+ public wsrep::storage_service,
+ public wsrep::high_priority_context
+{
+public:
+ Wsrep_storage_service(THD*);
+ ~Wsrep_storage_service();
+ int start_transaction(const wsrep::ws_handle&);
+ void adopt_transaction(const wsrep::transaction&);
+ int append_fragment(const wsrep::id&,
+ wsrep::transaction_id,
+ int flags,
+ const wsrep::const_buffer&);
+ int update_fragment_meta(const wsrep::ws_meta&);
+ int remove_fragments();
+ int commit(const wsrep::ws_handle&, const wsrep::ws_meta&);
+ int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&);
+ void store_globals();
+ void reset_globals();
+private:
+ friend class Wsrep_server_service;
+ THD* m_thd;
+};
+
+#endif /* WSREP_STORAGE_SERVICE_H */
diff --git a/sql/wsrep_tc.h b/sql/wsrep_tc.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index ce6d9688cb3..a96db7e6986 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -15,6 +15,8 @@
#include "mariadb.h"
#include "wsrep_thd.h"
+#include "wsrep_high_priority_service.h"
+#include "wsrep_storage_service.h"
#include "transaction.h"
#include "rpl_rli.h"
#include "log_event.h"
@@ -22,12 +24,16 @@
//#include "global_threads.h" // LOCK_thread_count, etc.
#include "sql_base.h" // close_thread_tables()
#include "mysqld.h" // start_wsrep_THD();
-
-#include "slave.h" // opt_log_slave_updates
-#include "rpl_filter.h"
+#include "wsrep_applier.h" // start_wsrep_THD();
+#include "mysql/service_wsrep.h"
+#include "debug_sync.h"
+#include "slave.h"
#include "rpl_rli.h"
#include "rpl_mi.h"
+static Wsrep_thd_queue* wsrep_rollback_queue = 0;
+static Wsrep_thd_queue* wsrep_post_rollback_queue = 0;
+
#if (__LP64__)
static volatile int64 wsrep_bf_aborts_counter(0);
#define WSREP_ATOMIC_LOAD_LONG my_atomic_load64
@@ -47,52 +53,6 @@ int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff,
return 0;
}
-/* must have (&thd->LOCK_thd_data) */
-void wsrep_client_rollback(THD *thd)
-{
- WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s",
- (longlong) thd->thread_id, thd->query());
-
- WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1);
-
- thd->wsrep_conflict_state= ABORTING;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- trans_rollback(thd);
-
- if (thd->locked_tables_mode && thd->lock)
- {
- WSREP_DEBUG("unlocking tables for BF abort (%lld)",
- (longlong) thd->thread_id);
- thd->locked_tables_list.unlock_locked_tables(thd);
- thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
- }
-
- if (thd->global_read_lock.is_acquired())
- {
- WSREP_DEBUG("unlocking GRL for BF abort (%lld)",
- (longlong) thd->thread_id);
- thd->global_read_lock.unlock_global_read_lock(thd);
- }
-
- /* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
-
- /* release explicit MDL locks */
- thd->mdl_context.release_explicit_locks();
-
- if (thd->get_binlog_table_maps())
- {
- WSREP_DEBUG("clearing binlog table map for BF abort (%lld)",
- (longlong) thd->thread_id);
- thd->clear_binlog_table_maps();
- }
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_conflict_state= ABORTED;
-}
-
-#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1
-#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2
-
static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
{
Relay_log_info* rli= new Relay_log_info(false);
@@ -135,292 +95,53 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
return rgi;
}
-static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow)
+static void wsrep_replication_process(THD *thd,
+ void* arg __attribute__((unused)))
{
- shadow->options = thd->variables.option_bits;
- shadow->server_status = thd->server_status;
- shadow->wsrep_exec_mode = thd->wsrep_exec_mode;
- shadow->vio = thd->net.vio;
-
- // Disable general logging on applier threads
- thd->variables.option_bits |= OPTION_LOG_OFF;
- // Enable binlogging if opt_log_slave_updates is set
- if (opt_log_slave_updates)
- thd->variables.option_bits|= OPTION_BIN_LOG;
- else
- thd->variables.option_bits&= ~(OPTION_BIN_LOG);
-
+ DBUG_ENTER("wsrep_replication_process");
if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay");
/* thd->system_thread_info.rpl_sql_info isn't initialized. */
thd->system_thread_info.rpl_sql_info=
new rpl_sql_thread_info(thd->wsrep_rgi->rli->mi->rpl_filter);
- thd->wsrep_exec_mode= REPL_RECV;
- thd->net.vio= 0;
- thd->clear_error();
-
- shadow->tx_isolation = thd->variables.tx_isolation;
- thd->variables.tx_isolation = ISO_READ_COMMITTED;
- thd->tx_isolation = ISO_READ_COMMITTED;
+ Wsrep_applier_service applier_service(thd);
- shadow->db = thd->db.str;
- shadow->db_length = thd->db.length;
- shadow->user_time = thd->user_time;
- shadow->row_count_func= thd->get_row_count_func();
- thd->reset_db(&null_clex_str);
-}
+ WSREP_INFO("Starting applier thread %llu", thd->thread_id);
+ enum wsrep::provider::status
+ ret= Wsrep_server_state::get_provider().run_applier(&applier_service);
-static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
-{
- LEX_CSTRING db= {shadow->db, shadow->db_length };
- thd->variables.option_bits = shadow->options;
- thd->server_status = shadow->server_status;
- thd->wsrep_exec_mode = shadow->wsrep_exec_mode;
- thd->net.vio = shadow->vio;
- thd->variables.tx_isolation = shadow->tx_isolation;
- thd->user_time = shadow->user_time;
- thd->reset_db(&db);
+ WSREP_INFO("Applier thread exiting %d", ret);
+ mysql_mutex_lock(&LOCK_thread_count);
+ wsrep_close_applier(thd);
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
delete thd->system_thread_info.rpl_sql_info;
delete thd->wsrep_rgi->rli->mi;
delete thd->wsrep_rgi->rli;
-
+
thd->wsrep_rgi->cleanup_after_session();
delete thd->wsrep_rgi;
thd->wsrep_rgi = NULL;
- thd->set_row_count_func(shadow->row_count_func);
-}
-void wsrep_replay_transaction(THD *thd)
-{
- DBUG_ENTER("wsrep_replay_transaction");
- /* checking if BF trx must be replayed */
- if (thd->wsrep_conflict_state== MUST_REPLAY) {
- DBUG_ASSERT(wsrep_thd_trx_seqno(thd));
- if (thd->wsrep_exec_mode!= REPL_RECV) {
- if (thd->get_stmt_da()->is_sent())
- {
- WSREP_ERROR("replay issue, thd has reported status already");
- }
-
-
- /*
- PS reprepare observer should have been removed already.
- open_table() will fail if we have dangling observer here.
- */
- DBUG_ASSERT(thd->m_reprepare_observer == NULL);
-
- struct da_shadow
- {
- enum Diagnostics_area::enum_diagnostics_status status;
- ulonglong affected_rows;
- ulonglong last_insert_id;
- char message[MYSQL_ERRMSG_SIZE];
- };
- struct da_shadow da_status;
- da_status.status= thd->get_stmt_da()->status();
- if (da_status.status == Diagnostics_area::DA_OK)
- {
- da_status.affected_rows= thd->get_stmt_da()->affected_rows();
- da_status.last_insert_id= thd->get_stmt_da()->last_insert_id();
- strmake(da_status.message,
- thd->get_stmt_da()->message(),
- sizeof(da_status.message)-1);
- }
-
- thd->get_stmt_da()->reset_diagnostics_area();
-
- thd->wsrep_conflict_state= REPLAYING;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
-
- thd->reset_for_next_command();
- thd->reset_killed();
- close_thread_tables(thd);
- if (thd->locked_tables_mode && thd->lock)
- {
- WSREP_DEBUG("releasing table lock for replaying (%lld)",
- (longlong) thd->thread_id);
- thd->locked_tables_list.unlock_locked_tables(thd);
- thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
- }
- thd->mdl_context.release_transactional_locks();
- /*
- Replaying will call MYSQL_START_STATEMENT when handling
- BEGIN Query_log_event so end statement must be called before
- replaying.
- */
- MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
- thd->m_statement_psi= NULL;
- thd->m_digest= NULL;
- thd_proc_info(thd, "WSREP replaying trx");
- WSREP_DEBUG("replay trx: %s %lld",
- thd->query() ? thd->query() : "void",
- (long long)wsrep_thd_trx_seqno(thd));
- struct wsrep_thd_shadow shadow;
- wsrep_prepare_bf_thd(thd, &shadow);
-
- /* From trans_begin() */
- thd->variables.option_bits|= OPTION_BEGIN;
- thd->server_status|= SERVER_STATUS_IN_TRANS;
-
- int rcode = wsrep->replay_trx(wsrep,
- &thd->wsrep_ws_handle,
- (void *)thd);
-
- wsrep_return_from_bf_mode(thd, &shadow);
- if (thd->wsrep_conflict_state!= REPLAYING)
- WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state );
-
- mysql_mutex_lock(&thd->LOCK_thd_data);
-
- switch (rcode)
- {
- case WSREP_OK:
- thd->wsrep_conflict_state= NO_CONFLICT;
- wsrep->post_commit(wsrep, &thd->wsrep_ws_handle);
- WSREP_DEBUG("trx_replay successful for: %lld %lld",
- (longlong) thd->thread_id, (longlong) thd->real_id);
- if (thd->get_stmt_da()->is_sent())
- {
- WSREP_WARN("replay ok, thd has reported status");
- }
- else if (thd->get_stmt_da()->is_set())
- {
- if (thd->get_stmt_da()->status() != Diagnostics_area::DA_OK &&
- thd->get_stmt_da()->status() != Diagnostics_area::DA_OK_BULK)
- {
- WSREP_WARN("replay ok, thd has error status %d",
- thd->get_stmt_da()->status());
- }
- }
- else
- {
- if (da_status.status == Diagnostics_area::DA_OK)
- {
- my_ok(thd,
- da_status.affected_rows,
- da_status.last_insert_id,
- da_status.message);
- }
- else
- {
- my_ok(thd);
- }
- }
- break;
- case WSREP_TRX_FAIL:
- if (thd->get_stmt_da()->is_sent())
- {
- WSREP_ERROR("replay failed, thd has reported status");
- }
- else
- {
- WSREP_DEBUG("replay failed, rolling back");
- }
- thd->wsrep_conflict_state= ABORTED;
- wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle);
- break;
- default:
- WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
- rcode, thd->get_db(),
- thd->query() ? thd->query() : "void");
- /* we're now in inconsistent state, must abort */
-
- /* http://bazaar.launchpad.net/~codership/codership-mysql/5.6/revision/3962#sq… */
- mysql_mutex_unlock(&thd->LOCK_thd_data);
-
- unireg_abort(1);
- break;
- }
-
- wsrep_cleanup_transaction(thd);
-
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- wsrep_replaying--;
- WSREP_DEBUG("replaying decreased: %d, thd: %lld",
- wsrep_replaying, (longlong) thd->thread_id);
- mysql_cond_broadcast(&COND_wsrep_replaying);
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
- }
- }
- DBUG_VOID_RETURN;
-}
-
-static void wsrep_replication_process(THD *thd)
-{
- int rcode;
- DBUG_ENTER("wsrep_replication_process");
-
- struct wsrep_thd_shadow shadow;
- wsrep_prepare_bf_thd(thd, &shadow);
-
- /* From trans_begin() */
- thd->variables.option_bits|= OPTION_BEGIN;
- thd->server_status|= SERVER_STATUS_IN_TRANS;
-
- rcode = wsrep->recv(wsrep, (void *)thd);
- DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode));
-
- WSREP_INFO("applier thread exiting (code:%d)", rcode);
-
- switch (rcode) {
- case WSREP_OK:
- case WSREP_NOT_IMPLEMENTED:
- case WSREP_CONN_FAIL:
- /* provider does not support slave operations / disconnected from group,
- * just close applier thread */
- break;
- case WSREP_NODE_FAIL:
- /* data inconsistency => SST is needed */
- /* Note: we cannot just blindly restart replication here,
- * SST might require server restart if storage engines must be
- * initialized after SST */
- WSREP_ERROR("node consistency compromised, aborting");
- wsrep_kill_mysql(thd);
- break;
- case WSREP_WARNING:
- case WSREP_TRX_FAIL:
- case WSREP_TRX_MISSING:
- /* these suggests a bug in provider code */
- WSREP_WARN("bad return from recv() call: %d", rcode);
- /* Shut down this node. */
- /* fall through */
- case WSREP_FATAL:
- /* Cluster connectivity is lost.
- *
- * If applier was killed on purpose (KILL_CONNECTION), we
- * avoid mysql shutdown. This is because the killer will then handle
- * shutdown processing (or replication restarting)
- */
- if (thd->killed != KILL_CONNECTION)
- {
- wsrep_kill_mysql(thd);
- }
- break;
- }
-
- mysql_mutex_lock(&LOCK_thread_count);
- wsrep_close_applier(thd);
- mysql_cond_broadcast(&COND_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
if(thd->has_thd_temporary_tables())
{
WSREP_WARN("Applier %lld has temporary tables at exit.",
thd->thread_id);
}
- wsrep_return_from_bf_mode(thd, &shadow);
DBUG_VOID_RETURN;
}
-static bool create_wsrep_THD(wsrep_thd_processor_fun processor)
+static bool create_wsrep_THD(Wsrep_thd_args* args)
{
ulong old_wsrep_running_threads= wsrep_running_threads;
pthread_t unused;
mysql_mutex_lock(&LOCK_thread_count);
+
bool res= pthread_create(&unused, &connection_attrib, start_wsrep_THD,
- (void*)processor);
+ args);
/*
if starting a thread on server startup, wait until the this thread's THD
is fully initialized (otherwise a THD initialization code might
@@ -435,7 +156,16 @@ static bool create_wsrep_THD(wsrep_thd_processor_fun processor)
void wsrep_create_appliers(long threads)
{
- if (!wsrep_connected)
+ /*
+ Todo: We should somehow verify here that the provider has been
+ connected. However, currently the wsrep_connected status variable
+ is updated in Wsrep_server_service::log_state_change() after the
+ Wsrep_server_state reaches connected state. Due to the differences
+ in Wsrep_server_state state machine with different SST methods,
+ it is not straightforward to wait for certain state. Perhaps
+ connecting state needs to be implemented separately.
+ */
+ if (false)
{
/* see wsrep_replication_start() for the logic */
if (wsrep_cluster_address && strlen(wsrep_cluster_address) &&
@@ -449,88 +179,188 @@ void wsrep_create_appliers(long threads)
}
long wsrep_threads=0;
- while (wsrep_threads++ < threads) {
- if (create_wsrep_THD(wsrep_replication_process))
+
+ while (wsrep_threads++ < threads)
+ {
+ Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, 0));
+ if (create_wsrep_THD(args))
+ {
WSREP_WARN("Can't create thread to manage wsrep replication");
+ }
}
}
-static void wsrep_rollback_process(THD *thd)
+static void wsrep_rollback_process(THD *rollbacker,
+ void *arg __attribute__((unused)))
{
DBUG_ENTER("wsrep_rollback_process");
- mysql_mutex_lock(&LOCK_wsrep_rollback);
- wsrep_aborting_thd= NULL;
-
- while (thd->killed == NOT_KILLED) {
- thd_proc_info(thd, "WSREP aborter idle");
- thd->mysys_var->current_mutex= &LOCK_wsrep_rollback;
- thd->mysys_var->current_cond= &COND_wsrep_rollback;
+ THD* thd= NULL;
+ DBUG_ASSERT(!wsrep_rollback_queue);
+ wsrep_rollback_queue= new Wsrep_thd_queue(rollbacker);
- mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback);
+ thd_proc_info(rollbacker, "wsrep aborter idle");
+ while ((thd= wsrep_rollback_queue->pop_front()) != NULL)
+ {
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ wsrep::client_state& cs(thd->wsrep_cs());
+ const wsrep::transaction& tx(cs.transaction());
+ if (tx.state() == wsrep::transaction::s_aborted)
+ {
+ WSREP_DEBUG("rollbacker thd already aborted: %llu state: %d",
+ (long long)thd->real_id,
+ tx.state());
- WSREP_DEBUG("WSREP rollback thread wakes for signal");
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ continue;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
- mysql_mutex_lock(&thd->mysys_var->mutex);
- thd_proc_info(thd, "WSREP aborter active");
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- mysql_mutex_unlock(&thd->mysys_var->mutex);
+ thd_proc_info(rollbacker, "wsrep aborter active");
- /* check for false alarms */
- if (!wsrep_aborting_thd)
+ wsrep::transaction_id transaction_id(thd->wsrep_trx().id());
+ if (thd->wsrep_trx().is_streaming() &&
+ thd->wsrep_trx().bf_aborted_in_total_order())
{
- WSREP_DEBUG("WSREP rollback thread has empty abort queue");
- }
- /* process all entries in the queue */
- while (wsrep_aborting_thd) {
- THD *aborting;
- wsrep_aborting_thd_t next = wsrep_aborting_thd->next;
- aborting = wsrep_aborting_thd->aborting_thd;
- my_free(wsrep_aborting_thd);
- wsrep_aborting_thd= next;
- /*
- * must release mutex, appliers my want to add more
- * aborting thds in our work queue, while we rollback
- */
- mysql_mutex_unlock(&LOCK_wsrep_rollback);
-
- mysql_mutex_lock(&aborting->LOCK_thd_data);
- if (aborting->wsrep_conflict_state== ABORTED)
+ thd->store_globals();
+ thd->wsrep_cs().store_globals();
+ if (thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority)
+ {
+ DBUG_ASSERT(thd->wsrep_applier_service);
+ thd->wsrep_applier_service->rollback(wsrep::ws_handle(),
+ wsrep::ws_meta());
+ thd->wsrep_applier_service->after_apply();
+ /* Will free THD */
+ Wsrep_server_state::instance().server_service().
+ release_high_priority_service(thd->wsrep_applier_service);
+ }
+ else
{
- WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d",
- (long long)aborting->real_id,
- aborting->wsrep_conflict_state);
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ /* prepare THD for rollback processing */
+ thd->reset_for_next_command(true);
+ thd->lex->sql_command= SQLCOM_ROLLBACK;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ /* Perform a client rollback, restore globals and signal
+ the victim only when all the resources have been
+ released */
+ thd->wsrep_cs().client_service().bf_rollback();
+ thd->reset_globals();
+ thd->wsrep_cs().sync_rollback_complete();
+ }
+ }
+ else if (wsrep_thd_is_applying(thd))
+ {
+ WSREP_DEBUG("rollbacker aborting SR thd: (%lld %llu)",
+ thd->thread_id, (long long)thd->real_id);
+ DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_high_priority);
+ /* Must be streaming and must have been removed from the
+ server state streaming appliers map. */
+ DBUG_ASSERT(thd->wsrep_trx().is_streaming());
+ DBUG_ASSERT(!Wsrep_server_state::instance().find_streaming_applier(
+ thd->wsrep_trx().server_id(),
+ thd->wsrep_trx().id()));
+ DBUG_ASSERT(thd->wsrep_applier_service);
+
+ /* Fragment removal should happen before rollback to make
+ the transaction non-observable in SR table after the rollback
+ completes. For correctness the order does not matter here,
+ but currently it is mandated by checks in some MTR tests. */
+ Wsrep_storage_service* storage_service=
+ static_cast<Wsrep_storage_service*>(
+ Wsrep_server_state::instance().server_service().storage_service(
+ *thd->wsrep_applier_service));
+ storage_service->store_globals();
+ storage_service->adopt_transaction(thd->wsrep_trx());
+ storage_service->remove_fragments();
+ storage_service->commit(wsrep::ws_handle(transaction_id, 0),
+ wsrep::ws_meta());
+ Wsrep_server_state::instance().server_service().release_storage_service(storage_service);
+ thd->store_globals();
+ thd->wsrep_cs().store_globals();
+ thd->wsrep_applier_service->rollback(wsrep::ws_handle(),
+ wsrep::ws_meta());
+ thd->wsrep_applier_service->after_apply();
+ /* Will free THD */
+ Wsrep_server_state::instance().server_service()
+ .release_high_priority_service(thd->wsrep_applier_service);
- mysql_mutex_unlock(&aborting->LOCK_thd_data);
- mysql_mutex_lock(&LOCK_wsrep_rollback);
- continue;
+ }
+ else
+ {
+ if (thd->wsrep_trx().is_streaming())
+ {
+ Wsrep_storage_service* storage_service=
+ static_cast<Wsrep_storage_service*>(
+ Wsrep_server_state::instance().server_service().
+ storage_service(thd->wsrep_cs().client_service()));
+
+ storage_service->store_globals();
+ storage_service->adopt_transaction(thd->wsrep_trx());
+ storage_service->remove_fragments();
+ storage_service->commit(wsrep::ws_handle(transaction_id, 0),
+ wsrep::ws_meta());
+ Wsrep_server_state::instance().server_service().
+ release_storage_service(storage_service);
}
- aborting->wsrep_conflict_state= ABORTING;
+ thd->store_globals();
+ thd->wsrep_cs().store_globals();
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ /* prepare THD for rollback processing */
+ thd->reset_for_next_command();
+ thd->lex->sql_command= SQLCOM_ROLLBACK;
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ /* Perform a client rollback, restore globals and signal
+ the victim only when all the resources have been
+ released */
+ thd->wsrep_cs().client_service().bf_rollback();
+ thd->reset_globals();
+ thd->wsrep_cs().sync_rollback_complete();
+ WSREP_DEBUG("rollbacker aborted thd: (%llu %llu)",
+ thd->thread_id, (long long)thd->real_id);
+ }
- mysql_mutex_unlock(&aborting->LOCK_thd_data);
+ thd_proc_info(rollbacker, "wsrep aborter idle");
+ }
+
+ delete wsrep_rollback_queue;
+ wsrep_rollback_queue= NULL;
- set_current_thd(aborting);
- aborting->store_globals();
+ sql_print_information("WSREP: rollbacker thread exiting");
- mysql_mutex_lock(&aborting->LOCK_thd_data);
- wsrep_client_rollback(aborting);
- WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %lld)",
- (longlong) aborting->thread_id,
- (longlong) aborting->real_id);
- mysql_mutex_unlock(&aborting->LOCK_thd_data);
+ DBUG_ASSERT(rollbacker->killed != NOT_KILLED);
+ DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting"));
+ DBUG_VOID_RETURN;
+}
- set_current_thd(thd);
- thd->store_globals();
+static void wsrep_post_rollback_process(THD *post_rollbacker,
+ void *arg __attribute__((unused)))
+{
+ DBUG_ENTER("wsrep_post_rollback_process");
+ THD* thd= NULL;
- mysql_mutex_lock(&LOCK_wsrep_rollback);
- }
+ DBUG_ASSERT(!wsrep_post_rollback_queue);
+ wsrep_post_rollback_queue= new Wsrep_thd_queue(post_rollbacker);
+
+ while ((thd= wsrep_post_rollback_queue->pop_front()) != NULL)
+ {
+ thd->store_globals();
+ wsrep::client_state& cs(thd->wsrep_cs());
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting);
+ WSREP_DEBUG("post rollbacker calling post rollback for thd %llu, conf %s",
+ thd->thread_id, wsrep_thd_transaction_state_str(thd));
+
+ cs.after_rollback();
+ DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborted);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
}
- mysql_mutex_unlock(&LOCK_wsrep_rollback);
- sql_print_information("WSREP: rollbacker thread exiting");
+ delete wsrep_post_rollback_queue;
+ wsrep_post_rollback_queue= NULL;
- DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting"));
+ DBUG_ASSERT(post_rollbacker->killed != NOT_KILLED);
+ DBUG_PRINT("wsrep",("wsrep post rollbacker thread exiting"));
DBUG_VOID_RETURN;
}
@@ -538,12 +368,19 @@ void wsrep_create_rollbacker()
{
if (wsrep_provider && strcasecmp(wsrep_provider, "none"))
{
+ Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0);
+
/* create rollbacker */
- if (create_wsrep_THD(wsrep_rollback_process))
+ if (create_wsrep_THD(args))
WSREP_WARN("Can't create thread to manage wsrep rollback");
- }
-}
+ /* create post_rollbacker */
+ args= new Wsrep_thd_args(wsrep_post_rollback_process, 0);
+ if (create_wsrep_THD(args))
+ WSREP_WARN("Can't create thread to manage wsrep post rollback");
+ }
+}
+#if 0
void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe)
{
if (thd_ptr)
@@ -553,116 +390,51 @@ void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe)
}
}
-enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd, my_bool sync)
-{
- enum wsrep_conflict_state state = NO_CONFLICT;
- if (thd)
- {
- if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
-
- state = thd->wsrep_conflict_state;
- if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
- return state;
-}
-
-my_bool wsrep_thd_is_wsrep(THD *thd)
-{
- my_bool status = FALSE;
- if (thd)
- {
- status = (WSREP(thd) && WSREP_PROVIDER_EXISTS);
- }
- return status;
-}
-
-my_bool wsrep_thd_is_BF(THD *thd, my_bool sync)
-{
- my_bool status = FALSE;
- if (thd)
- {
- // THD can be BF only if provider exists
- if (wsrep_thd_is_wsrep(thd))
- {
- if (sync)
- mysql_mutex_lock(&thd->LOCK_thd_data);
-
- status = ((thd->wsrep_exec_mode == REPL_RECV) ||
- (thd->wsrep_exec_mode == TOTAL_ORDER));
- if (sync)
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
- }
- return status;
-}
+#endif
+/*
+ Start async rollback process
-extern "C"
-my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
+ Asserts thd->LOCK_thd_data ownership
+ */
+void wsrep_fire_rollbacker(THD *thd)
{
- bool status = FALSE;
- if (thd_ptr)
+ DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting);
+ DBUG_PRINT("wsrep",("enqueuing trx abort for %llu", thd->thread_id));
+ WSREP_DEBUG("enqueuing trx abort for (%llu)", thd->thread_id);
+ if (wsrep_rollback_queue->push_back(thd))
{
- THD* thd = (THD*)thd_ptr;
- if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
-
- status = ((thd->wsrep_exec_mode == REPL_RECV) ||
- (thd->wsrep_exec_mode == TOTAL_ORDER) ||
- (thd->wsrep_exec_mode == LOCAL_COMMIT));
- if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
+ WSREP_WARN("duplicate thd %llu for rollbacker",
+ thd->thread_id);
}
- return status;
}
-extern "C"
-my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
-{
- bool status = FALSE;
- if (thd_ptr)
- {
- THD* thd = (THD*)thd_ptr;
- if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
-
- status = (thd->wsrep_exec_mode == LOCAL_STATE);
- if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
- return status;
-}
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal)
{
+ DBUG_ENTER("wsrep_abort_thd");
THD *victim_thd = (THD *) victim_thd_ptr;
THD *bf_thd = (THD *) bf_thd_ptr;
- DBUG_ENTER("wsrep_abort_thd");
-
+ mysql_mutex_lock(&victim_thd->LOCK_thd_data);
if ( (WSREP(bf_thd) ||
( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
- bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) &&
- victim_thd)
+ wsrep_thd_is_toi(bf_thd)) ) &&
+ victim_thd &&
+ !wsrep_thd_is_aborting(victim_thd))
{
- if ((victim_thd->wsrep_conflict_state == MUST_ABORT) ||
- (victim_thd->wsrep_conflict_state == ABORTED) ||
- (victim_thd->wsrep_conflict_state == ABORTING))
- {
- WSREP_DEBUG("wsrep_abort_thd called by %llu with victim %llu already "
- "aborted. Ignoring.",
- (bf_thd) ? (long long)bf_thd->real_id : 0,
- (long long)victim_thd->real_id);
- DBUG_RETURN(1);
- }
-
- WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ?
- (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id);
- ha_abort_transaction(bf_thd, victim_thd, signal);
+ WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ?
+ (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id);
+ mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
+ ha_abort_transaction(bf_thd, victim_thd, signal);
+ mysql_mutex_lock(&victim_thd->LOCK_thd_data);
}
else
{
WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd);
}
-
+ mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
DBUG_RETURN(1);
}
-
-extern "C"
+#if 0
int wsrep_thd_in_locking_session(void *thd_ptr)
{
if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) {
@@ -676,3 +448,27 @@ bool wsrep_thd_has_explicit_locks(THD *thd)
assert(thd);
return thd->mdl_context.has_explicit_locks();
}
+
+#endif
+
+bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd)
+{
+ WSREP_LOG_THD((THD*)bf_thd, "BF aborter before");
+ WSREP_LOG_THD(victim_thd, "victim before");
+ wsrep::seqno bf_seqno(bf_thd->wsrep_trx().ws_meta().seqno());
+ bool ret;
+ if (wsrep_thd_is_toi(bf_thd))
+ {
+ ret= victim_thd->wsrep_cs().total_order_bf_abort(bf_seqno);
+ }
+ else
+ {
+ ret= victim_thd->wsrep_cs().bf_abort(bf_seqno);
+ }
+ if (ret)
+ {
+ my_atomic_add64(&wsrep_bf_aborts_counter, 1);
+ }
+ return ret;
+}
+
diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h
index 5900668f3fb..a2fdd7d1a36 100644
--- a/sql/wsrep_thd.h
+++ b/sql/wsrep_thd.h
@@ -18,37 +18,220 @@
#ifndef WSREP_THD_H
#define WSREP_THD_H
-#ifdef WITH_WSREP
-
+#include "mysql/service_wsrep.h"
#include "sql_class.h"
+#include "wsrep_utils.h"
+#include <deque>
+class Wsrep_thd_queue
+{
+public:
+ Wsrep_thd_queue(THD* t) : thd(t)
+ {
+ mysql_mutex_init(key_LOCK_wsrep_thd_queue,
+ &LOCK_wsrep_thd_queue,
+ MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_thd_queue, NULL);
+ }
+ ~Wsrep_thd_queue()
+ {
+ mysql_mutex_destroy(&LOCK_wsrep_thd_queue);
+ mysql_cond_destroy(&COND_wsrep_thd_queue);
+ }
+ bool push_back(THD* thd)
+ {
+ DBUG_ASSERT(thd);
+ wsp::auto_lock lock(&LOCK_wsrep_thd_queue);
+ std::deque<THD*>::iterator it = queue.begin();
+ while (it != queue.end())
+ {
+ if (*it == thd)
+ {
+ return true;
+ }
+ it++;
+ }
+ queue.push_back(thd);
+ mysql_cond_signal(&COND_wsrep_thd_queue);
+ return false;
+ }
+ THD* pop_front()
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_thd_queue);
+ while (queue.empty())
+ {
+ if (thd->killed != NOT_KILLED)
+ return NULL;
+
+ thd->mysys_var->current_mutex= &LOCK_wsrep_thd_queue;
+ thd->mysys_var->current_cond= &COND_wsrep_thd_queue;
+
+ mysql_cond_wait(&COND_wsrep_thd_queue, &LOCK_wsrep_thd_queue);
+
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ }
+ THD* ret= queue.front();
+ queue.pop_front();
+ return ret;
+ }
+private:
+ THD* thd;
+ std::deque<THD*> queue;
+ mysql_mutex_t LOCK_wsrep_thd_queue;
+ mysql_cond_t COND_wsrep_thd_queue;
+};
+
+void wsrep_prepare_bf_thd(THD*, struct wsrep_thd_shadow*);
+void wsrep_return_from_bf_mode(THD*, struct wsrep_thd_shadow*);
int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope);
-void wsrep_client_rollback(THD *thd);
+void wsrep_client_rollback(THD *thd, bool rollbacker = false);
void wsrep_replay_transaction(THD *thd);
void wsrep_create_appliers(long threads);
void wsrep_create_rollbacker();
+bool wsrep_bf_abort(const THD*, THD*);
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
my_bool signal);
-
-/*
- PA = Parallel Applying (on the slave side)
-*/
extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
-extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync);
-extern my_bool wsrep_thd_is_wsrep(void *thd_ptr);
+THD* wsrep_start_SR_THD(char *thread_stack);
+void wsrep_end_SR_THD(THD* thd);
+
+/**
+ Helper functions to override error status
+
+ In many contexts it is desirable to mask the original error status
+ set for THD or it is necessary to change OK status to error.
+ This function implements the common logic for the most
+ of the cases.
+
+ Rules:
+ * If the diagnostics are has OK or EOF status, override it unconditionally
+ * If the error is either ER_ERROR_DURING_COMMIT or ER_LOCK_DEADLOCK
+ it is usually the correct error status to be returned to client,
+ so don't override those by default
+ */
+
+static inline void wsrep_override_error(THD *thd, uint error)
+{
+ DBUG_ASSERT(error != ER_ERROR_DURING_COMMIT);
+ Diagnostics_area *da= thd->get_stmt_da();
+ if (da->is_ok() ||
+ da->is_eof() ||
+ !da->is_set() ||
+ (da->is_error() &&
+ da->sql_errno() != error &&
+ da->sql_errno() != ER_ERROR_DURING_COMMIT &&
+ da->sql_errno() != ER_LOCK_DEADLOCK))
+ {
+ da->reset_diagnostics_area();
+ my_error(error, MYF(0));
+ }
+}
+
+/**
+ Override error with additional wsrep status.
+ */
+static inline void wsrep_override_error(THD *thd, uint error,
+ enum wsrep::provider::status status)
+{
+ Diagnostics_area *da= thd->get_stmt_da();
+ if (da->is_ok() ||
+ !da->is_set() ||
+ (da->is_error() &&
+ da->sql_errno() != error &&
+ da->sql_errno() != ER_ERROR_DURING_COMMIT &&
+ da->sql_errno() != ER_LOCK_DEADLOCK))
+ {
+ da->reset_diagnostics_area();
+ my_error(error, MYF(0), status);
+ }
+}
+
+static inline void wsrep_override_error(THD* thd,
+ wsrep::client_error ce,
+ enum wsrep::provider::status status)
+{
+ DBUG_ASSERT(ce != wsrep::e_success);
+ switch (ce)
+ {
+ case wsrep::e_error_during_commit:
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
+ break;
+ case wsrep::e_deadlock_error:
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ break;
+ case wsrep::e_interrupted_error:
+ wsrep_override_error(thd, ER_QUERY_INTERRUPTED);
+ break;
+ case wsrep::e_size_exceeded_error:
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
+ break;
+ case wsrep::e_append_fragment_error:
+ /* TODO: Figure out better error number */
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
+ break;
+ case wsrep::e_not_supported_error:
+ wsrep_override_error(thd, ER_NOT_SUPPORTED_YET);
+ break;
+ case wsrep::e_timeout_error:
+ wsrep_override_error(thd, ER_LOCK_WAIT_TIMEOUT);
+ break;
+ default:
+ wsrep_override_error(thd, ER_UNKNOWN_ERROR);
+ break;
+ }
+}
+
+/**
+ Helper function to log THD wsrep context.
+
+ @param thd Pointer to THD
+ @param message Optional message
+ @param function Function where the call was made from
+ */
+static inline void wsrep_log_thd(THD *thd,
+ const char *message,
+ const char *function)
+{
+ WSREP_DEBUG("%s %s\n"
+ " thd: %llu thd_ptr: %p client_mode: %s client_state: %s trx_state: %s\n"
+ " next_trx_id: %lld trx_id: %lld seqno: %lld\n"
+ " is_streaming: %d fragments: %zu\n"
+ " sql_errno: %u message: %s\n"
+#define WSREP_THD_LOG_QUERIES
+#ifdef WSREP_THD_LOG_QUERIES
+ " command: %d query: %.72s"
+#endif /* WSREP_OBSERVER_LOG_QUERIES */
+ ,
+ function,
+ message ? message : "",
+ thd->thread_id,
+ thd,
+ wsrep_thd_client_mode_str(thd),
+ wsrep_thd_client_state_str(thd),
+ wsrep_thd_transaction_state_str(thd),
+ (long long)thd->wsrep_next_trx_id(),
+ (long long)thd->wsrep_trx_id(),
+ wsrep_thd_trx_seqno(thd),
+ thd->wsrep_trx().is_streaming(),
+ thd->wsrep_sr().fragments().size(),
+ (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0),
+ (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->message() : "")
+#ifdef WSREP_THD_LOG_QUERIES
+ , thd->lex->sql_command,
+ WSREP_QUERY(thd)
+#endif /* WSREP_OBSERVER_LOG_QUERIES */
+ );
+}
-enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
-extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);
-extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
-extern "C" int wsrep_thd_in_locking_session(void *thd_ptr);
+#define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__)
#else /* WITH_WSREP */
-#define wsrep_thd_is_BF(T, S) (0)
-#define wsrep_abort_thd(X,Y,Z) do { } while(0)
-#define wsrep_create_appliers(T) do { } while(0)
+//#define wsrep_thd_is_BF(T, S) (0)
+//#define wsrep_abort_thd(X,Y,Z) do { } while(0)
+//#define wsrep_create_appliers(T) do { } while(0)
-#endif
#endif /* WSREP_THD_H */
diff --git a/sql/wsrep_thd_pool.cc b/sql/wsrep_thd_pool.cc
new file mode 100644
index 00000000000..4a1ff7fde5f
--- /dev/null
+++ b/sql/wsrep_thd_pool.cc
@@ -0,0 +1,125 @@
+/* Copyright (C) 2015 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#include "my_global.h"
+#include "wsrep_api.h"
+#include "wsrep_mysqld.h"
+#include "wsrep_thd_pool.h"
+#include "wsrep_utils.h"
+#include "sql_class.h"
+//#include "global_threads.h"
+
+#include <list>
+
+static THD* wsrep_thd_pool_new_thd()
+{
+ THD *thd = new THD(next_thread_id());
+ thd->thread_stack= (char*) &thd;
+ thd->security_ctx->skip_grants();
+ thd->system_thread= SYSTEM_THREAD_GENERIC;
+
+ mysql_mutex_lock(&LOCK_thread_count);
+
+ thd->real_id=pthread_self(); // Keep purify happy
+
+ WSREP_DEBUG("Wsrep_thd_pool: creating system thread: %lld",
+ (long long)thd->thread_id);
+ thd->prior_thr_create_utime= thd->start_utime= thd->thr_create_utime;
+ (void) mysql_mutex_unlock(&LOCK_thread_count);
+
+ /* */
+ thd->variables.wsrep_on = 0;
+ /* No binlogging */
+ thd->variables.sql_log_bin = 0;
+ thd->variables.option_bits &= ~OPTION_BIN_LOG;
+ /* No general log */
+ thd->variables.option_bits |= OPTION_LOG_OFF;
+ /* Read committed isolation to avoid gap locking */
+ thd->variables.tx_isolation = ISO_READ_COMMITTED;
+
+ return thd;
+}
+
+Wsrep_thd_pool::Wsrep_thd_pool(size_t threads)
+ :
+ threads_(threads),
+ pool_()
+{
+ WSREP_DEBUG("Wsrep_thd_pool constructor");
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ pool_.reserve(threads);
+ for (size_t i= 0; i < threads; ++i)
+ {
+ pool_.push_back(wsrep_thd_pool_new_thd());
+ }
+}
+
+Wsrep_thd_pool::~Wsrep_thd_pool()
+{
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ while (!pool_.empty())
+ {
+ THD *thd = pool_.back();
+ WSREP_DEBUG("Wsrep_thd_pool: closing thread %lld",
+ (long long)thd->thread_id);
+
+ delete thd;
+
+ pool_.pop_back();
+ }
+}
+
+THD* Wsrep_thd_pool::get_thd(THD* thd)
+{
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ THD *ret= NULL;
+ if (pool_.empty())
+ {
+ ret= wsrep_thd_pool_new_thd();
+ }
+ else
+ {
+ ret= pool_.back();
+ pool_.pop_back();
+ }
+ if (thd)
+ {
+ ret->thread_stack = thd->thread_stack;
+ }
+ else
+ {
+ ret->thread_stack= (char*) &ret;
+ }
+ ret->store_globals();
+ return ret;
+}
+
+void Wsrep_thd_pool::release_thd(THD* thd)
+{
+ DBUG_ASSERT(!thd->mdl_context.has_locks());
+ DBUG_ASSERT(!thd->open_tables);
+ DBUG_ASSERT(thd->transaction.stmt.is_empty());
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ if (pool_.size() < threads_)
+ {
+ pool_.push_back(thd);
+ }
+ else
+ {
+ delete thd;
+ }
+}
+
diff --git a/sql/wsrep_thd_pool.h b/sql/wsrep_thd_pool.h
new file mode 100644
index 00000000000..af335ac3b87
--- /dev/null
+++ b/sql/wsrep_thd_pool.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2015 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#ifndef WSREP_THD_POOL_H
+#define WSREP_THD_POOL_H
+
+#include <cstddef>
+#include <vector>
+
+class THD;
+
+class Wsrep_thd_pool
+{
+public:
+ Wsrep_thd_pool(size_t threads = 10);
+ ~Wsrep_thd_pool();
+ THD* get_thd(THD*);
+ void release_thd(THD*);
+private:
+ size_t threads_;
+ std::vector<THD*> pool_;
+};
+
+#endif /* !WSREP_THD_POOL_H */
diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h
new file mode 100644
index 00000000000..cf78912195a
--- /dev/null
+++ b/sql/wsrep_trans_observer.h
@@ -0,0 +1,369 @@
+/* Copyright 2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef WSREP_TRANS_OBSERVER_H
+#define WSREP_TRANS_OBSERVER_H
+
+#include "my_global.h"
+#include "mysql/service_wsrep.h"
+#include "wsrep_applier.h" /* wsrep_apply_error */
+#include "wsrep_xid.h"
+#include "wsrep_thd.h"
+
+#include "my_dbug.h"
+
+class THD;
+
+/*
+ Return true if THD has active wsrep transaction.
+ */
+static inline bool wsrep_is_active(THD* thd)
+{
+ return (wsrep_on(thd) && thd->wsrep_cs().transaction().active());
+}
+
+/*
+ Return true if THD is either committing a transaction or statement
+ is autocommit.
+ */
+static inline bool wsrep_is_real(THD* thd, bool all)
+{
+ return (all || thd->transaction.all.ha_list == 0);
+}
+
+static inline int wsrep_check_pk(THD* thd)
+{
+ if (!wsrep_certify_nonPK)
+ {
+ for (TABLE* table= thd->open_tables; table != NULL; table= table->next)
+ {
+ if (table->key_info == NULL || table->s->primary_key == MAX_KEY)
+ {
+ WSREP_DEBUG("No primary key found for table %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static inline bool wsrep_streaming_enabled(THD* thd)
+{
+ return (thd->wsrep_sr().fragment_size() > 0);
+}
+
+
+static inline int wsrep_start_transaction(THD* thd, wsrep_trx_id_t trx_id)
+{
+ return (wsrep_on(thd) ?
+ thd->wsrep_cs().start_transaction(wsrep::transaction_id(trx_id)) :
+ 0);
+}
+
+/**/
+static inline int wsrep_start_trx_if_not_started(THD* thd)
+{
+ int ret= 0;
+ DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_local);
+ if (thd->wsrep_trx().active() == false)
+ {
+ ret= wsrep_start_transaction(thd, thd->wsrep_next_trx_id());
+ }
+ return ret;
+}
+
+/*
+ Called after each row operation.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_after_row(THD* thd, bool)
+{
+ if (wsrep_on(thd) && wsrep_thd_is_local(thd))
+ {
+ if (wsrep_check_pk(thd))
+ {
+ return 1;
+ }
+ else if (wsrep_streaming_enabled(thd))
+ {
+ return thd->wsrep_cs().after_row();
+ }
+ }
+ return 0;
+}
+
+/*
+ Called before the transaction is prepared.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_before_prepare(THD* thd, bool all)
+{
+ WSREP_DEBUG("wsrep_before_prepare: %d", wsrep_is_real(thd, all));
+ int ret= ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ?
+ thd->wsrep_cs().before_prepare() : 0);
+ DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error());
+ return ret;
+}
+
+/*
+ Called after the transaction has been prepared.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_after_prepare(THD* thd, bool all)
+{
+ WSREP_DEBUG("wsrep_after_prepare: %d", wsrep_is_real(thd, all));
+ int ret= ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ?
+ thd->wsrep_cs().after_prepare() : 0);
+ DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error() ||
+ thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay);
+ return ret;
+}
+
+
+/*
+ Called before the transaction is committed.
+
+ This function must be called from both client and
+ applier contexts before commit.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_before_commit(THD* thd, bool all)
+{
+ WSREP_DEBUG("wsrep_before_commit: %d, %lld",
+ wsrep_is_real(thd, all),
+ wsrep_thd_trx_seqno(thd));
+ return ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ?
+ wsrep_xid_init(&thd->wsrep_xid,
+ thd->wsrep_cs().transaction().ws_meta().gtid()),
+ thd->wsrep_cs().before_commit() : 0);
+}
+
+/*
+ Called after the transaction has been ordered for commit.
+
+ This function must be called from both client and
+ applier contexts after the commit has been ordered.
+
+ @param thd Pointer to THD
+ @param all
+ @param err Error buffer in case of applying error
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_ordered_commit(THD* thd,
+ bool all,
+ const wsrep_apply_error&)
+{
+ WSREP_DEBUG("wsrep_ordered_commit: %d", wsrep_is_real(thd, all));
+ return ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ?
+ thd->wsrep_cs().ordered_commit() : 0);
+}
+
+/*
+ Called after the transaction has been committed.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_after_commit(THD* thd, bool all)
+{
+ WSREP_DEBUG("wsrep_after_commit: %d, %d, %lu", wsrep_is_real(thd, all),
+ wsrep_is_active(thd), wsrep_thd_trx_seqno(thd));
+ bool run_after_commit= (wsrep_is_real(thd, all) && wsrep_is_active(thd));
+ if (run_after_commit)
+ {
+ return (wsrep_ordered_commit_if_no_binlog(thd, all) ||
+ (wsrep_xid_init(&thd->wsrep_xid, wsrep::gtid::undefined()),
+ thd->wsrep_cs().after_commit()));
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*
+ Called before the transaction is rolled back.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_before_rollback(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_before_rollback");
+ int ret= 0;
+ if (wsrep_is_active(thd))
+ {
+ if (!all && thd->in_active_multi_stmt_transaction() &&
+ thd->wsrep_trx().is_streaming() &&
+ !wsrep_stmt_rollback_is_safe(thd))
+ {
+ /* Non-safe statement rollback during SR multi statement
+ transasction. Self abort the transaction, the actual rollback
+ and error handling will be done in after statement phase. */
+ wsrep_thd_self_abort(thd);
+ ret= 0;
+ }
+ else if (wsrep_is_real(thd, all) &&
+ thd->wsrep_trx().state() != wsrep::transaction::s_aborted)
+ {
+ /* Real transaction rolling back and wsrep abort not completed
+ yet */
+ /* Reset XID so that it does not trigger writing serialization
+ history in InnoDB. This needs to be avoided because rollback
+ may happen out of order and replay may follow. */
+ wsrep_xid_init(&thd->wsrep_xid, wsrep::gtid::undefined());
+ ret= thd->wsrep_cs().before_rollback();
+ }
+ }
+ DBUG_RETURN(ret);
+}
+
+/*
+ Called after the transaction has been rolled back.
+
+ Return zero on succes, non-zero on failure.
+ */
+static inline int wsrep_after_rollback(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_rollback");
+ DBUG_RETURN((wsrep_is_real(thd, all) && wsrep_is_active(thd) &&
+ thd->wsrep_cs().transaction().state() !=
+ wsrep::transaction::s_aborted) ?
+ thd->wsrep_cs().after_rollback() : 0);
+}
+
+static inline int wsrep_before_statement(THD* thd)
+{
+ return (wsrep_on(thd) ? thd->wsrep_cs().before_statement() : 0);
+}
+
+static inline
+// enum wsrep::client_state::after_statement_result
+int wsrep_after_statement(THD* thd)
+{
+ return (wsrep_on((const void*)thd) ?
+ thd->wsrep_cs().after_statement() : 0);
+}
+
+static inline void wsrep_after_apply(THD* thd)
+{
+ DBUG_ASSERT(wsrep_thd_is_applying(thd));
+ WSREP_DEBUG("wsrep_after_apply %lld", thd->thread_id);
+ thd->wsrep_cs().after_applying();
+}
+
+static inline void wsrep_open(THD* thd)
+{
+ DBUG_ENTER("wsrep_open");
+ if (wsrep_global_on())
+ {
+ thd->wsrep_cs().open(wsrep::client_id(thd->thread_id));
+ thd->wsrep_cs().debug_log_level(wsrep_debug);
+ }
+ DBUG_VOID_RETURN;
+}
+
+static inline void wsrep_close(THD* thd)
+{
+ DBUG_ENTER("wsrep_close");
+ if (wsrep_global_on())
+ {
+ thd->wsrep_cs().close();
+ }
+ DBUG_VOID_RETURN;
+}
+
+static inline int wsrep_before_command(THD* thd)
+{
+ return (wsrep_global_on() ? thd->wsrep_cs().before_command() : 0);
+}
+/*
+ Called after each command.
+
+ Return zero on success, non-zero on failure.
+*/
+static inline void wsrep_after_command_before_result(THD* thd)
+{
+ if (wsrep_global_on())
+ {
+ thd->wsrep_cs().after_command_before_result();
+ }
+}
+
+static inline void wsrep_after_command_after_result(THD* thd)
+{
+ if (wsrep_global_on())
+ {
+ thd->wsrep_cs().after_command_after_result();
+ }
+}
+
+static inline void wsrep_after_command_ignore_result(THD* thd)
+{
+ wsrep_after_command_before_result(thd);
+ DBUG_ASSERT(!thd->wsrep_cs().current_error());
+ wsrep_after_command_after_result(thd);
+}
+
+static inline enum wsrep::client_error wsrep_current_error(THD* thd)
+{
+ return thd->wsrep_cs().current_error();
+}
+
+static inline enum wsrep::provider::status
+wsrep_current_error_status(THD* thd)
+{
+ return thd->wsrep_cs().current_error_status();
+}
+
+
+/*
+ Commit an empty transaction.
+
+ If the transaction is real and the wsrep transaction is still active,
+ the transaction did not generate any rows or keys and is committed
+ as empty. Here the wsrep transaction is rolled back and after statement
+ step is performed to leave the wsrep transaction in the state as it
+ never existed.
+*/
+static inline void wsrep_commit_empty(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_commit_empty");
+ WSREP_DEBUG("wsrep_commit_empty(%llu)", thd->thread_id);
+ if (wsrep_is_real(thd, all) &&
+ wsrep_thd_is_local(thd) &&
+ thd->wsrep_trx().active())
+ {
+ bool have_error= wsrep_current_error(thd);
+ int ret= wsrep_before_rollback(thd, all) ||
+ wsrep_after_rollback(thd, all) ||
+ wsrep_after_statement(thd);
+ DBUG_ASSERT(!ret);
+ DBUG_ASSERT(have_error || !wsrep_current_error(thd));
+ if (ret)
+ {
+ WSREP_WARN("wsrep_commit_empty failed: %d", wsrep_current_error(thd));
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+#endif /* WSREP_TRANS_OBSERVER */
diff --git a/sql/wsrep_types.h b/sql/wsrep_types.h
new file mode 100644
index 00000000000..9da00e305a7
--- /dev/null
+++ b/sql/wsrep_types.h
@@ -0,0 +1,29 @@
+/* Copyright 2018 Codership Oy <info(a)codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/*
+ Wsrep typedefs to better conform to coding style.
+ */
+#ifndef WSREP_TYPES_H
+#define WSREP_TYPES_H
+
+#include "wsrep/seqno.hpp"
+#include "wsrep/view.hpp"
+
+typedef wsrep::id Wsrep_id;
+typedef wsrep::seqno Wsrep_seqno;
+typedef wsrep::view Wsrep_view;
+
+#endif /* WSREP_TYPES_H */
diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc
index 3c341e222b3..f0f82ac41b9 100644
--- a/sql/wsrep_utils.cc
+++ b/sql/wsrep_utils.cc
@@ -21,6 +21,8 @@
#endif
#include "mariadb.h"
+#include "my_global.h"
+#include "wsrep_api.h"
#include "wsrep_utils.h"
#include "wsrep_mysqld.h"
diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h
index 277cea9dc31..f6520dda86e 100644
--- a/sql/wsrep_utils.h
+++ b/sql/wsrep_utils.h
@@ -21,6 +21,27 @@
unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6);
size_t wsrep_guess_ip (char* buf, size_t buf_len);
+namespace wsp {
+class node_status
+{
+public:
+ node_status() : status(WSREP_MEMBER_UNDEFINED) {}
+ void set(wsrep_member_status_t new_status,
+ const wsrep_view_info_t* view = 0)
+ {
+ if (status != new_status || 0 != view)
+ {
+ wsrep_notify_status(new_status, view);
+ status = new_status;
+ }
+ }
+ wsrep_member_status_t get() const { return status; }
+private:
+ wsrep_member_status_t status;
+};
+} /* namespace wsp */
+
+extern wsp::node_status local_status;
/* returns the length of the host part of the address string */
size_t wsrep_host_len(const char* addr, size_t addr_len);
@@ -314,6 +335,17 @@ class string
char* string_;
};
+/* scope level lock */
+class auto_lock
+{
+public:
+ auto_lock(mysql_mutex_t* m) : m_(m) { mysql_mutex_lock(m_); }
+ ~auto_lock() { mysql_mutex_unlock(m_); }
+private:
+ mysql_mutex_t& operator =(mysql_mutex_t&);
+ mysql_mutex_t* const m_;
+};
+
#ifdef REMOVED
class lock
{
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index f8a494416e2..791bd1c2b2a 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -28,8 +28,6 @@
ulong wsrep_reject_queries;
-static long wsrep_prev_slave_threads = wsrep_slave_threads;
-
int wsrep_init_vars()
{
wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME));
@@ -157,15 +155,15 @@ bool wsrep_start_position_verify (const char* start_str)
static
-bool wsrep_set_local_position(const char* const value, size_t length,
- bool const sst)
+bool wsrep_set_local_position(THD* thd, const char* const value,
+ size_t length, bool const sst)
{
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);
if (sst) {
- return wsrep_sst_received (wsrep, uuid, seqno, NULL, 0, false);
+ wsrep_sst_received (thd, uuid, seqno, NULL, 0);
} else {
// initialization
local_uuid = uuid;
@@ -194,7 +192,7 @@ bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var)
As part of further verification, we try to update the value and catch
errors (if any).
*/
- if (wsrep_set_local_position(var->save_result.string_value.str,
+ if (wsrep_set_local_position(thd, var->save_result.string_value.str,
var->save_result.string_value.length,
true))
{
@@ -226,7 +224,7 @@ bool wsrep_start_position_init (const char* val)
return true;
}
- if (wsrep_set_local_position (val, strlen(val), false))
+ if (wsrep_set_local_position (NULL, val, strlen(val), false))
{
WSREP_ERROR("Failed to set initial wsep_start_position: %s", val);
return true;
@@ -263,25 +261,23 @@ static int get_provider_option_value(const char* opts,
static bool refresh_provider_options()
{
- DBUG_ASSERT(wsrep);
-
WSREP_DEBUG("refresh_provider_options: %s",
(wsrep_provider_options) ? wsrep_provider_options : "null");
- char* opts= wsrep->options_get(wsrep);
- if (opts)
+
+ try
{
- wsrep_provider_options_init(opts);
+ std::string opts= Wsrep_server_state::instance().provider().options();
+ wsrep_provider_options_init(opts.c_str());
get_provider_option_value(wsrep_provider_options,
(char*)"repl.max_ws_size",
&wsrep_max_ws_size);
- free(opts);
+ return false;
}
- else
+ catch (...)
{
WSREP_ERROR("Failed to get provider options");
return true;
}
- return false;
}
static int wsrep_provider_verify (const char* provider_str)
@@ -332,8 +328,6 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
{
bool rcode= false;
- bool wsrep_on_saved= thd->variables.wsrep_on;
- thd->variables.wsrep_on= false;
WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider);
@@ -344,12 +338,18 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
+ mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool);
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
- mysql_mutex_lock(&LOCK_global_system_variables);
+
+ /* provider status variables are allocated in provider library
+ and need to freed here, otherwise a dangling reference to
+ wsrep_status_vars would remain in THD
+ */
+ wsrep_free_status(thd);
if (wsrep_inited == 1)
- wsrep_deinit(false);
+ wsrep_deinit();
char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider
//when fails
@@ -364,10 +364,10 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
// we sure don't want to use old address with new provider
wsrep_cluster_address_init(NULL);
wsrep_provider_options_init(NULL);
+ if (!rcode)
+ refresh_provider_options();
- thd->variables.wsrep_on= wsrep_on_saved;
-
- refresh_provider_options();
+ mysql_mutex_lock(&LOCK_global_system_variables);
return rcode;
}
@@ -390,19 +390,14 @@ void wsrep_provider_init (const char* value)
bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var)
{
- if (wsrep == NULL)
- {
- my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
- return true;
- }
return false;
}
bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type)
{
- DBUG_ASSERT(wsrep);
- wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options);
- if (ret != WSREP_OK)
+ enum wsrep::provider::status ret=
+ Wsrep_server_state::instance().provider().options(wsrep_provider_options);
+ if (ret)
{
WSREP_ERROR("Set options returned %d", ret);
refresh_provider_options();
@@ -468,18 +463,6 @@ bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var)
bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
{
- bool wsrep_on_saved;
-
- /* Do not proceed if wsrep provider is not loaded. */
- if (!wsrep)
- {
- WSREP_INFO("wsrep provider is not loaded, can't re(start) replication.");
- return false;
- }
-
- wsrep_on_saved= thd->variables.wsrep_on;
- thd->variables.wsrep_on= false;
-
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
@@ -487,16 +470,10 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
+ mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool);
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
- /*
- Unlock and lock LOCK_wsrep_slave_threads to maintain lock order & avoid
- any potential deadlock.
- */
- mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
- mysql_mutex_lock(&LOCK_global_system_variables);
- mysql_mutex_lock(&LOCK_wsrep_slave_threads);
if (wsrep_start_replication())
{
@@ -504,7 +481,13 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
wsrep_create_appliers(wsrep_slave_threads);
}
- thd->variables.wsrep_on= wsrep_on_saved;
+ /* locking order to be enforced is:
+ 1. LOCK_global_system_variables
+ 2. LOCK_wsrep_slave_threads
+ */
+ mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
+ mysql_mutex_lock(&LOCK_global_system_variables);
+ mysql_mutex_lock(&LOCK_wsrep_slave_threads);
return false;
}
@@ -594,10 +577,10 @@ void wsrep_node_address_init (const char* value)
static void wsrep_slave_count_change_update ()
{
- wsrep_slave_count_change = (wsrep_slave_threads - wsrep_prev_slave_threads);
- WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %d",
- wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change);
- wsrep_prev_slave_threads = wsrep_slave_threads;
+ // wsrep_running_threads = appliers threads + 2 rollbacker threads
+ wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_threads + 2);
+ WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %lu",
+ wsrep_slave_threads, wsrep_running_threads, wsrep_slave_count_change);
}
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
@@ -613,7 +596,7 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var)
{
- if (wsrep == NULL)
+ if (!WSREP_ON)
{
my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
return true;
@@ -638,17 +621,17 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var)
}
return false;
}
- wsrep_status_t ret(WSREP_WARNING);
+ int ret= 1;
if (new_wsrep_desync) {
- ret = wsrep->desync (wsrep);
- if (ret != WSREP_OK) {
- WSREP_WARN ("SET desync failed %d for schema: %s, query: %s",
- ret, thd->get_db(), thd->query());
+ ret= Wsrep_server_state::instance().provider().desync();
+ if (ret) {
+ WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", ret,
+ thd->db.str, WSREP_QUERY(thd));
my_error (ER_CANNOT_USER, MYF(0), "'desync'", thd->query());
return true;
}
} else {
- ret = wsrep->resync (wsrep);
+ ret= Wsrep_server_state::instance().provider().resync();
if (ret != WSREP_OK) {
WSREP_WARN ("SET resync failed %d for schema: %s, query: %s", ret,
thd->get_db(), thd->query());
@@ -661,32 +644,67 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var)
bool wsrep_desync_update (sys_var *self, THD* thd, enum_var_type type)
{
- DBUG_ASSERT(wsrep);
return false;
}
bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var)
{
- if (wsrep == NULL)
- {
- my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0));
+ return false;
+}
+
+bool wsrep_trx_fragment_size_check (sys_var *self, THD* thd, set_var* var)
+{
+ if (var->value == NULL) {
+ return false;
+ }
+
+ const ulong new_trx_fragment_size = var->value->val_uint();
+
+ if (!WSREP(thd) && new_trx_fragment_size > 0) {
+ push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_VALUE_FOR_VAR,
+ "Cannot set 'wsrep_trx_fragment_size' to a value other than "
+ "0 because wsrep is switched off.");
return true;
}
+
+ if (new_trx_fragment_size > 0 && !wsrep_provider_is_SR_capable()) {
+ push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_VALUE_FOR_VAR,
+ "Cannot set 'wsrep_trx_fragment_size' to a value other than "
+ "0 because the wsrep_provider does not support streaming "
+ "replication.");
+ return true;
+ }
+
return false;
}
-bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
+bool wsrep_trx_fragment_size_update(sys_var* self, THD *thd, enum_var_type)
{
- DBUG_ASSERT(wsrep);
+ WSREP_INFO("wsrep_trx_fragment_size_update: %lu", thd->variables.wsrep_trx_fragment_size);
+ if (thd->variables.wsrep_trx_fragment_size)
+ {
+ return thd->wsrep_cs().enable_streaming(
+ thd->wsrep_sr().fragment_unit(),
+ thd->variables.wsrep_trx_fragment_size);
+ }
+ else
+ {
+ thd->wsrep_cs().disable_streaming();
+ return false;
+ }
+}
+bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
+{
char max_ws_size_opt[128];
my_snprintf(max_ws_size_opt, sizeof(max_ws_size_opt),
- "repl.max_ws_size=%lu", wsrep_max_ws_size);
- wsrep_status_t ret= wsrep->options_set(wsrep, max_ws_size_opt);
- if (ret != WSREP_OK)
+ "repl.max_ws_size=%d", wsrep_max_ws_size);
+ enum wsrep::provider::status ret= Wsrep_server_state::instance().provider().options(max_ws_size_opt);
+ if (ret)
{
WSREP_ERROR("Set options returned %d", ret);
- refresh_provider_options();
return true;
}
return refresh_provider_options();
@@ -695,16 +713,17 @@ bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
static SHOW_VAR wsrep_status_vars[]=
{
{"connected", (char*) &wsrep_connected, SHOW_BOOL},
- {"ready", (char*) &wsrep_ready, SHOW_BOOL},
+ {"ready", (char*) &wsrep_show_ready, SHOW_FUNC},
{"cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
{"cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
{"cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},
{"cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH},
{"local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH},
- {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_SIMPLE_FUNC},
+ {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC},
{"provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
{"provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
{"provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
+ {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
{"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH}
};
@@ -713,6 +732,30 @@ static int show_var_cmp(const void *var1, const void *var2)
return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
}
+/*
+ * Status variables stuff below
+ */
+static inline void
+wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep_var)
+{
+ mysql->name = wsrep_var->name;
+ switch (wsrep_var->type) {
+ case WSREP_VAR_INT64:
+ mysql->value = (char*) &wsrep_var->value._int64;
+ mysql->type = SHOW_LONGLONG;
+ break;
+ case WSREP_VAR_STRING:
+ mysql->value = (char*) &wsrep_var->value._string;
+ mysql->type = SHOW_CHAR_PTR;
+ break;
+ case WSREP_VAR_DOUBLE:
+ mysql->value = (char*) &wsrep_var->value._double;
+ mysql->type = SHOW_DOUBLE;
+ break;
+ }
+}
+
+#ifdef OLD_MARIADB
int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
{
@@ -758,3 +801,67 @@ int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff,
v->name= 0; // terminator
return 0;
}
+#endif
+
+#if DYNAMIC
+// somehow this mysql status thing works only with statically allocated arrays.
+static SHOW_VAR* mysql_status_vars = NULL;
+static int mysql_status_len = -1;
+#else
+static SHOW_VAR mysql_status_vars[512 + 1];
+static const int mysql_status_len = 512;
+#endif
+
+static void export_wsrep_status_to_mysql(THD* thd)
+{
+ int wsrep_status_len, i;
+
+ thd->wsrep_status_vars = Wsrep_server_state::instance().status();
+
+ wsrep_status_len= thd->wsrep_status_vars.size();
+
+#if DYNAMIC
+ if (wsrep_status_len != mysql_status_len) {
+ void* tmp = realloc (mysql_status_vars,
+ (wsrep_status_len + 1) * sizeof(SHOW_VAR));
+ if (!tmp) {
+
+ sql_print_error ("Out of memory for wsrep status variables."
+ "Number of variables: %d", wsrep_status_len);
+ return;
+ }
+
+ mysql_status_len = wsrep_status_len;
+ mysql_status_vars = (SHOW_VAR*)tmp;
+ }
+ /* @TODO: fix this: */
+#else
+ if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len;
+#endif
+
+ for (i = 0; i < wsrep_status_len; i++)
+ {
+ mysql_status_vars[i].name= (char*)thd->wsrep_status_vars[i].name().c_str();
+ mysql_status_vars[i].value= (char*)thd->wsrep_status_vars[i].value().c_str();
+ mysql_status_vars[i].type= SHOW_CHAR;
+ }
+
+ mysql_status_vars[wsrep_status_len].name = NullS;
+ mysql_status_vars[wsrep_status_len].value = NullS;
+ mysql_status_vars[wsrep_status_len].type = SHOW_LONG;
+}
+
+int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff)
+{
+ if (WSREP_ON)
+ {
+ export_wsrep_status_to_mysql(thd);
+ var->type= SHOW_ARRAY;
+ var->value= (char *) &mysql_status_vars;
+ }
+ return 0;
+}
+void wsrep_free_status (THD* thd)
+{
+ thd->wsrep_status_vars.clear();
+}
diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h
index 7d3ff50f1d2..15187a542dc 100644
--- a/sql/wsrep_var.h
+++ b/sql/wsrep_var.h
@@ -90,10 +90,14 @@ extern bool wsrep_slave_threads_update UPDATE_ARGS;
extern bool wsrep_desync_check CHECK_ARGS;
extern bool wsrep_desync_update UPDATE_ARGS;
-extern bool wsrep_max_ws_size_check CHECK_ARGS;
+extern bool wsrep_trx_fragment_size_check CHECK_ARGS;
+extern bool wsrep_trx_fragment_size_update UPDATE_ARGS;
+
extern bool wsrep_max_ws_size_update UPDATE_ARGS;
extern bool wsrep_reject_queries_update UPDATE_ARGS;
+extern bool wsrep_reject_queries_update UPDATE_ARGS;
+
#else /* WITH_WSREP */
#define WSREP_NONE
diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc
index 2834100568a..a77d884a5a0 100644
--- a/sql/wsrep_xid.cc
+++ b/sql/wsrep_xid.cc
@@ -21,6 +21,7 @@
#include "sql_class.h"
#include "wsrep_mysqld.h" // for logging macros
+#include <sstream>
/*
* WSREPXid
*/
@@ -34,20 +35,23 @@
#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))
-void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
+void wsrep_xid_init(XID* xid, const wsrep::gtid& gtid)
{
xid->formatID= 1;
xid->gtrid_length= WSREP_XID_GTRID_LEN;
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;
- memcpy(xid->data + WSREP_XID_UUID_OFFSET, &uuid, sizeof(wsrep_uuid_t));
- int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno);
+ memcpy(xid->data + WSREP_XID_UUID_OFFSET,
+ gtid.id().data(), gtid.id().size());
+ long long seqno= gtid.seqno().get();
+ memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(seqno));
}
-int wsrep_is_wsrep_xid(const XID* xid)
+//extern "C"
+int wsrep_is_wsrep_xid(const void* xid_ptr)
{
+ const XID* xid= reinterpret_cast<const XID*>(xid_ptr);
return (xid->formatID == 1 &&
xid->gtrid_length == WSREP_XID_GTRID_LEN &&
xid->bqual_length == 0 &&
@@ -56,45 +60,27 @@ int wsrep_is_wsrep_xid(const XID* xid)
xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2));
}
-const wsrep_uuid_t* wsrep_xid_uuid(const XID& xid)
+wsrep::id wsrep_xid_uuid(const XID& xid)
{
+ wsrep::id ret(xid.data + WSREP_XID_UUID_OFFSET, 16);
if (wsrep_is_wsrep_xid(&xid))
- return reinterpret_cast<const wsrep_uuid_t*>(xid.data
- + WSREP_XID_UUID_OFFSET);
+ return wsrep::id(xid.data + WSREP_XID_UUID_OFFSET, 16);
else
- return &WSREP_UUID_UNDEFINED;
+ return wsrep::id::undefined();
}
-const unsigned char* wsrep_xid_uuid(const xid_t* xid)
+wsrep::seqno wsrep_xid_seqno(const XID& xid)
{
- DBUG_ASSERT(xid);
- return wsrep_xid_uuid(*xid)->data;
-}
-
-wsrep_seqno_t wsrep_xid_seqno(const XID& xid)
-{
- wsrep_seqno_t ret= WSREP_SEQNO_UNDEFINED;
if (wsrep_is_wsrep_xid(&xid))
{
- switch (xid.data[WSREP_XID_VERSION_OFFSET])
- {
- case WSREP_XID_VERSION_1:
- memcpy(&ret, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof ret);
- break;
- case WSREP_XID_VERSION_2:
- ret= sint8korr(xid.data + WSREP_XID_SEQNO_OFFSET);
- break;
- default:
- break;
- }
+ wsrep_seqno_t seqno;
+ memcpy(&seqno, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t));
+ return wsrep::seqno(seqno);
+ }
+ else
+ {
+ return wsrep::seqno::undefined();
}
- return ret;
-}
-
-long long wsrep_xid_seqno(const xid_t* xid)
-{
- DBUG_ASSERT(xid);
- return wsrep_xid_seqno(*xid);
}
static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
@@ -102,29 +88,29 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
XID* xid= static_cast<XID*>(arg);
handlerton* hton= plugin_data(plugin, handlerton *);
- if (hton->set_checkpoint)
+ if (hton->db_type == DB_TYPE_INNODB)
{
- const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid));
- char uuid_str[40] = {0, };
- wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str));
+ const wsrep::id uuid(wsrep_xid_uuid(*xid));
+ std::ostringstream oss;
+ oss << uuid;
WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld",
- uuid_str, (long long)wsrep_xid_seqno(*xid));
+ oss.str().c_str(), get_wsrep_xid_seqno(xid));
hton->set_checkpoint(hton, xid);
}
+
return FALSE;
}
-bool wsrep_set_SE_checkpoint(XID& xid)
+void wsrep_set_SE_checkpoint(XID& xid)
{
- return plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
- &xid);
+ plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid);
}
-bool wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
+void wsrep_set_SE_checkpoint(const wsrep::gtid& gtid)
{
XID xid;
- wsrep_xid_init(&xid, uuid, seqno);
- return wsrep_set_SE_checkpoint(xid);
+ wsrep_xid_init(&xid, gtid);
+ wsrep_set_SE_checkpoint(xid);
}
static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
@@ -135,47 +121,39 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
if (hton->get_checkpoint)
{
hton->get_checkpoint(hton, xid);
- const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid));
- char uuid_str[40] = {0, };
- wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str));
- WSREP_DEBUG("Read WSREPXid from InnoDB: %s:%lld",
- uuid_str, (long long)wsrep_xid_seqno(*xid));
+ std::ostringstream oss;
+ oss << wsrep_xid_uuid(*xid);
+ oss << ":";
+ oss << wsrep_xid_seqno(*xid);
+ WSREP_DEBUG("Read WSREPXid from InnoDB: %s", oss.str().c_str());
}
return FALSE;
}
-bool wsrep_get_SE_checkpoint(XID& xid)
+void wsrep_get_SE_checkpoint(XID& xid)
{
- return plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
+ plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
&xid);
}
-bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
+wsrep::gtid wsrep_get_SE_checkpoint()
{
- uuid= WSREP_UUID_UNDEFINED;
- seqno= WSREP_SEQNO_UNDEFINED;
-
XID xid;
xid.null();
- if (wsrep_get_SE_checkpoint(xid))
- {
- return true;
- }
+ wsrep_get_SE_checkpoint(xid);
if (xid.is_null())
{
- return false;
+ return wsrep::gtid();
}
if (!wsrep_is_wsrep_xid(&xid))
{
WSREP_WARN("Read non-wsrep XID from storage engines.");
- return false;
+ return wsrep::gtid::undefined();
}
+ return wsrep::gtid(wsrep_xid_uuid(xid), wsrep_xid_seqno(xid));
+}
- uuid= *wsrep_xid_uuid(xid);
- seqno= wsrep_xid_seqno(xid);
- return false;
-}
diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h
index 5b33a904de1..92ea6618f81 100644
--- a/sql/wsrep_xid.h
+++ b/sql/wsrep_xid.h
@@ -15,22 +15,20 @@
#ifndef WSREP_XID_H
#define WSREP_XID_H
-
#include <my_config.h>
-
+
#ifdef WITH_WSREP
-#include "../wsrep/wsrep_api.h"
+#include "wsrep/gtid.hpp"
#include "handler.h" // XID typedef
+#include "wsrep_api.h"
-void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t);
-const wsrep_uuid_t* wsrep_xid_uuid(const XID&);
-wsrep_seqno_t wsrep_xid_seqno(const XID&);
+void wsrep_xid_init(xid_t*, const wsrep::gtid&);
+wsrep::id wsrep_xid_uuid(const XID&);
+wsrep::seqno wsrep_xid_seqno(const XID&);
-//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */
-bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&);
-//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */
-bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t);
+wsrep::gtid wsrep_get_SE_checkpoint();
+void wsrep_set_SE_checkpoint(const wsrep::gtid& gtid);
#endif /* WITH_WSREP */
#endif /* WSREP_UTILS_H */
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index 088741e8ce8..34462873b57 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -43,6 +43,9 @@ Created April 08, 2011 Vasil Dimov
#include "ut0byte.h"
#include <algorithm>
+#ifdef WITH_WSREP_OUT
+extern my_bool wsrep_recovery;
+#endif /* WITH_WSREP */
#include "mysql/service_wsrep.h" /* wsrep_recovery */
#include <my_service_manager.h>
@@ -824,7 +827,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
if (srv_buffer_pool_load_at_startup) {
#ifdef WITH_WSREP
- if (!wsrep_recovery) {
+ if (!get_wsrep_recovery()) {
#endif /* WITH_WSREP */
buf_load();
#ifdef WITH_WSREP
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index b2df3983831..0f703c53dca 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -151,21 +151,14 @@ void close_thread_tables(THD* thd);
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
-static inline wsrep_ws_handle_t*
-wsrep_ws_handle(THD* thd, const trx_t* trx) {
- return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd),
- (wsrep_trx_id_t)trx->id);
-}
-
-extern TC_LOG* tc_log;
-extern void wsrep_cleanup_transaction(THD *thd);
-static int
-wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
- my_bool signal);
-static void
-wsrep_fake_trx_id(handlerton* hton, THD *thd);
-static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
-static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
+extern bool wsrep_prepare_key_for_innodb(
+ THD* thd,
+ const uchar *cache_key,
+ size_t cache_key_len,
+ const uchar* row_id,
+ size_t row_id_len,
+ wsrep_buf_t* key,
+ size_t* key_len);
#endif /* WITH_WSREP */
/** to force correct commit order in binlog */
@@ -1851,6 +1844,13 @@ thd_to_trx_id(
}
#endif /* WITH_WSREP */
+#ifdef WITH_WSREP
+static int
+wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
+ my_bool signal);
+static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
+static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
+#endif
/********************************************************************//**
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
@@ -4160,10 +4160,10 @@ static int innodb_init(void* p)
| HTON_NATIVE_SYS_VERSIONING;
#ifdef WITH_WSREP
- innobase_hton->abort_transaction=wsrep_abort_transaction;
- innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint;
- innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint;
- innobase_hton->fake_trx_id=wsrep_fake_trx_id;
+ innobase_hton->abort_transaction=wsrep_abort_transaction;
+ innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint;
+ innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint;
+ innobase_hton->fake_trx_id=NULL;
#endif /* WITH_WSREP */
innobase_hton->tablefile_extensions = ha_innobase_exts;
@@ -4630,6 +4630,16 @@ innobase_commit(
this one, to allow then to group commit with us. */
thd_wakeup_subsequent_commits(thd, 0);
+#ifdef WITH_WSREP
+ /* Serialisation history has been written, so the
+ commit is now ordered.
+ This seems to be problematic with load data splitting.
+ Commented out for now. */
+ // if (trx->mysql_thd) {
+ // (void)wsrep_ordered_commit_if_no_binlog(trx->mysql_thd);
+ // }
+#endif /* WITH_WSREP */
+
/* Now do a write + flush of logs. */
trx_commit_complete_for_mysql(trx);
@@ -5109,7 +5119,7 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
{
DBUG_ENTER("innobase_kill_query");
#ifdef WITH_WSREP
- if (wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) {
+ if (wsrep_on(thd) && wsrep_thd_is_aborting(thd)) {
/* if victim has been signaled by BF thread and/or aborting
is already progressing, following query aborting is not necessary
any more.
@@ -5121,9 +5131,22 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
#endif /* WITH_WSREP */
if (trx_t* trx = thd_to_trx(thd)) {
+#ifdef WITH_WSREP
+ bool locked= trx->lock.was_chosen_as_deadlock_victim;
+ if (locked) {
+ lock_mutex_exit();
+ trx_mutex_exit(trx);
+ }
+#endif /* WITH_WSREP */
ut_ad(trx->mysql_thd == thd);
/* Cancel a pending lock request if there are any */
lock_trx_handle_wait(trx);
+#ifdef WITH_WSREP
+ if (locked) {
+ lock_mutex_enter();
+ trx_mutex_enter(trx);
+ }
+#endif /* WITH_WSREP */
}
DBUG_VOID_RETURN;
@@ -6501,7 +6524,6 @@ ha_innobase::close()
UNIV_INTERN
ulint
wsrep_innobase_mysql_sort(
-/*======================*/
/* out: str contains sort string */
int mysql_type, /* in: MySQL type */
uint charset_number, /* in: number of the charset */
@@ -6925,7 +6947,6 @@ Stores a key value for a row to a buffer.
UNIV_INTERN
uint
wsrep_store_key_val_for_row(
-/*=========================*/
THD* thd,
TABLE* table,
uint keynr, /*!< in: key number */
@@ -6937,7 +6958,8 @@ wsrep_store_key_val_for_row(
{
KEY* key_info = table->key_info + keynr;
KEY_PART_INFO* key_part = key_info->key_part;
- KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts;
+ KEY_PART_INFO* end =
+ key_part + key_info->user_defined_key_parts;
char* buff_start = buff;
enum_field_types mysql_type;
Field* field;
@@ -8097,9 +8119,9 @@ ha_innobase::write_row(
wsrep_thd_query(m_user_thd) :
(char *)"void");
error= DB_SUCCESS;
- wsrep_thd_set_conflict_state(
- m_user_thd, MUST_ABORT);
- innobase_srv_conc_exit_innodb(m_prebuilt);
+ wsrep_thd_self_abort(current_thd);
+ innobase_srv_conc_exit_innodb(
+ m_prebuilt);
/* jump straight to func exit over
* later wsrep hooks */
goto func_exit;
@@ -8167,14 +8189,15 @@ ha_innobase::write_row(
error, m_prebuilt->table->flags, m_user_thd);
#ifdef WITH_WSREP
- if (!error_result
- && wsrep_on(m_user_thd)
- && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE
- && !wsrep_consistency_check(m_user_thd)
- && !wsrep_thd_ignore_table(m_user_thd)) {
- if (wsrep_append_keys(m_user_thd, false, record, NULL)) {
- DBUG_PRINT("wsrep", ("row key failed"));
- error_result = HA_ERR_INTERNAL_ERROR;
+ if (!error_result && wsrep_thd_is_local(m_user_thd) &&
+ wsrep_on(m_user_thd) && !wsrep_consistency_check(m_user_thd) &&
+ (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) &&
+ (thd_sql_command(m_user_thd) != SQLCOM_LOAD ||
+ thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) {
+ if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record,
+ NULL)) {
+ DBUG_PRINT("wsrep", ("row key failed"));
+ error_result = HA_ERR_INTERNAL_ERROR;
goto wsrep_error;
}
}
@@ -8645,7 +8668,6 @@ calc_row_difference(
static
int
wsrep_calc_row_hash(
-/*================*/
byte* digest, /*!< in/out: md5 sum */
const uchar* row, /*!< in: row in MySQL format */
TABLE* table, /*!< in: table in MySQL data
@@ -8868,13 +8890,13 @@ ha_innobase::update_row(
innobase_active_small();
#ifdef WITH_WSREP
- if (error == DB_SUCCESS &&
- wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE &&
- wsrep_on(m_user_thd) &&
- !wsrep_thd_ignore_table(m_user_thd)) {
+ if (error == DB_SUCCESS && wsrep_thd_is_local(m_user_thd) &&
+ wsrep_on(m_user_thd)) {
+
DBUG_PRINT("wsrep", ("update row key"));
- if (wsrep_append_keys(m_user_thd, false, old_row, new_row)) {
+ if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, old_row,
+ new_row)) {
WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED");
DBUG_PRINT("wsrep", ("row key failed"));
err = HA_ERR_INTERNAL_ERROR;
@@ -8934,11 +8956,12 @@ ha_innobase::delete_row(
innobase_active_small();
#ifdef WITH_WSREP
- if (error == DB_SUCCESS &&
- wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE &&
- wsrep_on(m_user_thd) &&
+ if (error == DB_SUCCESS && wsrep_thd_is_local(m_user_thd) &&
+ wsrep_on(m_user_thd) &&
!wsrep_thd_ignore_table(m_user_thd)) {
- if (wsrep_append_keys(m_user_thd, false, record, NULL)) {
+
+ if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record,
+ NULL)) {
DBUG_PRINT("wsrep", ("delete fail"));
error = (dberr_t) HA_ERR_INTERNAL_ERROR;
goto wsrep_error;
@@ -10130,16 +10153,30 @@ wsrep_dict_foreign_find_index(
ibool check_charsets,
ulint check_null);
+inline
+const char*
+wsrep_key_type_to_str(wsrep_key_type type)
+{
+ switch (type) {
+ case WSREP_KEY_SHARED:
+ return "shared";
+ case WSREP_KEY_SEMI:
+ return "semi";
+ case WSREP_KEY_EXCLUSIVE:
+ return "exclusive";
+ };
+ return "unknown";
+}
extern dberr_t
wsrep_append_foreign_key(
-/*===========================*/
trx_t* trx, /*!< in: trx */
dict_foreign_t* foreign, /*!< in: foreign key constraint */
const rec_t* rec, /*!<in: clustered index record */
dict_index_t* index, /*!<in: clustered index */
ibool referenced, /*!<in: is check for referenced table */
- ibool shared) /*!<in: is shared access */
+ wsrep_key_type key_type) /*!< in: access type of this key
+ (shared, exclusive, semi...) */
{
ut_a(trx);
THD* thd = (THD*)trx->mysql_thd;
@@ -10149,7 +10186,7 @@ wsrep_append_foreign_key(
bool const copy = true;
if (!wsrep_on(trx->mysql_thd) ||
- wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
+ wsrep_thd_is_local(trx->mysql_thd) == false) {
return DB_SUCCESS;
}
@@ -10238,11 +10275,11 @@ wsrep_append_foreign_key(
if (rcode != DB_SUCCESS) {
WSREP_ERROR(
- "FK key set failed: " ULINTPF
- " (" ULINTPF " " ULINTPF "), index: %s %s, %s",
- rcode, referenced, shared,
- (index) ? index->name() : "void index",
- (index && index->table) ? index->table->name.m_name :
+ "FK key set failed: %lu (%lu %s), index: %s %s, %s",
+ rcode, referenced, wsrep_key_type_to_str(key_type),
+ (index && index->name) ? index->name :
+ "void index",
+ (index) ? index->table->name.m_name :
"void table",
wsrep_thd_query(thd));
return DB_ERROR;
@@ -10278,7 +10315,8 @@ wsrep_append_foreign_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)cache_key,
cache_key_len + 1,
(const uchar*)key, len+1,
@@ -10289,17 +10327,10 @@ wsrep_append_foreign_key(
wsrep_thd_query(thd) : "void");
return DB_ERROR;
}
-
- wsrep_t *wsrep= get_wsrep();
-
- rcode = (int)wsrep->append_key(
- wsrep,
- wsrep_ws_handle(thd, trx),
- &wkey,
- 1,
- shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
- copy);
-
+ rcode = wsrep_thd_append_key(
+ thd, &wkey, 1,
+ (key_type == WSREP_KEY_SHARED) ? wsrep_key_shared :
+ wsrep_key_exclusive);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: " ULINTPF, rcode));
WSREP_ERROR("Appending cascaded fk row key failed: %s, "
@@ -10314,20 +10345,22 @@ wsrep_append_foreign_key(
static int
wsrep_append_key(
-/*=============*/
THD *thd,
trx_t *trx,
TABLE_SHARE *table_share,
const char* key,
uint16_t key_len,
- bool shared
+ wsrep_key_type key_type /*!< in: access type of this key
+ (shared, exclusive, semi...) */
)
{
DBUG_ENTER("wsrep_append_key");
- bool const copy = true;
+ DBUG_PRINT("enter",
+ ("thd: %lld trx: %lld", thd_get_thread_id(thd),
+ (long long)trx->id));
#ifdef WSREP_DEBUG_PRINT
- fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ",
- (shared) ? "Shared" : "Exclusive",
+ fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n SQL: %s ",
+ wsrep_key_type_to_str(key_type),
thd_get_thread_id(thd), (long long)trx->id, key_len,
table_share->table_name.str, wsrep_thd_query(thd));
for (int i=0; i<key_len; i++) {
@@ -10338,7 +10371,8 @@ wsrep_append_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)table_share->table_cache_key.str,
table_share->table_cache_key.length,
(const uchar*)key, key_len,
@@ -10350,15 +10384,11 @@ wsrep_append_key(
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
- wsrep_t *wsrep= get_wsrep();
-
- int rcode = (int)wsrep->append_key(
- wsrep,
- wsrep_ws_handle(thd, trx),
- &wkey,
- 1,
- shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
- copy);
+ int rcode = wsrep_thd_append_key(
+ thd,
+ &wkey,
+ 1,
+ (key_type == WSREP_KEY_SHARED) ? wsrep_key_shared : wsrep_key_exclusive);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
WSREP_WARN("Appending row key failed: %s, %d",
@@ -10397,9 +10427,9 @@ referenced_by_foreign_key2(
int
ha_innobase::wsrep_append_keys(
-/*===========================*/
THD *thd,
- bool shared,
+ wsrep_key_type key_type, /*!< in: access type of this key
+ (shared, exclusive, semi...) */
const uchar* record0, /* in: row in MySQL format */
const uchar* record1) /* in: row in MySQL format */
{
@@ -10431,7 +10461,7 @@ ha_innobase::wsrep_append_keys(
if (!is_null) {
rcode = wsrep_append_key(
thd, trx, table_share, keyval,
- len, shared);
+ len, key_type);
if (rcode) {
DBUG_RETURN(rcode);
@@ -10485,14 +10515,13 @@ ha_innobase::wsrep_append_keys(
if (!is_null) {
rcode = wsrep_append_key(
thd, trx, table_share,
- keyval0, len+1, shared);
+ keyval0, len+1, key_type);
- if (rcode) {
- DBUG_RETURN(rcode);
- }
+ if (rcode) DBUG_RETURN(rcode);
- if (key_info->flags & HA_NOSAME || shared)
- key_appended = true;
+ if (key_info->flags & HA_NOSAME ||
+ key_type == WSREP_KEY_SHARED)
+ key_appended = true;
} else {
WSREP_DEBUG("NULL key skipped: %s",
wsrep_thd_query(thd));
@@ -10507,7 +10536,7 @@ ha_innobase::wsrep_append_keys(
if (!is_null && memcmp(key0, key1, len)) {
rcode = wsrep_append_key(
thd, trx, table_share,
- keyval1, len+1, shared);
+ keyval1, len+1, key_type);
if (rcode) DBUG_RETURN(rcode);
}
}
@@ -10524,7 +10553,7 @@ ha_innobase::wsrep_append_keys(
if ((rcode = wsrep_append_key(thd, trx, table_share,
(const char*) digest, 16,
- shared))) {
+ key_type))) {
DBUG_RETURN(rcode);
}
@@ -10533,7 +10562,7 @@ ha_innobase::wsrep_append_keys(
digest, record1, table, m_prebuilt);
if ((rcode = wsrep_append_key(thd, trx, table_share,
(const char*) digest,
- 16, shared))) {
+ 16, key_type))) {
DBUG_RETURN(rcode);
}
}
@@ -15379,8 +15408,7 @@ ha_innobase::external_lock(
if (!skip) {
#ifdef WITH_WSREP
- if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE)
- {
+ if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) {
#endif /* WITH_WSREP */
my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
" InnoDB is limited to row-logging when"
@@ -18496,118 +18524,22 @@ wsrep_innobase_kill_one_trx(
bf_trx ? bf_trx->id : 0);
DBUG_RETURN(1);
}
-
- WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
-
- WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF
- "), victim: (%lu) trx: " TRX_ID_FMT,
- signal, bf_seqno,
- thd_get_thread_id(thd),
- victim_trx->id);
-
- WSREP_DEBUG("Aborting query: %s conf %d trx: %" PRId64,
- (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void",
- wsrep_thd_conflict_state(thd, FALSE),
- wsrep_thd_ws_handle(thd)->trx_id);
+ WSREP_LOG_CONFLICT((const void*)bf_thd, (const void*)thd, TRUE);
wsrep_thd_LOCK(thd);
- DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
- {
- const char act[]=
- "now "
- "wait_for signal.wsrep_after_BF_victim_lock";
- DBUG_ASSERT(!debug_sync_set_action(bf_thd,
- STRING_WITH_LEN(act)));
- };);
-
-
- if (wsrep_thd_query_state(thd) == QUERY_EXITING) {
- WSREP_DEBUG("kill trx EXITING for " TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- }
-
- if (wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
- WSREP_DEBUG("withdraw for BF trx: " TRX_ID_FMT ", state: %d",
- victim_trx->id,
- wsrep_thd_get_conflict_state(thd));
- }
-
- switch (wsrep_thd_get_conflict_state(thd)) {
- case NO_CONFLICT:
- wsrep_thd_set_conflict_state(thd, MUST_ABORT);
- break;
- case MUST_ABORT:
- WSREP_DEBUG("victim " TRX_ID_FMT " in MUST ABORT state",
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(0);
- break;
- case ABORTED:
- case ABORTING: // fall through
- default:
- WSREP_DEBUG("victim " TRX_ID_FMT " in state %d",
- victim_trx->id, wsrep_thd_get_conflict_state(thd));
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- break;
- }
+ WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%llu) trx: %llu",
+ signal, (long long)bf_seqno,
+ (long long)thd_get_thread_id(thd),
+ (long long)victim_trx->id);
- switch (wsrep_thd_query_state(thd)) {
- case QUERY_COMMITTING:
- enum wsrep_status rcode;
-
- WSREP_DEBUG("kill query for: %ld",
- thd_get_thread_id(thd));
- WSREP_DEBUG("kill trx QUERY_COMMITTING for " TRX_ID_FMT,
- victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- } else {
- wsrep_t *wsrep= get_wsrep();
- rcode = wsrep->abort_pre_commit(
- wsrep, bf_seqno,
- (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id
- );
-
- switch (rcode) {
- case WSREP_WARNING:
- WSREP_DEBUG("cancel commit warning: "
- TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(1);
- break;
- case WSREP_OK:
- break;
- default:
- WSREP_ERROR(
- "cancel commit bad exit: %d "
- TRX_ID_FMT,
- rcode, victim_trx->id);
- /* unable to interrupt, must abort */
- /* note: kill_mysql() will block, if we cannot.
- * kill the lock holder first.
- */
- abort();
- break;
- }
- }
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- break;
- case QUERY_EXEC:
- /* it is possible that victim trx is itself waiting for some
- * other lock. We need to cancel this waiting
- */
- WSREP_DEBUG("kill trx QUERY_EXEC for " TRX_ID_FMT,
- victim_trx->id);
+ WSREP_DEBUG("Aborting query: %s conf %s trx: %lld",
+ (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void",
+ wsrep_thd_transaction_state_str(thd),
+ wsrep_thd_transaction_id(thd));
+ wsrep_thd_UNLOCK(thd);
+ if (wsrep_thd_bf_abort(bf_thd, thd, signal))
+ {
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
if (victim_trx->lock.wait_lock) {
@@ -18620,9 +18552,7 @@ wsrep_innobase_kill_one_trx(
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
lock_cancel_waiting_and_release(wait_lock);
}
-
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
+ wsrep_thd_awake((const void*)thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
@@ -18631,56 +18561,8 @@ wsrep_innobase_kill_one_trx(
thd_get_thread_id(thd));
/* Note that innobase_kill_query will take lock_mutex
and trx_mutex */
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
-
- /* for BF thd, we need to prevent him from committing */
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- }
- }
- break;
- case QUERY_IDLE:
- {
- WSREP_DEBUG("kill IDLE for " TRX_ID_FMT, victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- WSREP_DEBUG("kill BF IDLE, seqno: %lld",
- (long long)wsrep_thd_trx_seqno(thd));
- wsrep_thd_UNLOCK(thd);
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- DBUG_RETURN(0);
- }
- /* This will lock thd from proceeding after net_read() */
- wsrep_thd_set_conflict_state(thd, ABORTING);
-
- wsrep_lock_rollback();
-
- if (wsrep_aborting_thd_contains(thd)) {
- WSREP_WARN("duplicate thd aborter %lu",
- (ulong) thd_get_thread_id(thd));
- } else {
- wsrep_aborting_thd_enqueue(thd);
- DBUG_PRINT("wsrep",("enqueuing trx abort for %lu",
- thd_get_thread_id(thd)));
- WSREP_DEBUG("enqueuing trx abort for (%lu)",
- thd_get_thread_id(thd));
+ wsrep_thd_awake((const void*)thd, signal);
}
-
- DBUG_PRINT("wsrep",("signalling wsrep rollbacker"));
- WSREP_DEBUG("signaling aborter");
- wsrep_unlock_rollback();
- wsrep_thd_UNLOCK(thd);
-
- break;
- }
- default:
- WSREP_WARN("bad wsrep query state: %d",
- wsrep_thd_query_state(thd));
- wsrep_thd_UNLOCK(thd);
- break;
}
DBUG_RETURN(0);
@@ -18700,26 +18582,24 @@ wsrep_abort_transaction(
trx_t* victim_trx = thd_to_trx(victim_thd);
trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
- WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d",
+ WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s",
wsrep_thd_query(bf_thd),
wsrep_thd_query(victim_thd),
- wsrep_thd_conflict_state(victim_thd, FALSE));
+ wsrep_thd_transaction_state_str(victim_thd));
if (victim_trx) {
lock_mutex_enter();
trx_mutex_enter(victim_trx);
- int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
- victim_trx, signal);
- lock_mutex_exit();
+ int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
+ victim_trx, signal);
trx_mutex_exit(victim_trx);
+ lock_mutex_exit();
wsrep_srv_conc_cancel_wait(victim_trx);
DBUG_RETURN(rcode);
- } else {
- WSREP_DEBUG("victim does not have transaction");
- wsrep_thd_LOCK(victim_thd);
- wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT);
- wsrep_thd_UNLOCK(victim_thd);
- wsrep_thd_awake(victim_thd, signal);
+ }
+ else
+ {
+ wsrep_thd_bf_abort(bf_thd, victim_thd, signal);
}
DBUG_RETURN(-1);
@@ -18761,6 +18641,7 @@ static void wsrep_fake_trx_id(handlerton *, THD *thd)
trx_id_t trx_id = trx_sys.get_new_trx_id();
WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
trx_id, wsrep_thd_query(thd));
+
wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index e65e7a57c99..7d1a9680010 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -16,6 +16,10 @@ this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
+#ifdef WITH_WSREP
+#include "wsrep_api.h"
+#include <mysql/service_wsrep.h>
+#endif /* WITH_WSREP */
/* The InnoDB handler: the interface between MySQL and InnoDB. */
@@ -450,8 +454,11 @@ class ha_innobase: public handler
dict_index_t* innobase_get_index(uint keynr);
#ifdef WITH_WSREP
- int wsrep_append_keys(THD *thd, bool shared,
- const uchar* record0, const uchar* record1);
+ int wsrep_append_keys(
+ THD *thd,
+ wsrep_key_type key_type,
+ const uchar* record0,
+ const uchar* record1);
#endif
/** Builds a 'template' to the prebuilt struct.
@@ -577,23 +584,7 @@ thd_get_work_part_info(
struct trx_t;
#ifdef WITH_WSREP
#include <mysql/service_wsrep.h>
-//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
-
-extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
-
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state);
-
-extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
-
-extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
-extern "C" time_t wsrep_thd_query_start(THD *thd);
-extern "C" query_id_t wsrep_thd_query_id(THD *thd);
-extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
-extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-#endif
+#endif /* WITH_WSREP */
extern const struct _ft_vft ft_vft_result;
@@ -627,10 +618,6 @@ innobase_index_name_is_reserved(
be created. */
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
-#ifdef WITH_WSREP
-//extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
-#endif
-
/** Parse hint for table and its indexes, and update the information
in dictionary.
@param[in] thd Connection thread
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index 1313705f119..4ce29521b55 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -233,13 +233,11 @@ innobase_casedn_str(
#ifdef WITH_WSREP
UNIV_INTERN
int
-wsrep_innobase_kill_one_trx(void * const thd_ptr,
- const trx_t * const bf_trx,
- trx_t *victim_trx,
- ibool signal);
+wsrep_innobase_kill_one_trx(void *thd_ptr,
+ const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
- unsigned char* str, unsigned int str_length,
- unsigned int buf_length);
+ unsigned char* str, unsigned int str_length,
+ unsigned int buf_length);
#endif /* WITH_WSREP */
/**********************************************************************//**
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index cb878fa5b19..d60ab6826ef 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -270,6 +270,23 @@ trx_commit_step(
/*============*/
que_thr_t* thr); /*!< in: query thread */
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+/*==============*/
+ FILE* f, /*!< in: output stream */
+ const trx_t* trx, /*!< in: transaction */
+ ulint max_query_len) /*!< in: max query length to print,
+ or 0 to use the default max length */
+ MY_ATTRIBUTE((nonnull));
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Caller must hold trx_sys.mutex. */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index c19797ab9da..edeb9e5a871 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -766,9 +766,7 @@ lock_rec_has_to_wait(
<< wsrep_thd_query(lock2->trx->mysql_thd);
}
- if (wsrep_trx_order_before(trx->mysql_thd,
- lock2->trx->mysql_thd)
- && (type_mode & LOCK_MODE_MASK) == LOCK_X
+ if ((type_mode & LOCK_MODE_MASK) == LOCK_X
&& (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) {
if (for_locking || wsrep_debug) {
/* exclusive lock conflicts are not
@@ -778,12 +776,11 @@ lock_rec_has_to_wait(
<< type_mode
<< " supremum: " << lock_is_on_supremum
<< "conflicts states: my "
- << wsrep_thd_conflict_state(
- trx->mysql_thd, FALSE)
+ << wsrep_thd_transaction_state_str(
+ trx->mysql_thd)
<< " locked "
- << wsrep_thd_conflict_state(
- lock2->trx->mysql_thd,
- FALSE);
+ << wsrep_thd_transaction_state_str(
+ lock2->trx->mysql_thd);
lock_rec_print(stderr, lock2);
ib::info() << " SQL1: "
<< wsrep_thd_query(trx->mysql_thd)
@@ -1103,11 +1100,14 @@ wsrep_kill_victim(
}
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
+ if (!bf_this) return;
+
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
- if ((bf_this && !bf_other) ||
- (bf_this && bf_other && wsrep_trx_order_before(
+ if ((!bf_other) ||
+ (bf_other && wsrep_thd_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
+ ut_ad(bf_this);
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) {
@@ -1429,9 +1429,11 @@ lock_rec_create_low(
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
- while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE)
- && wsrep_trx_order_before(hash->trx->mysql_thd,
- trx->mysql_thd)) {
+ while (hash &&
+ wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) &&
+ wsrep_thd_order_before(
+ ((lock_t *)hash)->trx->mysql_thd,
+ trx->mysql_thd)) {
prev = hash;
hash = (lock_t *)hash->hash;
}
@@ -1844,15 +1846,15 @@ lock_rec_add_to_queue(
ib::info() << "WSREP BF lock conflict for my lock:\n BF:" <<
((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " <<
wsrep_thd_query(trx->mysql_thd);
trx_t* otrx = other_lock->trx;
ib::info() << "WSREP other lock:\n BF:" <<
((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " <<
wsrep_thd_query(otrx->mysql_thd);
}
@@ -4944,8 +4946,8 @@ lock_rec_queue_validate(
if (!lock_get_wait(other_lock) ) {
ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" <<
((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " <<
wsrep_thd_query(impl_trx->mysql_thd);
@@ -4953,8 +4955,8 @@ lock_rec_queue_validate(
ib::info() << "WSREP other lock:\n BF:" <<
((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " <<
wsrep_thd_query(otrx->mysql_thd);
}
@@ -6986,6 +6988,9 @@ DeadlockChecker::trx_rollback()
trx_t* trx = m_wait_lock->trx;
print("*** WE ROLL BACK TRANSACTION (1)\n");
+#ifdef WITH_WSREP
+ wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd);
+#endif
trx_mutex_enter(trx);
diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc
index 4a3adaa4757..c84dd9e512e 100644
--- a/storage/innobase/lock/lock0wait.cc
+++ b/storage/innobase/lock/lock0wait.cc
@@ -36,7 +36,9 @@ Created 25/5/2010 Sunny Bains
#include "row0mysql.h"
#include "srv0start.h"
#include "lock0priv.h"
-
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP */
/*********************************************************************//**
Print the contents of the lock_sys_t::waiting_threads array. */
static
@@ -195,8 +197,8 @@ wsrep_is_BF_lock_timeout(
if (wsrep_on_trx(trx)
&& wsrep_thd_is_BF(trx->mysql_thd, FALSE)
&& trx->error_state != DB_DEADLOCK) {
- ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id)
- << " query: " << wsrep_thd_query(trx->mysql_thd);
+ ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id)
+ << " query: " << wsrep_thd_query(trx->mysql_thd);
if (!locked) {
lock_mutex_enter();
}
@@ -214,7 +216,9 @@ wsrep_is_BF_lock_timeout(
os_event_set(srv_monitor_event);
return true;
}
- return false;
+
+
+ return false;
}
#endif /* WITH_WSREP */
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index cfc7c20b8cb..39ee2dd8ae1 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -50,6 +50,10 @@ Created 4/20/1996 Heikki Tuuri
#include "fts0types.h"
#include "m_string.h"
#include "gis0geo.h"
+#include "wsrep_api.h"
+#include "mysql/service_wsrep.h"
+#include "wsrep_mysqld.h"
+#include "mysql/service_wsrep.h"
/*************************************************************************
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -1049,7 +1053,7 @@ dberr_t wsrep_append_foreign_key(trx_t *trx,
const rec_t* clust_rec,
dict_index_t* clust_index,
ibool referenced,
- ibool shared);
+ wsrep_key_type key_type);
#endif /* WITH_WSREP */
/*********************************************************************//**
@@ -1434,7 +1438,7 @@ row_ins_foreign_check_on_constraint(
#ifdef WITH_WSREP
err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index,
- FALSE, FALSE);
+ FALSE, WSREP_KEY_EXCLUSIVE);
if (err != DB_SUCCESS) {
fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err);
@@ -1809,13 +1813,19 @@ row_ins_check_foreign_constraint(
if (check_ref) {
err = DB_SUCCESS;
#ifdef WITH_WSREP
+ wsrep_key_type key_type;
+ if (upd_node != NULL) {
+ key_type = WSREP_KEY_SHARED;
+ } else {
+ key_type = WSREP_KEY_SEMI;
+ }
err = wsrep_append_foreign_key(
thr_get_trx(thr),
foreign,
rec,
check_index,
check_ref,
- (upd_node) ? TRUE : FALSE);
+ key_type);
#endif /* WITH_WSREP */
goto end_scan;
} else if (foreign->type != 0) {
@@ -1913,6 +1923,23 @@ row_ins_check_foreign_constraint(
check_table->inc_fk_checks();
lock_wait_suspend_thread(thr);
+#ifdef WITH_WSREP
+ ut_ad(!trx_mutex_own(trx));
+ switch (trx->error_state) {
+ case DB_DEADLOCK:
+ if (wsrep_debug) {
+ ib::info() <<
+ "WSREP: innodb trx state changed during wait "
+ << " trx: " << trx->id << " with error_state: "
+ << trx->error_state << " err: " << err;
+ }
+ err = trx->error_state;
+ break;
+ default:
+ break;
+ }
+
+#endif /* WITH_WSREP */
thr->lock_state = QUE_THR_LOCK_NOLOCK;
@@ -3231,9 +3258,26 @@ row_ins_clust_index_entry(
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
+#ifdef WITH_WSREP
+ const bool skip_locking
+ = wsrep_thd_skip_locking(thr_get_trx(thr)->mysql_thd);
+ ulint flags = skip_locking | index->table->is_temporary()
+ ? BTR_NO_LOCKING_FLAG
+ : index->table->no_rollback() ? BTR_NO_ROLLBACK : 0;
+#ifdef UNIV_DEBUG
+ if (skip_locking && sr_table_name_full_str != index->table->name.m_name) {
+ WSREP_ERROR("Record locking is disabled in this thread, "
+ "but the table being modified is not "
+ "`%s`: `%s`.", sr_table_name_full_str.c_str(),
+ index->table->name.m_name);
+ ut_error;
+ }
+#endif /* UNIV_DEBUG */
+#else
ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
: index->table->is_temporary()
? BTR_NO_LOCKING_FLAG : 0;
+#endif /* WITH_WSREP */
const ulint orig_n_fields = entry->n_fields;
/* Try first optimistic descent to the B-tree */
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 1531fb38b7f..079573e0417 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -56,6 +56,13 @@ Created 12/19/1997 Heikki Tuuri
#include "ha_prototypes.h"
#include "srv0mon.h"
#include "ut0new.h"
+#include "m_string.h" /* for my_sys.h */
+#include "my_sys.h" /* DEBUG_SYNC_C */
+
+#include "my_compare.h" /* enum icp_result */
+#include "thr_lock.h"
+#include "handler.h"
+#include "ha_innodb.h"
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -4503,6 +4510,13 @@ row_search_mvcc(
set_also_gap_locks = FALSE;
}
+#ifdef WITH_WSREP
+ if (wsrep_thd_skip_locking(trx->mysql_thd)) {
+
+ ut_ad(sr_table_name_full_str == prebuilt->table->name.m_name);
+ set_also_gap_locks = FALSE;
+ }
+#endif /* WITH_WSREP */
/* Note that if the search mode was GE or G, then the cursor
naturally moves upward (in fetch next) in alphabetical order,
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 5279d21b452..3caca05c89a 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -51,6 +51,10 @@ Created 12/27/1996 Heikki Tuuri
#include "trx0rec.h"
#include "fts0fts.h"
#include "fts0types.h"
+#ifdef WITH_WSREP
+extern my_bool wsrep_debug;
+#include "mysql/service_wsrep.h"
+#endif
#include <algorithm>
#include <mysql/plugin.h>
#include <mysql/service_wsrep.h>
@@ -2451,6 +2455,10 @@ row_upd_sec_index_entry(
row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) {
+#ifdef WITH_WSREP
+ const upd_node_t* parent =
+ static_cast<const upd_node_t*>(node->common.parent);
+#endif /* WITH_WSREP */
err = btr_cur_del_mark_set_sec_rec(
flags, btr_cur, TRUE, thr, &mtr);
if (err != DB_SUCCESS) {
@@ -2458,8 +2466,11 @@ row_upd_sec_index_entry(
}
#ifdef WITH_WSREP
if (!referenced && foreign
- && wsrep_must_process_fk(node, trx)
- && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
+ && wsrep_on(trx->mysql_thd)
+ && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)
+ && (!parent || que_node_get_type(parent) != QUE_NODE_UPDATE ||
+ !parent->cascade_node)
+ ) {
ulint* offsets = rec_get_offsets(
rec, index, NULL, true,
@@ -2791,8 +2802,8 @@ row_upd_clust_rec_by_insert(
<< " table " << index->table->name;
goto err_exit;
}
-#endif /* WITH_WSREP */
}
+#endif /* WITH_WSREP */
}
mtr_commit(mtr);
@@ -2998,7 +3009,8 @@ row_upd_del_mark_clust_rec(
err = row_upd_check_references_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
#ifdef WITH_WSREP
- } else if (foreign && wsrep_must_process_fk(node, trx)) {
+ } else if (trx && wsrep_on(trx->mysql_thd) && err == DB_SUCCESS
+ && wsrep_must_process_fk(node, trx)) {
err = wsrep_row_upd_check_foreign_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc
index d26e61253cd..65c5c47d35e 100644
--- a/storage/innobase/srv/srv0conc.cc
+++ b/storage/innobase/srv/srv0conc.cc
@@ -122,12 +122,11 @@ srv_conc_enter_innodb_with_atomics(
for (;;) {
ulint sleep_in_us;
#ifdef WITH_WSREP
- if (wsrep_on(trx->mysql_thd) &&
- wsrep_trx_is_aborting(trx->mysql_thd)) {
- if (wsrep_debug) {
+ if (wsrep_on(trx->mysql_thd) &&
+ wsrep_thd_is_aborting(trx->mysql_thd)) {
+ if (wsrep_debug)
ib::info() <<
"srv_conc_enter due to MUST_ABORT";
- }
srv_conc_force_enter_innodb(trx);
return;
}
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 94e5954c884..dd855c63599 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -80,8 +80,8 @@ Created 10/8/1995 Heikki Tuuri
#include <my_service_manager.h>
#ifdef WITH_WSREP
-extern int wsrep_debug;
-extern int wsrep_trx_is_aborting(void *thd_ptr);
+extern my_bool wsrep_debug;
+#include "mysql/service_wsrep.h"
#endif
/* The following is the maximum allowed duration of a lock wait. */
UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT;
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index f7f6dff4380..bb63ca509ab 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -186,6 +186,11 @@ trx_rollback_to_savepoint(
partial rollback requested, or NULL for
complete rollback */
{
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) && savept == NULL) {
+ wsrep_handle_SR_rollback(NULL, trx->mysql_thd);
+ }
+#endif /* WITH_WSREP */
ut_ad(!trx_mutex_own(trx));
trx_start_if_not_started_xa(trx, true);
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index bfa49b88d1d..2a3e908c115 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -58,10 +58,11 @@ trx_rseg_update_wsrep_checkpoint(
#ifdef UNIV_DEBUG
/* Check that seqno is monotonically increasing */
- long long xid_seqno = wsrep_xid_seqno(xid);
- const byte* xid_uuid = wsrep_xid_uuid(xid);
+ long long xid_seqno = get_wsrep_xid_seqno(xid);
+ const byte* xid_uuid = get_wsrep_xid_uuid(xid);
- if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) {
+ if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid) &&
+ xid_seqno != -1) {
ut_ad(xid_seqno > wsrep_seqno);
} else {
memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid);
@@ -108,7 +109,7 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr);
- const byte* xid_uuid = wsrep_xid_uuid(xid);
+ const byte* xid_uuid = get_wsrep_xid_uuid(xid);
if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) {
memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid);
@@ -206,8 +207,8 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
found = trx_rseg_init_wsrep_xid(sys->frame, xid);
ut_ad(!found || xid.formatID == 1);
if (found) {
- max_xid_seqno = wsrep_xid_seqno(&xid);
- memcpy(wsrep_uuid, wsrep_xid_uuid(&xid),
+ max_xid_seqno = get_wsrep_xid_seqno(&xid);
+ memcpy(wsrep_uuid, get_wsrep_xid_uuid(&xid),
sizeof wsrep_uuid);
}
}
@@ -229,12 +230,12 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
XID tmp_xid;
long long tmp_seqno = 0;
if (trx_rseg_read_wsrep_checkpoint(rseg_header, tmp_xid)
- && (tmp_seqno = wsrep_xid_seqno(&tmp_xid))
+ && (tmp_seqno = get_wsrep_xid_seqno(&tmp_xid))
> max_xid_seqno) {
found = true;
max_xid_seqno = tmp_seqno;
xid = tmp_xid;
- memcpy(wsrep_uuid, wsrep_xid_uuid(&tmp_xid),
+ memcpy(wsrep_uuid, get_wsrep_xid_uuid(&tmp_xid),
sizeof wsrep_uuid);
}
}
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 600a6eb6229..388cd3c8174 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -55,6 +55,9 @@ Created 3/26/1996 Heikki Tuuri
#include <set>
#include <new>
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#endif /* WITH_WSREP */
/** The bit pattern corresponding to TRX_ID_MAX */
const byte trx_id_max_bytes[8] = {
diff --git a/wsrep-lib b/wsrep-lib
new file mode 160000
index 00000000000..94174b06e65
--- /dev/null
+++ b/wsrep-lib
@@ -0,0 +1 @@
+Subproject commit 94174b06e653dcf92a940dfb009e525ca62b5204
diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt
deleted file mode 100644
index ff2bdec4def..00000000000
--- a/wsrep/CMakeLists.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2012, Codership Oy. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-SET(WSREP_SOURCES wsrep_gtid.c wsrep_uuid.c wsrep_loader.c wsrep_dummy.c)
-
-IF(NOT WITH_INNOBASE_STORAGE_ENGINE)
- MESSAGE(WARNING "WSRep is enabled, but innodb is not. This configuration is not supported")
-ENDIF()
-
-ADD_CONVENIENCE_LIBRARY(wsrep ${WSREP_SOURCES})
-DTRACE_INSTRUMENT(wsrep)
-
-#ADD_EXECUTABLE(listener wsrep_listener.c ${WSREP_SOURCES})
-#TARGET_LINK_LIBRARIES(listener ${LIBDL})
diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h
index 1d6bc059d3d..ecbf08fbc34 100644
--- a/wsrep/wsrep_api.h
+++ b/wsrep/wsrep_api.h
@@ -48,6 +48,7 @@
#define WSREP_H
#include <stdint.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
@@ -62,7 +63,7 @@ extern "C" {
* *
**************************************************************************/
-#define WSREP_INTERFACE_VERSION "25"
+#define WSREP_INTERFACE_VERSION "26"
/*! Empty backend spec */
#define WSREP_NONE "none"
@@ -110,27 +111,40 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *);
#define WSREP_CAP_UNORDERED ( 1ULL << 12 )
#define WSREP_CAP_ANNOTATION ( 1ULL << 13 )
#define WSREP_CAP_PREORDERED ( 1ULL << 14 )
+#define WSREP_CAP_STREAMING ( 1ULL << 15 )
+#define WSREP_CAP_SNAPSHOT ( 1ULL << 16 )
+#define WSREP_CAP_NBO ( 1ULL << 17 )
+typedef uint32_t wsrep_cap_t; //!< capabilities bitmask
/*!
- * Writeset flags
+ * Writeset flags
*
- * COMMIT the writeset and all preceding writesets must be committed
+ * TRX_END the writeset and all preceding writesets must be committed
* ROLLBACK all preceding writesets in a transaction must be rolled back
* ISOLATION the writeset must be applied AND committed in isolation
* PA_UNSAFE the writeset cannot be applied in parallel
* COMMUTATIVE the order in which the writeset is applied does not matter
* NATIVE the writeset contains another writeset in this provider format
*
- * Note that some of the flags are mutually exclusive (e.g. COMMIT and
+ * TRX_START shall be set on the first trx fragment by provider
+ * TRX_PREPARE shall be set on the fragment which prepares the transaction
+ *
+ * Note that some of the flags are mutually exclusive (e.g. TRX_END and
* ROLLBACK).
*/
-#define WSREP_FLAG_COMMIT ( 1ULL << 0 )
+#define WSREP_FLAG_TRX_END ( 1ULL << 0 )
#define WSREP_FLAG_ROLLBACK ( 1ULL << 1 )
#define WSREP_FLAG_ISOLATION ( 1ULL << 2 )
#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 )
#define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 )
#define WSREP_FLAG_NATIVE ( 1ULL << 5 )
+#define WSREP_FLAG_TRX_START ( 1ULL << 6 )
+#define WSREP_FLAG_TRX_PREPARE ( 1ULL << 7 )
+#define WSREP_FLAG_SNAPSHOT ( 1ULL << 8 )
+
+#define WSREP_FLAGS_LAST WSREP_FLAG_SNAPSHOT
+#define WSREP_FLAGS_MASK ((WSREP_FLAGS_LAST << 1) - 1)
typedef uint64_t wsrep_trx_id_t; //!< application transaction ID
@@ -158,7 +172,8 @@ typedef enum wsrep_status
WSREP_CONN_FAIL, //!< error in client connection, must abort
WSREP_NODE_FAIL, //!< error in node state, wsrep must reinit
WSREP_FATAL, //!< fatal error, server must abort
- WSREP_NOT_IMPLEMENTED //!< feature not implemented
+ WSREP_NOT_IMPLEMENTED, //!< feature not implemented
+ WSREP_NOT_ALLOWED //!< operation not allowed
} wsrep_status_t;
@@ -178,8 +193,9 @@ typedef enum wsrep_cb_status
/*!
* UUID type - for all unique IDs
*/
-typedef struct wsrep_uuid {
+typedef union wsrep_uuid {
uint8_t data[16];
+ size_t alignment;
} wsrep_uuid_t;
/*! Undefined UUID */
@@ -202,6 +218,18 @@ wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid);
extern int
wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len);
+/*!
+ * @brief Compare two UUIDs
+ *
+ * Performs a byte by byte comparison of lhs and rhs.
+ * Returns 0 if lhs and rhs match, otherwise -1 or 1 according to the
+ * difference of the first byte that differs in lsh and rhs.
+ *
+ * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs
+ */
+extern int
+wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs);
+
#define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length
#define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00
@@ -237,6 +265,14 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid);
extern int
wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len);
+/*!
+ * Source/server transaction ID (trx ID assigned at originating node)
+ */
+typedef struct wsrep_stid {
+ wsrep_uuid_t node; //!< source node ID
+ wsrep_trx_id_t trx; //!< local trx ID at source
+ wsrep_conn_id_t conn; //!< local connection ID at source
+} wsrep_stid_t;
/*!
* Transaction meta data
@@ -244,10 +280,24 @@ wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len);
typedef struct wsrep_trx_meta
{
wsrep_gtid_t gtid; /*!< Global transaction identifier */
- wsrep_seqno_t depends_on; /*!< Sequence number part of the last transaction
- this transaction depends on */
+ wsrep_stid_t stid; /*!< Source transaction identifier */
+ wsrep_seqno_t depends_on; /*!< Sequence number of the last transaction
+ this transaction may depend on */
} wsrep_trx_meta_t;
+/*! Abstract data buffer structure */
+typedef struct wsrep_buf
+{
+ const void* ptr; /*!< Pointer to data buffer */
+ size_t len; /*!< Length of buffer */
+} wsrep_buf_t;
+
+/*! Transaction handle struct passed for wsrep transaction handling calls */
+typedef struct wsrep_ws_handle
+{
+ wsrep_trx_id_t trx_id; //!< transaction ID
+ void* opaque; //!< opaque provider transaction context data
+} wsrep_ws_handle_t;
/*!
* member status
@@ -288,17 +338,53 @@ typedef struct wsrep_view_info {
wsrep_gtid_t state_id; //!< global state ID
wsrep_seqno_t view; //!< global view number
wsrep_view_status_t status; //!< view status
- wsrep_bool_t state_gap; //!< gap between global and local states
+ wsrep_cap_t capabilities;//!< capabilities available in the view
int my_idx; //!< index of this member in the view
int memb_num; //!< number of members in the view
int proto_ver; //!< application protocol agreed on the view
wsrep_member_info_t members[1];//!< array of member information
} wsrep_view_info_t;
+
+/*!
+ * @brief connected to group
+ *
+ * This handler is called once the first primary view is seen.
+ * The purpose of this call is to provide basic information only,
+ * like node UUID and group UUID.
+ */
+typedef enum wsrep_cb_status (*wsrep_connected_cb_t) (
+ void* app_ctx,
+ const wsrep_view_info_t* view
+);
+
+
+/*!
+ * @brief group view handler
+ *
+ * This handler is called in *total order* corresponding to the group
+ * configuration change. It is to provide a vital information about
+ * new group view.
+ *
+ * @param app_ctx application context
+ * @param recv_ctx receiver context
+ * @param view new view on the group
+ * @param state current state
+ * @param state_len length of current state
+ */
+typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
+ void* app_ctx,
+ void* recv_ctx,
+ const wsrep_view_info_t* view,
+ const char* state,
+ size_t state_len
+);
+
+
/*!
* Magic string to tell provider to engage into trivial (empty) state transfer.
* No data will be passed, but the node shall be considered JOINED.
- * Should be passed in sst_req parameter of wsrep_view_cb_t.
+ * Should be passed in sst_req parameter of wsrep_sst_cb_t.
*/
#define WSREP_STATE_TRANSFER_TRIVIAL "trivial"
@@ -306,40 +392,39 @@ typedef struct wsrep_view_info {
* Magic string to tell provider not to engage in state transfer at all.
* The member will stay in WSREP_MEMBER_UNDEFINED state but will keep on
* receiving all writesets.
- * Should be passed in sst_req parameter of wsrep_view_cb_t.
+ * Should be passed in sst_req parameter of wsrep_sst_cb_t.
*/
#define WSREP_STATE_TRANSFER_NONE "none"
+
/*!
- * @brief group view handler
+ * @brief Creates and returns State Snapshot Transfer request for provider.
*
- * This handler is called in total order corresponding to the group
- * configuration change. It is to provide a vital information about
- * new group view. If view info indicates existence of discontinuity
- * between group and member states, state transfer request message
- * should be filled in by the callback implementation.
+ * This handler is called whenever the node is found to miss some of events
+ * from the cluster history (e.g. fresh node joining the cluster).
+ * SST will be used if it is impossible (or impractically long) to replay
+ * missing events, which may be not known in advance, so the node must always
+ * be ready to accept full SST or abort in case event replay is impossible.
+ *
+ * Normally SST request is an opaque buffer that is passed to the
+ * chosen SST donor node and must contain information sufficient for
+ * donor to deliver SST (typically SST method and delivery address).
+ * See above macros WSREP_STATE_TRANSFER_TRIVIAL and WSREP_STATE_TRANSFER_NONE
+ * to modify the standard provider behavior.
*
* @note Currently it is assumed that sst_req is allocated using
* malloc()/calloc()/realloc() and it will be freed by
- * wsrep implementation.
+ * wsrep provider.
*
* @param app_ctx application context
- * @param recv_ctx receiver context
- * @param view new view on the group
- * @param state current state
- * @param state_len lenght of current state
* @param sst_req location to store SST request
* @param sst_req_len location to store SST request length or error code,
* value of 0 means no SST.
*/
-typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
- void* app_ctx,
- void* recv_ctx,
- const wsrep_view_info_t* view,
- const char* state,
- size_t state_len,
- void** sst_req,
- size_t* sst_req_len
+typedef enum wsrep_cb_status (*wsrep_sst_request_cb_t) (
+ void* app_ctx,
+ void** sst_req,
+ size_t* sst_req_len
);
@@ -349,47 +434,24 @@ typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
* This handler is called from wsrep library to apply replicated writeset
* Must support brute force applying for multi-master operation
*
- * @param recv_ctx receiver context pointer provided by the application
- * @param data data buffer containing the writeset
- * @param size data buffer size
- * @param flags WSREP_FLAG_... flags
- * @param meta transaction meta data of the writeset to be applied
+ * @param recv_ctx receiver context pointer provided by the application
+ * @param ws_handle internal provider writeset handle
+ * @param flags WSREP_FLAG_... flags
+ * @param data data buffer containing the writeset
+ * @param meta transaction meta data of the writeset to be applied
+ * @param exit_loop set to true to exit receive loop
*
- * @return success code:
- * @retval WSREP_OK
- * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format
- * @retval WSREP_ERROR failed to apply the writeset
+ * @return error code:
+ * @retval 0 - success
+ * @retval non-0 - application-specific error code
*/
typedef enum wsrep_cb_status (*wsrep_apply_cb_t) (
- void* recv_ctx,
- const void* data,
- size_t size,
- uint32_t flags,
- const wsrep_trx_meta_t* meta
-);
-
-
-/*!
- * @brief commit callback
- *
- * This handler is called to commit the changes made by apply callback.
- *
- * @param recv_ctx receiver context pointer provided by the application
- * @param flags WSREP_FLAG_... flags
- * @param meta transaction meta data of the writeset to be committed
- * @param exit set to true to exit recv loop
- * @param commit true - commit writeset, false - rollback writeset
- *
- * @return success code:
- * @retval WSREP_OK
- * @retval WSREP_ERROR call failed
- */
-typedef enum wsrep_cb_status (*wsrep_commit_cb_t) (
- void* recv_ctx,
- uint32_t flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* exit,
- wsrep_bool_t commit
+ void* recv_ctx,
+ const wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ const wsrep_buf_t* data,
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop
);
@@ -401,12 +463,10 @@ typedef enum wsrep_cb_status (*wsrep_commit_cb_t) (
*
* @param recv_ctx receiver context pointer provided by the application
* @param data data buffer containing the writeset
- * @param size data buffer size
*/
typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) (
- void* recv_ctx,
- const void* data,
- size_t size
+ void* recv_ctx,
+ const wsrep_buf_t* data
);
@@ -421,21 +481,17 @@ typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) (
*
* @param app_ctx application context
* @param recv_ctx receiver context
- * @param msg state transfer request message
- * @param msg_len state transfer request message length
+ * @param str_msg state transfer request message
* @param gtid current state ID on this node
* @param state current wsrep internal state buffer
- * @param state_len current wsrep internal state buffer len
* @param bypass bypass snapshot transfer, only transfer uuid:seqno pair
*/
typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) (
void* app_ctx,
void* recv_ctx,
- const void* msg,
- size_t msg_len,
+ const wsrep_buf_t* str_msg,
const wsrep_gtid_t* state_id,
- const char* state,
- size_t state_len,
+ const wsrep_buf_t* state,
wsrep_bool_t bypass
);
@@ -448,8 +504,10 @@ typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) (
* rest of the cluster.
*
* @param app_ctx application context
+ *
+ * @return wsrep_cb_status enum
*/
-typedef void (*wsrep_synced_cb_t) (void* app_ctx);
+typedef enum wsrep_cb_status (*wsrep_synced_cb_t) (void* app_ctx);
/*!
@@ -469,21 +527,21 @@ struct wsrep_init_args
/* Application initial state information. */
const wsrep_gtid_t* state_id; //!< Application state GTID
- const char* state; //!< Initial state for wsrep provider
- size_t state_len; //!< Length of state buffer
+ const wsrep_buf_t* state; //!< Initial state for wsrep provider
/* Application callbacks */
- wsrep_log_cb_t logger_cb; //!< logging handler
- wsrep_view_cb_t view_handler_cb; //!< group view change handler
+ wsrep_log_cb_t logger_cb; //!< logging handler
+ wsrep_connected_cb_t connected_cb; //!< connected to group
+ wsrep_view_cb_t view_cb; //!< group view change handler
+ wsrep_sst_request_cb_t sst_request_cb; //!< SST request creator
/* Applier callbacks */
- wsrep_apply_cb_t apply_cb; //!< apply callback
- wsrep_commit_cb_t commit_cb; //!< commit callback
- wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions
+ wsrep_apply_cb_t apply_cb; //!< apply callback
+ wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions
/* State Snapshot Transfer callbacks */
- wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate
- wsrep_synced_cb_t synced_cb; //!< synced with group
+ wsrep_sst_donate_cb_t sst_donate_cb; //!< donate SST
+ wsrep_synced_cb_t synced_cb; //!< synced with group
};
@@ -502,20 +560,13 @@ struct wsrep_stats_var
const char* name; //!< variable name
wsrep_var_type_t type; //!< variable value type
union {
- int64_t _integer64;
+ int64_t _int64;
double _double;
const char* _string;
} value; //!< variable value
};
-/*! Abstract data buffer structure */
-typedef struct wsrep_buf
-{
- const void* ptr; /*!< Pointer to data buffer */
- size_t len; /*!< Length of buffer */
-} wsrep_buf_t;
-
/*! Key struct used to pass certification keys for transaction handling calls.
* A key consists of zero or more key parts. */
typedef struct wsrep_key
@@ -526,7 +577,7 @@ typedef struct wsrep_key
/*! Key type:
* EXCLUSIVE conflicts with any key type
- * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE
+ * SEMI reserved. If not supported, should be interpreted as EXCLUSIVE
* SHARED conflicts only with EXCLUSIVE keys */
typedef enum wsrep_key_type
{
@@ -549,13 +600,6 @@ typedef enum wsrep_data_type
} wsrep_data_type_t;
-/*! Transaction handle struct passed for wsrep transaction handling calls */
-typedef struct wsrep_ws_handle
-{
- wsrep_trx_id_t trx_id; //!< transaction ID
- void* opaque; //!< opaque provider transaction context data
-} wsrep_ws_handle_t;
-
/*!
* @brief Helper method to reset trx writeset handle state when trx id changes
*
@@ -585,11 +629,11 @@ typedef struct wsrep_po_handle { void* opaque; } wsrep_po_handle_t;
static const wsrep_po_handle_t WSREP_PO_INITIALIZER = { NULL };
-typedef struct wsrep wsrep_t;
+typedef struct wsrep_st wsrep_t;
/*!
* wsrep interface for dynamically loadable libraries
*/
-struct wsrep {
+struct wsrep_st {
const char *version; //!< interface version string
@@ -603,11 +647,15 @@ struct wsrep {
const struct wsrep_init_args* args);
/*!
- * @brief Returns provider capabilities flag bitmap
+ * @brief Returns provider capabilities bitmap
+ *
+ * Note that these are potential provider capabilities. Provider will
+ * offer only capabilities supported by all members in the view
+ * (see wsrep_view_info).
*
* @param wsrep provider handle
*/
- uint64_t (*capabilities) (wsrep_t* wsrep);
+ wsrep_cap_t (*capabilities) (wsrep_t* wsrep);
/*!
* @brief Passes provider-specific configuration string to provider.
@@ -616,7 +664,7 @@ struct wsrep {
* @param conf configuration string
*
* @retval WSREP_OK configuration string was parsed successfully
- * @retval WSREP_WARNING could't not parse conf string, no action taken
+ * @retval WSREP_WARNING could not parse configuration string, no action taken
*/
wsrep_status_t (*options_set) (wsrep_t* wsrep, const char* conf);
@@ -633,7 +681,7 @@ struct wsrep {
/*!
* @brief Opens connection to cluster
*
- * Returns when either node is ready to operate as a part of the clsuter
+ * Returns when either node is ready to operate as a part of the cluster
* or fails to reach operating status.
*
* @param wsrep provider handle
@@ -642,7 +690,7 @@ struct wsrep {
* @param state_donor name of the node to be asked for state transfer.
* @param bootstrap a flag to request initialization of a new wsrep
* service rather then a connection to the existing one.
- * clister_url may still carry important initialization
+ * cluster_url may still carry important initialization
* parameters, like backend spec and/or listen address.
*/
wsrep_status_t (*connect) (wsrep_t* wsrep,
@@ -672,52 +720,100 @@ struct wsrep {
wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx);
/*!
- * @brief Replicates/logs result of transaction to other nodes and allocates
- * required resources.
+ * @brief Tells provider that a given writeset has a read view associated
+ * with it.
+ *
+ * @param wsrep provider handle
+ * @param handle writeset handle
+ * @param rv read view GTID established by the caller or if NULL,
+ * provider will infer it internally.
+ */
+ wsrep_status_t (*assign_read_view)(wsrep_t* wsrep,
+ wsrep_ws_handle_t* handle,
+ const wsrep_gtid_t* rv);
+
+ /*!
+ * @brief Certifies transaction with provider.
*
* Must be called before transaction commit. Returns success code, which
* caller must check.
- * In case of WSREP_OK, starts commit critical section, transaction can
- * commit. Otherwise transaction must rollback.
+ *
+ * In case of WSREP_OK, transaction can proceed to commit.
+ * Otherwise transaction must rollback.
+ *
+ * In case of a failure there are two conceptually different situations:
+ * - the writeset was not ordered. In that case meta struct shall contain
+ * undefined GTID: WSREP_UUID_UNDEFINED:WSREP_SEQNO_UNDEFINED.
+ * - the writeset was successfully ordered, but failed certification.
+ * In this case meta struct shall contain a valid GTID.
+ *
+ * Regardless of the return code, if meta struct contains a valid GTID
+ * the commit order critical section must be entered with that GTID.
*
* @param wsrep provider handle
- * @param ws_handle writeset of committing transaction
* @param conn_id connection ID
+ * @param ws_handle writeset of committing transaction
* @param flags fine tuning the replication WSREP_FLAG_*
* @param meta transaction meta data
*
- * @retval WSREP_OK cluster-wide commit succeeded
+ * @retval WSREP_OK writeset successfully certified, can commit
* @retval WSREP_TRX_FAIL must rollback transaction
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*pre_commit)(wsrep_t* wsrep,
- wsrep_conn_id_t conn_id,
- wsrep_ws_handle_t* ws_handle,
- uint32_t flags,
- wsrep_trx_meta_t* meta);
+ wsrep_status_t (*certify)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ wsrep_trx_meta_t* meta);
/*!
- * @brief Releases resources after transaction commit.
+ * @brief Enters commit order critical section.
*
- * Ends commit critical section.
+ * Anything executed between this call and commit_order_leave() will be
+ * executed in provider enforced order.
*
* @param wsrep provider handle
- * @param ws_handle writeset of committing transaction
- * @retval WSREP_OK post_commit succeeded
+ * @param ws_handle internal provider writeset handle
+ * @param meta transaction meta data
+ *
+ * @retval WSREP_OK commit order entered successfully
+ * @retval WSREP_NODE_FAIL must close all connections and reinit
+ */
+ wsrep_status_t (*commit_order_enter)(wsrep_t* wsrep,
+ const wsrep_ws_handle_t* ws_handle,
+ const wsrep_trx_meta_t* meta);
+
+ /*!
+ * @brief Leaves commit order critical section
+ *
+ * Anything executed between commit_order_enter() and this call will be
+ * executed in provider enforced order.
+ *
+ * @param wsrep provider handle
+ * @param ws_handle internal provider writeset handle
+ * @param meta transaction meta data
+ * @param error buffer containing error info (null/empty for no error)
+ *
+ * @retval WSREP_OK commit order left successfully
+ * @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*post_commit) (wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle);
+ wsrep_status_t (*commit_order_leave)(wsrep_t* wsrep,
+ const wsrep_ws_handle_t* ws_handle,
+ const wsrep_trx_meta_t* meta,
+ const wsrep_buf_t* error);
/*!
- * @brief Releases resources after transaction rollback.
+ * @brief Releases resources after transaction commit/rollback.
+ *
+ * Ends total order critical section.
*
* @param wsrep provider handle
* @param ws_handle writeset of committing transaction
- * @retval WSREP_OK post_rollback succeeded
+ * @retval WSREP_OK release succeeded
*/
- wsrep_status_t (*post_rollback)(wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle);
+ wsrep_status_t (*release) (wsrep_t* wsrep,
+ wsrep_ws_handle_t* ws_handle);
/*!
* @brief Replay trx as a slave writeset
@@ -738,29 +834,49 @@ struct wsrep {
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*replay_trx)(wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle,
- void* trx_ctx);
+ wsrep_status_t (*replay_trx)(wsrep_t* wsrep,
+ const wsrep_ws_handle_t* ws_handle,
+ void* trx_ctx);
/*!
- * @brief Abort pre_commit() call of another thread.
+ * @brief Abort certify() call of another thread.
*
* It is possible, that some high-priority transaction needs to abort
- * another transaction which is in pre_commit() call waiting for resources.
+ * another transaction which is in certify() call waiting for resources.
*
- * The kill routine checks that abort is not attmpted against a transaction
+ * The kill routine checks that abort is not attempted against a transaction
* which is front of the caller (in total order).
*
+ * If the abort was successful, the victim sequence number is stored
+ * into location pointed by the victim_seqno.
+ *
* @param wsrep provider handle
* @param bf_seqno seqno of brute force trx, running this cancel
* @param victim_trx transaction to be aborted, and which is committing
+ * @param victim_seqno seqno of the victim transaction if assigned
+ *
+ * @retval WSREP_OK abort succeeded
+ * @retval WSREP_NOT_ALLOWED the provider declined the abort request
+ * @retval WSREP_TRX_MISSING the victim_trx was missing
+ * @retval WSREP_WARNING abort failed
+ */
+ wsrep_status_t (*abort_certification)(wsrep_t* wsrep,
+ wsrep_seqno_t bf_seqno,
+ wsrep_trx_id_t victim_trx,
+ wsrep_seqno_t* victim_seqno);
+
+ /*!
+ * @brief Send a rollback fragment on behalf of trx
+ *
+ * @param wsrep provider handle
+ * @param trx transaction to be rolled back
+ * @param data data to append to the fragment
*
- * @retval WSREP_OK abort secceded
- * @retval WSREP_WARNING abort failed
+ * @retval WSREP_OK rollback fragment sent successfully
*/
- wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep,
- wsrep_seqno_t bf_seqno,
- wsrep_trx_id_t victim_trx);
+ wsrep_status_t (*rollback)(wsrep_t* wsrep,
+ wsrep_trx_id_t trx,
+ const wsrep_buf_t* data);
/*!
* @brief Appends a row reference to transaction writeset
@@ -772,7 +888,7 @@ struct wsrep {
* @param ws_handle writeset handle
* @param keys array of keys
* @param count length of the array of keys
- * @param type type ot the key
+ * @param type type of the key
* @param copy can be set to FALSE if keys persist through commit.
*/
wsrep_status_t (*append_key)(wsrep_t* wsrep,
@@ -797,33 +913,54 @@ struct wsrep {
* @param type type of data
* @param copy can be set to FALSE if data persists through commit.
*/
- wsrep_status_t (*append_data)(wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle,
- const struct wsrep_buf* data,
- size_t count,
- enum wsrep_data_type type,
- wsrep_bool_t copy);
+ wsrep_status_t (*append_data)(wsrep_t* wsrep,
+ wsrep_ws_handle_t* ws_handle,
+ const wsrep_buf_t* data,
+ size_t count,
+ enum wsrep_data_type type,
+ wsrep_bool_t copy);
/*!
- * @brief Get causal ordering for read operation
+ * @brief Blocks until the given GTID is committed
*
- * This call will block until causal ordering with all possible
- * preceding writes in the cluster is guaranteed. If pointer to
- * gtid is non-null, the call stores the global transaction ID
- * of the last transaction which is guaranteed to be ordered
- * causally before this call.
+ * This call will block the caller until the given GTID
+ * is guaranteed to be committed, or until a timeout occurs.
+ * The timeout value is given in parameter tout, if tout is -1,
+ * then the global causal read timeout applies.
*
- * @param wsrep provider handle
- * @param gtid location to store GTID
+ * If no pointer upto is provided the call will block until
+ * causal ordering with all possible preceding writes in the
+ * cluster is guaranteed.
+ *
+ * If pointer to gtid is non-null, the call stores the global
+ * transaction ID of the last transaction which is guaranteed
+ * to be committed when the call returns.
+ *
+ * @param wsrep provider handle
+ * @param upto gtid to wait upto
+ * @param tout timeout in seconds
+ * -1 wait for global causal read timeout
+ * @param gtid location to store GTID
+ */
+ wsrep_status_t (*sync_wait)(wsrep_t* wsrep,
+ wsrep_gtid_t* upto,
+ int tout,
+ wsrep_gtid_t* gtid);
+
+ /*!
+ * @brief Returns the last committed gtid
+ *
+ * @param gtid location to store GTID
*/
- wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid);
+ wsrep_status_t (*last_committed_id)(wsrep_t* wsrep,
+ wsrep_gtid_t* gtid);
/*!
* @brief Clears allocated connection context.
*
* Whenever a new connection ID is passed to wsrep provider through
* any of the API calls, a connection context is allocated for this
- * connection. This call is to explicitly notify provider fo connection
+ * connection. This call is to explicitly notify provider of connection
* closing.
*
* @param wsrep provider handle
@@ -837,28 +974,51 @@ struct wsrep {
/*!
* @brief Replicates a query and starts "total order isolation" section.
*
+ * Regular mode:
+ *
* Replicates the action spec and returns success code, which caller must
* check. Total order isolation continues until to_execute_end() is called.
+ * Regular "total order isolation" is achieved by calling to_execute_start()
+ * with WSREP_FLAG_TRX_START and WSREP_FLAG_TRX_END set.
+ *
+ * Two-phase mode:
+ *
+ * In this mode a query execution is split in two phases. The first phase is
+ * acquiring total order isolation to access critical section and the
+ * second phase is to release acquired resources in total order.
+ *
+ * To start the first phase the call is made with WSREP_FLAG_TRX_START set.
+ * The action is replicated and success code is returned. The total order
+ * isolation continues until to_execute_end() is called. However, the provider
+ * will keep the reference to the operation for conflict resolution purposes.
+ *
+ * The second phase is started with WSREP_FLAG_TRX_END set. Provider
+ * returns once it has achieved total ordering isolation for second phase.
+ * Total order isolation continues until to_execute_end() is called.
+ * All references to the operation are cleared by provider before
+ * call to to_execute_end() returns.
*
* @param wsrep provider handle
* @param conn_id connection ID
* @param keys array of keys
- * @param keys_num lenght of the array of keys
+ * @param keys_num length of the array of keys
* @param action action buffer array to be executed
* @param count action buffer count
+ * @param flags flags
* @param meta transaction meta data
*
* @retval WSREP_OK cluster commit succeeded
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*to_execute_start)(wsrep_t* wsrep,
- wsrep_conn_id_t conn_id,
- const wsrep_key_t* keys,
- size_t keys_num,
- const struct wsrep_buf* action,
- size_t count,
- wsrep_trx_meta_t* meta);
+ wsrep_status_t (*to_execute_start)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ const wsrep_key_t* keys,
+ size_t keys_num,
+ const wsrep_buf_t* action,
+ size_t count,
+ uint32_t flags,
+ wsrep_trx_meta_t* meta);
/*!
* @brief Ends the total order isolation section.
@@ -866,14 +1026,18 @@ struct wsrep {
* Marks the end of total order isolation. TO locks are freed
* and other transactions are free to commit from this point on.
*
- * @param wsrep provider handle
+ * @param wsrep provider handle
* @param conn_id connection ID
+ * @param error error information about TOI operation (empty for no error)
*
* @retval WSREP_OK cluster commit succeeded
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, wsrep_conn_id_t conn_id);
+ wsrep_status_t (*to_execute_end)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ const wsrep_buf_t* error);
+
/*!
* @brief Collects preordered replication events into a writeset.
@@ -888,11 +1052,11 @@ struct wsrep {
* @retval WSREP_TRX_FAIL operation failed (e.g. trx size exceeded limit)
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*preordered_collect) (wsrep_t* wsrep,
- wsrep_po_handle_t* handle,
- const struct wsrep_buf* data,
- size_t count,
- wsrep_bool_t copy);
+ wsrep_status_t (*preordered_collect) (wsrep_t* wsrep,
+ wsrep_po_handle_t* handle,
+ const wsrep_buf_t* data,
+ size_t count,
+ wsrep_bool_t copy);
/*!
* @brief "Commits" preordered writeset to cluster.
@@ -943,20 +1107,18 @@ struct wsrep {
* @param wsrep provider handle
* @param state_id state ID
* @param state initial state provided by SST donor
- * @param state_len length of state buffer
* @param rcode 0 or negative error code of the operation.
*/
wsrep_status_t (*sst_received)(wsrep_t* wsrep,
const wsrep_gtid_t* state_id,
- const void* state,
- size_t state_len,
+ const wsrep_buf_t* state,
int rcode);
/*!
* @brief Generate request for consistent snapshot.
*
- * If successfull, this call will generate internally SST request
+ * If successful, this call will generate internally SST request
* which in turn triggers calling SST donate callback on the nodes
* specified in donor_spec. If donor_spec is null, callback is
* called only locally. This call will block until sst_sent is called
@@ -967,13 +1129,12 @@ struct wsrep {
* @param msg_len length of context message
* @param donor_spec list of snapshot donors
*/
- wsrep_status_t (*snapshot)(wsrep_t* wsrep,
- const void* msg,
- size_t msg_len,
- const char* donor_spec);
+ wsrep_status_t (*snapshot)(wsrep_t* wsrep,
+ const wsrep_buf_t* msg,
+ const char* donor_spec);
/*!
- * @brief Returns an array fo status variables.
+ * @brief Returns an array of status variables.
* Array is terminated by Null variable name.
*
* @param wsrep provider handle
@@ -1020,7 +1181,7 @@ struct wsrep {
* @brief Request to resynchronize with cluster.
*
* Effectively turns on flow control. Asynchronous - actual synchronization
- * event to be deliverred via sync_cb.
+ * event to be delivered via sync_cb.
*/
wsrep_status_t (*resync) (wsrep_t* wsrep);
@@ -1086,7 +1247,7 @@ struct wsrep {
void (*free)(wsrep_t* wsrep);
void *dlh; //!< reserved for future use
- void *ctx; //!< reserved for implemetation private context
+ void *ctx; //!< reserved for implementation private context
};
@@ -1094,7 +1255,7 @@ struct wsrep {
*
* @brief Loads wsrep library
*
- * @param spec path to wsrep library. If NULL or WSREP_NONE initialises dummy
+ * @param spec path to wsrep library. If NULL or WSREP_NONE initializes dummy
* pass-through implementation.
* @param hptr wsrep handle
* @param log_cb callback to handle loader messages. Otherwise writes to stderr.
diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c
index e48dcff39a1..8c39ca5ace0 100644
--- a/wsrep/wsrep_dummy.c
+++ b/wsrep/wsrep_dummy.c
@@ -19,6 +19,7 @@
#include "wsrep_api.h"
#include <errno.h>
+#include <stdbool.h>
#include <string.h>
/*! Dummy backend context. */
@@ -62,7 +63,7 @@ static wsrep_status_t dummy_init (wsrep_t* w,
return WSREP_OK;
}
-static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
+static wsrep_cap_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
{
return 0;
}
@@ -84,15 +85,8 @@ static wsrep_status_t dummy_options_set(
static char* dummy_options_get (wsrep_t* w)
{
- char *options;
-
- WSREP_DBUG_ENTER(w);
- options= WSREP_DUMMY(w)->options;
-
- if (options)
- options= strdup(WSREP_DUMMY(w)->options);
-
- return options;
+ WSREP_DBUG_ENTER(w);
+ return strdup(WSREP_DUMMY(w)->options);
}
static wsrep_status_t dummy_connect(
@@ -119,7 +113,16 @@ static wsrep_status_t dummy_recv(wsrep_t* w,
return WSREP_OK;
}
-static wsrep_status_t dummy_pre_commit(
+static wsrep_status_t dummy_assign_read_view(
+ wsrep_t* w,
+ wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ const wsrep_gtid_t* rv __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_certify(
wsrep_t* w,
const wsrep_conn_id_t conn_id __attribute__((unused)),
wsrep_ws_handle_t* ws_handle __attribute__((unused)),
@@ -130,15 +133,24 @@ static wsrep_status_t dummy_pre_commit(
return WSREP_OK;
}
-static wsrep_status_t dummy_post_commit(
+static wsrep_status_t dummy_commit_order_enter(
wsrep_t* w,
- wsrep_ws_handle_t* ws_handle __attribute__((unused)))
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
}
-static wsrep_status_t dummy_post_rollback(
+static wsrep_status_t dummy_commit_order_leave(
+ wsrep_t* w,
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ const wsrep_buf_t* error __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_release(
wsrep_t* w,
wsrep_ws_handle_t* ws_handle __attribute__((unused)))
{
@@ -155,10 +167,20 @@ static wsrep_status_t dummy_replay_trx(
return WSREP_OK;
}
-static wsrep_status_t dummy_abort_pre_commit(
+static wsrep_status_t dummy_abort_certification(
wsrep_t* w,
const wsrep_seqno_t bf_seqno __attribute__((unused)),
- const wsrep_trx_id_t trx_id __attribute__((unused)))
+ const wsrep_trx_id_t trx_id __attribute__((unused)),
+ wsrep_seqno_t *victim_seqno __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_rollback(
+ wsrep_t* w,
+ const wsrep_trx_id_t trx __attribute__((unused)),
+ const wsrep_buf_t* data __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -170,7 +192,7 @@ static wsrep_status_t dummy_append_key(
const wsrep_key_t* key __attribute__((unused)),
const size_t key_num __attribute__((unused)),
const wsrep_key_type_t key_type __attribute__((unused)),
- const wsrep_bool_t copy __attribute__((unused)))
+ const bool copy __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -182,13 +204,23 @@ static wsrep_status_t dummy_append_data(
const struct wsrep_buf* data __attribute__((unused)),
const size_t count __attribute__((unused)),
const wsrep_data_type_t type __attribute__((unused)),
- const wsrep_bool_t copy __attribute__((unused)))
+ const bool copy __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_sync_wait(
+ wsrep_t* w,
+ wsrep_gtid_t* upto __attribute__((unused)),
+ int tout __attribute__((unused)),
+ wsrep_gtid_t* gtid __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
}
-static wsrep_status_t dummy_causal_read(
+static wsrep_status_t dummy_last_committed_id(
wsrep_t* w,
wsrep_gtid_t* gtid __attribute__((unused)))
{
@@ -211,6 +243,7 @@ static wsrep_status_t dummy_to_execute_start(
const size_t key_num __attribute__((unused)),
const struct wsrep_buf* data __attribute__((unused)),
const size_t count __attribute__((unused)),
+ const uint32_t flags __attribute__((unused)),
wsrep_trx_meta_t* meta __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
@@ -219,7 +252,8 @@ static wsrep_status_t dummy_to_execute_start(
static wsrep_status_t dummy_to_execute_end(
wsrep_t* w,
- const wsrep_conn_id_t conn_id __attribute__((unused)))
+ const wsrep_conn_id_t conn_id __attribute__((unused)),
+ const wsrep_buf_t* err __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -260,8 +294,7 @@ static wsrep_status_t dummy_sst_sent(
static wsrep_status_t dummy_sst_received(
wsrep_t* w,
const wsrep_gtid_t* state_id __attribute__((unused)),
- const void* state __attribute__((unused)),
- const size_t state_len __attribute__((unused)),
+ const wsrep_buf_t* state __attribute__((unused)),
const int rcode __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
@@ -270,9 +303,8 @@ static wsrep_status_t dummy_sst_received(
static wsrep_status_t dummy_snapshot(
wsrep_t* w,
- const void* msg __attribute__((unused)),
- const size_t msg_len __attribute__((unused)),
- const char* donor_spec __attribute__((unused)))
+ const wsrep_buf_t* msg __attribute__((unused)),
+ const char* donor_spec __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -325,10 +357,10 @@ static wsrep_status_t dummy_resync (wsrep_t* w)
}
static wsrep_status_t dummy_lock (wsrep_t* w,
- const char* s __attribute__((unused)),
- wsrep_bool_t r __attribute__((unused)),
- uint64_t o __attribute__((unused)),
- int64_t t __attribute__((unused)))
+ const char* s __attribute__((unused)),
+ bool r __attribute__((unused)),
+ uint64_t o __attribute__((unused)),
+ int64_t t __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_NOT_IMPLEMENTED;
@@ -342,13 +374,13 @@ static wsrep_status_t dummy_unlock (wsrep_t* w,
return WSREP_OK;
}
-static wsrep_bool_t dummy_is_locked (wsrep_t* w,
- const char* s __attribute__((unused)),
- uint64_t* o __attribute__((unused)),
- wsrep_uuid_t* t __attribute__((unused)))
+static bool dummy_is_locked (wsrep_t* w,
+ const char* s __attribute__((unused)),
+ uint64_t* o __attribute__((unused)),
+ wsrep_uuid_t* t __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
- return 0;
+ return false;
}
static wsrep_t dummy_iface = {
@@ -360,14 +392,18 @@ static wsrep_t dummy_iface = {
&dummy_connect,
&dummy_disconnect,
&dummy_recv,
- &dummy_pre_commit,
- &dummy_post_commit,
- &dummy_post_rollback,
+ &dummy_assign_read_view,
+ &dummy_certify,
+ &dummy_commit_order_enter,
+ &dummy_commit_order_leave,
+ &dummy_release,
&dummy_replay_trx,
- &dummy_abort_pre_commit,
+ &dummy_abort_certification,
+ &dummy_rollback,
&dummy_append_key,
&dummy_append_data,
- &dummy_causal_read,
+ &dummy_sync_wait,
+ &dummy_last_committed_id,
&dummy_free_connection,
&dummy_to_execute_start,
&dummy_to_execute_end,
diff --git a/wsrep/wsrep_gtid.c b/wsrep/wsrep_gtid.c
index 45148785c25..a02543ab523 100644
--- a/wsrep/wsrep_gtid.c
+++ b/wsrep/wsrep_gtid.c
@@ -53,7 +53,7 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid)
/*!
* Write GTID to string
- * @return length of GTID stirng representation of -EMSGSIZE if string is too
+ * @return length of GTID string representation or -EMSGSIZE if string is too
* short
*/
int
diff --git a/wsrep/wsrep_listener.c b/wsrep/wsrep_listener.c
new file mode 100644
index 00000000000..7d1558c3014
--- /dev/null
+++ b/wsrep/wsrep_listener.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 2012 Codership Oy <info(a)codersihp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*! @file Example of wsrep event listener. Outputs description of received
+ * events to stdout. To get a general picture you should start with
+ * main() function. */
+
+#include <wsrep_api.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+
+/*! This is global application context, it will be used by wsrep callbacks */
+struct application_context
+{};
+
+static struct application_context global_ctx;
+
+/*! This is receiving thread context, it will be used by wsrep callbacks */
+struct receiver_context
+{
+ char msg[4096];
+};
+
+/* wsrep provider handle (global for simplicty) */
+static wsrep_t* wsrep = NULL;
+
+/*! This is a logger callback which library will be using to log events. */
+static void
+logger_cb (wsrep_log_level_t level __attribute__((unused)), const char* msg)
+{
+ fprintf (stderr, "WSREP: %s\n", msg);
+}
+
+/*! This will be called on cluster view change (nodes joining, leaving, etc.).
+ * Each view change is the point where application may be pronounced out of
+ * sync with the current cluster view and need state transfer.
+ * It is guaranteed that no other callbacks are called concurrently with it. */
+static wsrep_cb_status_t
+view_cb (void* app_ctx __attribute__((unused)),
+ void* recv_ctx __attribute__((unused)),
+ const wsrep_view_info_t* view,
+ const char* state __attribute__((unused)),
+ size_t state_len __attribute__((unused)))
+{
+ printf ("New cluster membership view: %d nodes, my index is %d, "
+ "global seqno: %lld\n",
+ view->memb_num, view->my_idx, (long long)view->state_id.seqno);
+
+ return WSREP_CB_SUCCESS;
+}
+
+/*! This will be called on cluster view change (nodes joining, leaving, etc.).
+ * Each view change is the point where application may be pronounced out of
+ * sync with the current cluster view and need state transfer.
+ * It is guaranteed that no other callbacks are called concurrently with it. */
+static wsrep_cb_status_t
+sst_request_cb (void** sst_req,
+ size_t* sst_req_len)
+{
+ /* For simplicity we're skipping state transfer by using magic string
+ * as a state transfer request.
+ * This node will not be considered JOINED (having full state)
+ * by other cluster members. */
+ *sst_req = strdup(WSREP_STATE_TRANSFER_NONE);
+
+ if (*sst_req)
+ *sst_req_len = strlen(*sst_req) + 1;
+ else
+ *sst_req_len = -ENOMEM;
+
+ return WSREP_CB_SUCCESS;
+}
+
+/*! This is called to "apply" writeset.
+ * If writesets don't conflict on keys, it may be called concurrently to
+ * utilize several CPU cores. */
+static wsrep_cb_status_t
+apply_cb (void* recv_ctx,
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ uint32_t flags __attribute__((unused)),
+ const wsrep_buf_t* ws __attribute__((unused)),
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop __attribute__((unused)))
+{
+ struct receiver_context* ctx = (struct receiver_context*)recv_ctx;
+
+ snprintf (ctx->msg, sizeof(ctx->msg),
+ "Got writeset %lld, size %zu", (long long)meta->gtid.seqno,
+ ws->len);
+
+ bool const commit = flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK);
+
+ wsrep->commit_order_enter(wsrep, ws_handle);
+ if (commit) puts(ctx->msg);
+ wsrep->commit_order_leave(wsrep, ws_handle, NULL);
+
+ return WSREP_CB_SUCCESS;
+}
+
+/* The following callbacks are stubs and not used in this example. */
+static wsrep_cb_status_t
+unordered_cb(void* recv_ctx __attribute__((unused)),
+ const wsrep_buf_t* data __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+static wsrep_cb_status_t
+sst_donate_cb (void* app_ctx __attribute__((unused)),
+ void* recv_ctx __attribute__((unused)),
+ const wsrep_buf_t* msg __attribute__((unused)),
+ const wsrep_gtid_t* state_id __attribute__((unused)),
+ const wsrep_buf_t* state __attribute__((unused)),
+ wsrep_bool_t bypass __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+static wsrep_cb_status_t synced_cb (void* app_ctx __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+/* This is the listening thread. It blocks in wsrep::recv() call until
+ * disconnect from cluster. It will apply and commit writesets through the
+ * callbacks defined avbove. */
+static void*
+recv_thread (void* arg)
+{
+ struct receiver_context* ctx = (struct receiver_context*)arg;
+
+ wsrep_status_t rc = wsrep->recv(wsrep, ctx);
+
+ fprintf (stderr, "Receiver exited with code %d", rc);
+
+ return NULL;
+}
+
+/* This is a signal handler to demonstrate graceful cluster leave. */
+static void
+graceful_leave (int signum)
+{
+ printf ("Got signal %d, exiting...\n", signum);
+ wsrep->disconnect(wsrep);
+}
+
+int main (int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ fprintf (stderr, "Usage: %s </path/to/wsrep/provider> <wsrep URI> "
+ "<cluster name>\n", argv[0]);
+ exit (EXIT_FAILURE);
+ }
+
+ const char* const wsrep_provider = argv[1];
+ const char* const wsrep_uri = argv[2];
+ const char* const cluster_name = argv[3];
+
+ /* Now let's load and initialize provider */
+ wsrep_status_t rc = wsrep_load (wsrep_provider, &wsrep, logger_cb);
+ if (WSREP_OK != rc)
+ {
+ fprintf (stderr, "Failed to load wsrep provider '%s'\n",wsrep_provider);
+ exit (EXIT_FAILURE);
+ }
+
+ wsrep_gtid_t state_id = { WSREP_UUID_UNDEFINED, WSREP_SEQNO_UNDEFINED };
+
+ /* wsrep provider initialization arguments */
+ struct wsrep_init_args wsrep_args =
+ {
+ .app_ctx = &global_ctx,
+
+ .node_name = "example listener",
+ .node_address = "",
+ .node_incoming = "",
+ .data_dir = ".", // working directory
+ .options = "",
+ .proto_ver = 127, // maximum supported application event protocol
+
+ .state_id = &state_id,
+ .state = NULL,
+
+ .logger_cb = logger_cb,
+ .view_cb = view_cb,
+ .sst_request_cb = sst_request_cb,
+ .apply_cb = apply_cb,
+ .unordered_cb = unordered_cb,
+ .sst_donate_cb = sst_donate_cb,
+ .synced_cb = synced_cb
+ };
+
+ rc = wsrep->init(wsrep, &wsrep_args);
+ if (WSREP_OK != rc)
+ {
+ fprintf (stderr, "wsrep::init() failed: %d\n", rc);
+ exit (EXIT_FAILURE);
+ }
+
+ /* Connect to cluster */
+ rc = wsrep->connect (wsrep, cluster_name, wsrep_uri, "", 0);
+ if (0 != rc)
+ {
+ fprintf (stderr,
+ "wsrep::connect() failed: %d (%s)\n", rc, strerror(-rc));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Now let's start several listening threads*/
+ int const num_threads = 4;
+ struct receiver_context thread_ctx[num_threads];
+ pthread_t threads[num_threads];
+
+ int i;
+ for (i = 0; i < num_threads; i++)
+ {
+ int err = pthread_create (
+ &threads[i], NULL, recv_thread, &thread_ctx[i]);
+
+ if (err)
+ {
+ fprintf (stderr, "Failed to start thread %d: %d (%s)",
+ i, err, strerror(err));
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ signal (SIGTERM, graceful_leave);
+ signal (SIGINT, graceful_leave);
+
+ /* Listening threads are now running and receiving writesets. Wait for them
+ * to join. Threads will join after signal handler closes wsrep connection*/
+ for (i = 0; i < num_threads; i++)
+ {
+ pthread_join (threads[i], NULL);
+ }
+
+ /* Unload provider after nobody uses it any more. */
+ wsrep_unload (wsrep);
+
+ return 0;
+}
diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c
index 1321538742f..31618de420e 100644
--- a/wsrep/wsrep_loader.c
+++ b/wsrep/wsrep_loader.c
@@ -56,9 +56,10 @@ static int wsrep_check_iface_version(const char* found, const char* iface_ver)
static int verify(const wsrep_t *wh, const char *iface_ver)
{
char msg[128];
+ const size_t msg_len = sizeof(msg);
#define VERIFY(_p) if (!(_p)) { \
- snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \
+ snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \
logger (WSREP_LOG_ERROR, msg); \
return EINVAL; \
}
@@ -75,11 +76,13 @@ static int verify(const wsrep_t *wh, const char *iface_ver)
VERIFY(wh->connect);
VERIFY(wh->disconnect);
VERIFY(wh->recv);
- VERIFY(wh->pre_commit);
- VERIFY(wh->post_commit);
- VERIFY(wh->post_rollback);
+ VERIFY(wh->assign_read_view);
+ VERIFY(wh->certify);
+ VERIFY(wh->commit_order_enter);
+ VERIFY(wh->commit_order_leave);
+ VERIFY(wh->release);
VERIFY(wh->replay_trx);
- VERIFY(wh->abort_pre_commit);
+ VERIFY(wh->abort_certification);
VERIFY(wh->append_key);
VERIFY(wh->append_data);
VERIFY(wh->free_connection);
@@ -134,8 +137,9 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
int ret = 0;
void *dlh = NULL;
wsrep_loader_fun dlfun;
- char msg[1025];
- msg[sizeof(msg)-1] = 0;
+ char msg[1024];
+ const size_t msg_len = sizeof(msg) - 1;
+ msg[msg_len] = 0;
if (NULL != log_cb)
logger = log_cb;
@@ -143,7 +147,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
if (!(spec && hptr))
return EINVAL;
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): loading provider library '%s'", spec);
logger (WSREP_LOG_INFO, msg);
@@ -161,7 +165,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
}
if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) {
- snprintf(msg, sizeof(msg)-1, "wsrep_load(): dlopen(): %s", dlerror());
+ snprintf(msg, msg_len, "wsrep_load(): dlopen(): %s", dlerror());
logger (WSREP_LOG_ERROR, msg);
ret = EINVAL;
goto out;
@@ -178,14 +182,14 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
}
if ((ret = (*dlfun)(*hptr)) != 0) {
- snprintf(msg, sizeof(msg)-1, "wsrep_load(): loader failed: %s",
+ snprintf(msg, msg_len, "wsrep_load(): loader failed: %s",
strerror(ret));
logger (WSREP_LOG_ERROR, msg);
goto out;
}
if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) {
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): interface version mismatch: my version %s, "
"provider version %s", WSREP_INTERFACE_VERSION,
(*hptr)->version);
@@ -201,7 +205,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
free(*hptr);
*hptr = NULL;
} else {
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): %s %s by %s loaded successfully.",
(*hptr)->provider_name, (*hptr)->provider_version,
(*hptr)->provider_vendor);
diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c
index 54ae4ab5ed5..419594db127 100644
--- a/wsrep/wsrep_uuid.c
+++ b/wsrep/wsrep_uuid.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
+#include <string.h>
#include "wsrep_api.h"
@@ -81,3 +82,13 @@ wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len)
return -EMSGSIZE;
}
}
+
+/*!
+ * Compare two UUIDs
+ * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs
+ */
+int
+wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs)
+{
+ return memcmp(lhs, rhs, sizeof(wsrep_uuid_t));
+}
1
0
12 Oct '18
revision-id: 8009d85cc2e9245f6e8be06397914433e4b20007 (mariadb-5.5.61-30-g8009d85cc2e)
parent(s): acf8fc1ff8a7b2d49e25279670b04b8eb096ce0c
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-10-12 20:47:22 +0200
message:
MDEV-16207: Sig 11 on RHEL7 on Azure
The problem was that Item_subselect::const_item was not checked correctly and can differ from used_tables result.
Which lead to the situation when Item_direct_view_ref pointing on subselect was constant but the subquery return
FALSE on const_item() request (which was an error).
Now both methods report the same.
---
mysql-test/r/subselect.result | 31 +++++++++++++++++++++++--------
mysql-test/r/subselect_no_mat.result | 31 +++++++++++++++++++++++--------
mysql-test/r/subselect_no_opts.result | 31 +++++++++++++++++++++++--------
mysql-test/r/subselect_no_scache.result | 31 +++++++++++++++++++++++--------
mysql-test/r/subselect_no_semijoin.result | 31 +++++++++++++++++++++++--------
mysql-test/t/subselect.test | 21 +++++++++++++++++++++
sql/item.cc | 10 +++++++++-
sql/item_subselect.cc | 5 +++--
sql/sql_select.cc | 4 +++-
9 files changed, 151 insertions(+), 44 deletions(-)
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index cdedc02f825..934c145e995 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1156,19 +1156,19 @@ CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
@@ -4059,8 +4059,6 @@ SELECT COUNT(*), a
FROM t1 GROUP BY a
HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;
COUNT(*) a
-2 2
-3 3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
@@ -4582,7 +4580,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
-NULL NULL
+NULL 0
DROP TABLE t1, st1, st2;
#
# Bug #48709: Assertion failed in sql_select.cc:11782:
@@ -6652,7 +6650,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 NULL
+0 7
EXPLAIN
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -6660,7 +6658,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 0
+0 1
EXPLAIN
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -7187,4 +7185,21 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1,t2;
+#
+# MDEV-16207: Sig 11 on RHEL7 on Azure
+#
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+nm1 types
+char2 NULL
+char2 NULL
+drop table t2,t3,t5;
End of 5.5 tests
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index a7291297e7c..cdb13367c45 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -1163,19 +1163,19 @@ CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
@@ -4063,8 +4063,6 @@ SELECT COUNT(*), a
FROM t1 GROUP BY a
HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;
COUNT(*) a
-2 2
-3 3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
@@ -4584,7 +4582,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
-NULL NULL
+NULL 0
DROP TABLE t1, st1, st2;
#
# Bug #48709: Assertion failed in sql_select.cc:11782:
@@ -6651,7 +6649,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 NULL
+0 7
EXPLAIN
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -6659,7 +6657,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 0
+0 1
EXPLAIN
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -7184,6 +7182,23 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1,t2;
+#
+# MDEV-16207: Sig 11 on RHEL7 on Azure
+#
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+nm1 types
+char2 NULL
+char2 NULL
+drop table t2,t3,t5;
End of 5.5 tests
set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%';
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index c41fa1be47b..0cfb34e890c 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -1159,19 +1159,19 @@ CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
@@ -4059,8 +4059,6 @@ SELECT COUNT(*), a
FROM t1 GROUP BY a
HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;
COUNT(*) a
-2 2
-3 3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
@@ -4580,7 +4578,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
-NULL NULL
+NULL 0
DROP TABLE t1, st1, st2;
#
# Bug #48709: Assertion failed in sql_select.cc:11782:
@@ -6647,7 +6645,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 NULL
+0 7
EXPLAIN
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -6655,7 +6653,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 0
+0 1
EXPLAIN
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -7182,5 +7180,22 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1,t2;
+#
+# MDEV-16207: Sig 11 on RHEL7 on Azure
+#
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+nm1 types
+char2 NULL
+char2 NULL
+drop table t2,t3,t5;
End of 5.5 tests
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 1c181357050..0e4bdcca9dd 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -1162,19 +1162,19 @@ CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
@@ -4065,8 +4065,6 @@ SELECT COUNT(*), a
FROM t1 GROUP BY a
HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;
COUNT(*) a
-2 2
-3 3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
@@ -4588,7 +4586,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
-NULL NULL
+NULL 0
DROP TABLE t1, st1, st2;
#
# Bug #48709: Assertion failed in sql_select.cc:11782:
@@ -6658,7 +6656,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 NULL
+0 7
EXPLAIN
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -6666,7 +6664,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 0
+0 1
EXPLAIN
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -7193,6 +7191,23 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1,t2;
+#
+# MDEV-16207: Sig 11 on RHEL7 on Azure
+#
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+nm1 types
+char2 NULL
+char2 NULL
+drop table t2,t3,t5;
End of 5.5 tests
set optimizer_switch=default;
select @@optimizer_switch like '%subquery_cache=on%';
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index 89c671252ff..fae84f58c13 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -1159,19 +1159,19 @@ CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
-2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+2 UNCACHEABLE SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
@@ -4059,8 +4059,6 @@ SELECT COUNT(*), a
FROM t1 GROUP BY a
HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;
COUNT(*) a
-2 2
-3 3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
@@ -4580,7 +4578,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
-NULL NULL
+NULL 0
DROP TABLE t1, st1, st2;
#
# Bug #48709: Assertion failed in sql_select.cc:11782:
@@ -6647,7 +6645,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 NULL
+0 7
EXPLAIN
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -6655,7 +6653,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
COUNT(f1) f4
-0 0
+0 1
EXPLAIN
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
id select_type table type possible_keys key key_len ref rows Extra
@@ -7182,6 +7180,23 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1,t2;
+#
+# MDEV-16207: Sig 11 on RHEL7 on Azure
+#
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+nm1 types
+char2 NULL
+char2 NULL
+drop table t2,t3,t5;
End of 5.5 tests
set @optimizer_switch_for_subselect_test=null;
set @join_cache_level_for_subselect_test=NULL;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 4e35032a789..9f475ae3bf0 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -6075,4 +6075,25 @@ explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
drop table t1,t2;
+--echo #
+--echo # MDEV-16207: Sig 11 on RHEL7 on Azure
+--echo #
+
+CREATE TABLE t2 (ser1 char(20) NOT NULL, ids1 int NOT NULL, nm1 char(32) NOT NULL);
+INSERT INTO t2 VALUES ('char1',1,'char2'),('char2',2,'char2');
+
+CREATE TABLE t3 (id2 int );
+INSERT INTO t3 VALUES (1),(2);
+
+CREATE TABLE t5 (nm1 varchar(255), ls1 varchar(64), state enum('Active','Inactive','Event'));
+
+
+SELECT * FROM
+(SELECT nm1,
+(SELECT max(t5.nm1) FROM t5 WHERE t5.ls1 = ser1 AND STATE = 'Active') AS types
+FROM t3 JOIN t2 ON ids1 = id2) AS t1
+ORDER BY nm1 ;
+
+drop table t2,t3,t5;
+
--echo End of 5.5 tests
diff --git a/sql/item.cc b/sql/item.cc
index d2e3b847f5c..1f1aeacf96e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -7419,7 +7419,15 @@ void Item_ref::make_field(Send_field *field)
Item *Item_ref::get_tmp_table_item(THD *thd)
{
if (!result_field)
- return (*ref)->get_tmp_table_item(thd);
+ {
+ if (!with_sum_func && !const_item())
+ return (*ref)->get_tmp_table_item(thd);
+ else
+ {
+ DBUG_ASSERT((*ref)->const_item() || (*ref)->with_sum_func);
+ return copy_or_same(thd);
+ }
+ }
Item_field *item= new Item_field(result_field);
if (item)
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 57dcbd4f540..1938db86743 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -854,7 +854,8 @@ void Item_subselect::fix_length_and_dec()
table_map Item_subselect::used_tables() const
{
- return (table_map) ((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)?
+ return (table_map) ((!forced_const && !const_item_cache &&
+ (engine->uncacheable() & ~UNCACHEABLE_EXPLAIN))?
used_tables_cache : 0L);
}
@@ -864,7 +865,7 @@ bool Item_subselect::const_item() const
DBUG_ASSERT(thd);
return (thd->lex->context_analysis_only ?
FALSE :
- forced_const || const_item_cache);
+ used_tables() == 0);
}
Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 35937f0536f..9b0c1415662 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -14705,6 +14705,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
bool maybe_null= item->maybe_null;
Field *new_field;
LINT_INIT(new_field);
+ DBUG_ENTER("create_tmp_field_from_item");
+ DBUG_PRINT("enter", ("Item: %p modify: %d", item, modify_item));
/*
To preserve type or DATE/TIME and GEOMETRY fields,
@@ -14772,7 +14774,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->set_result_field(new_field);
if (item->type() == Item::NULL_ITEM)
new_field->is_created_from_null_item= TRUE;
- return new_field;
+ DBUG_RETURN(new_field);
}
1
0
[Commits] 1169dbc: MDEV-17354 Server crashes in add_key_field / .. / Item_func_null_predicate::add_key_fields
by IgorBabaev 12 Oct '18
by IgorBabaev 12 Oct '18
12 Oct '18
revision-id: 1169dbc8e72255d059f4309dddd939e95abdb902 (mariadb-10.2.18-22-g1169dbc)
parent(s): 00b6c7d8fc8a75b023f78d5f08324cba000002b3
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-10-12 11:44:19 -0700
message:
MDEV-17354 Server crashes in add_key_field / .. / Item_func_null_predicate::add_key_fields
upon INSERT .. SELECT
The function Item *Item_direct_view_ref::derived_field_transformer_for_where()
erroneously did not strip off ref wrappers from references to materialized
derived tables / views. As a result the expressions that contained some
references of the type Item_direct_view_ref to columns of a materialized
derived table / view V were pushed into V incorrectly. This could cause
crashes for some INSERT ... SELECT statements.
---
mysql-test/r/derived_cond_pushdown.result | 146 ++++++++++++++++++++++++++++++
mysql-test/t/derived_cond_pushdown.test | 33 +++++++
sql/item.cc | 2 +-
3 files changed, 180 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result
index 9ef3488..9d9d1e7 100644
--- a/mysql-test/r/derived_cond_pushdown.result
+++ b/mysql-test/r/derived_cond_pushdown.result
@@ -10241,3 +10241,149 @@ a b c
1 2 2
3 2 2
DROP TABLE t1;
+#
+# MDEV-17354: INSERT SELECT with condition pushdown into derived
+#
+CREATE TABLE t1 (f INT NOT NULL);
+INSERT INTO t1 VALUES (3), (7), (3);
+CREATE ALGORITHM= TEMPTABLE VIEW v1 AS SELECT * FROM ( SELECT * FROM t1 ) AS sq;
+INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
+EXPLAIN INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 144 Using where
+2 DERIVED <derived3> ALL NULL NULL NULL NULL 12
+2 DERIVED t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
+3 DERIVED t1 ALL NULL NULL NULL NULL 12
+EXPLAIN FORMAT=JSON INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "rows": 144,
+ "filtered": 100,
+ "attached_condition": "t.f is not null",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ALL",
+ "rows": 12,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 12,
+ "filtered": 100
+ }
+ }
+ }
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 12,
+ "filtered": 100,
+ "attached_condition": "t1.f is not null"
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL"
+ }
+ }
+ }
+ }
+ }
+}
+SELECT * FROM t1;
+f
+3
+7
+3
+3
+3
+3
+7
+7
+7
+3
+3
+3
+DELETE FROM t1;
+INSERT INTO t1 VALUES (3), (7), (3);
+INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t
+WHERE f IS NOT NULL;
+EXPLAIN FORMAT=JSON INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t
+WHERE f IS NOT NULL;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "rows": 16,
+ "filtered": 100,
+ "attached_condition": "t.f is not null",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 8,
+ "filtered": 100,
+ "attached_condition": "t1.f is not null"
+ },
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "4",
+ "used_key_parts": ["f"],
+ "ref": ["test.t1.f"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 8,
+ "filtered": 100,
+ "attached_condition": "t1.f is not null"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+SELECT * FROM t1;
+f
+3
+7
+3
+3
+3
+7
+3
+3
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test
index 2310966..476a3d7 100644
--- a/mysql-test/t/derived_cond_pushdown.test
+++ b/mysql-test/t/derived_cond_pushdown.test
@@ -2042,3 +2042,36 @@ SELECT * FROM
WHERE ((a,b) IN ((1,2),(3,2)));
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-17354: INSERT SELECT with condition pushdown into derived
+--echo #
+
+CREATE TABLE t1 (f INT NOT NULL);
+INSERT INTO t1 VALUES (3), (7), (3);
+
+CREATE ALGORITHM= TEMPTABLE VIEW v1 AS SELECT * FROM ( SELECT * FROM t1 ) AS sq;
+
+let $q1=
+INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
+
+eval $q1;
+eval EXPLAIN $q1;
+eval EXPLAIN FORMAT=JSON $q1;
+SELECT * FROM t1;
+
+DELETE FROM t1;
+INSERT INTO t1 VALUES (3), (7), (3);
+
+let $q2=
+INSERT INTO t1
+SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t
+ WHERE f IS NOT NULL;
+
+eval $q2;
+eval EXPLAIN FORMAT=JSON $q2;
+SELECT * FROM t1;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/sql/item.cc b/sql/item.cc
index 35de01b..2adec33 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -7214,7 +7214,7 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
DBUG_ASSERT (producing_item != NULL);
return producing_item->build_clone(thd, thd->mem_root);
}
- return this;
+ return (*ref);
}
static
1
0
[Commits] cc5c19ae523: MDEV-17401: LOAD DATA from very big file into MyISAM table results in EOF error and corrupt index
by Oleksandr Byelkin 12 Oct '18
by Oleksandr Byelkin 12 Oct '18
12 Oct '18
revision-id: cc5c19ae5233ba90de086de76043774ae6c78cd7 (mariadb-5.5.61-30-gcc5c19ae523)
parent(s): acf8fc1ff8a7b2d49e25279670b04b8eb096ce0c
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-10-12 09:07:05 +0200
message:
MDEV-17401: LOAD DATA from very big file into MyISAM table results in EOF error and corrupt index
my_read fixed as in higher versions.
my_pread made as my_read aware of partial read of huge chunks of files
MY_FULL_IO enabled for file operations
---
mysys/mf_iocache.c | 4 ++++
mysys/my_pread.c | 25 ++++++++++++++++++-------
mysys/my_read.c | 52 ++++++++++++++++++++++++++++------------------------
3 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index bd71e2ae527..9a051cf6a9e 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -282,6 +282,10 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
}
info->inited=info->aio_result.pending=0;
#endif
+ if (type == READ_CACHE || type == WRITE_CACHE || type == SEQ_READ_APPEND)
+ info->myflags|= MY_FULL_IO;
+ else
+ info->myflags&= ~MY_FULL_IO;
DBUG_RETURN(0);
} /* init_io_cache */
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 51b4c5f5599..5cbd6b4316b 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -47,8 +47,7 @@
size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
myf MyFlags)
{
- size_t readbytes;
- int error= 0;
+ size_t readbytes, save_count= 0;
DBUG_ENTER("my_pread");
@@ -66,11 +65,10 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
#else
readbytes= pread(Filedes, Buffer, Count, offset);
#endif
- error = (readbytes != Count);
- if (error)
+ if (readbytes != Count)
{
- my_errno= errno ? errno : -1;
+ my_errno= errno;
if (errno == 0 || (readbytes != (size_t) -1 &&
(MyFlags & (MY_NABP | MY_FNABP))))
my_errno= HA_ERR_FILE_TOO_SHORT;
@@ -82,6 +80,17 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
(int) readbytes));
continue; /* Interrupted */
}
+
+ /* Do a read retry if we didn't get enough data on first read */
+ if (readbytes != (size_t) -1 && readbytes != 0 &&
+ (MyFlags & MY_FULL_IO))
+ {
+ Buffer+= readbytes;
+ Count-= readbytes;
+ save_count+= readbytes;
+ continue;
+ }
+
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
if (readbytes == (size_t) -1)
@@ -97,8 +106,10 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
}
if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Read went ok; Return 0 */
- DBUG_RETURN(readbytes); /* purecov: inspected */
+ readbytes= 0; /* Read went ok; Return 0 */
+ else
+ readbytes+= save_count;
+ DBUG_RETURN(readbytes);
}
} /* my_pread */
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 883a1c5fdc7..47f2d725f65 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -35,17 +35,16 @@
size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
{
- size_t readbytes, save_count;
+ size_t readbytes, save_count= 0;
DBUG_ENTER("my_read");
- DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d",
- Filedes, Buffer, (ulong) Count, MyFlags));
- save_count= Count;
+ DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %lu",
+ Filedes, Buffer, (ulong) Count, (ulong) MyFlags));
if (!(MyFlags & (MY_WME | MY_FAE | MY_FNABP)))
MyFlags|= my_global_flags;
for (;;)
{
- errno= 0; /* Linux, Windows don't reset this on EOF/success */
+ errno= 0; /* Linux, Windows don't reset this on EOF/success */
#ifdef _WIN32
readbytes= my_win_read(Filedes, Buffer, Count);
#else
@@ -61,47 +60,52 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
if (readbytes != Count)
{
- my_errno= errno;
- if (errno == 0 || (readbytes != (size_t) -1 &&
- (MyFlags & (MY_NABP | MY_FNABP))))
- my_errno= HA_ERR_FILE_TOO_SHORT;
+ int got_errno= my_errno= errno;
DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d",
(int) readbytes, (ulong) Count, Filedes,
- my_errno));
+ got_errno));
+
+ if (got_errno == 0 || (readbytes != (size_t) -1 &&
+ (MyFlags & (MY_NABP | MY_FNABP))))
+ my_errno= HA_ERR_FILE_TOO_SHORT;
- if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
- {
+ if ((readbytes == 0 || (int) readbytes == -1) && got_errno == EINTR)
+ {
DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld",
(long) readbytes));
continue; /* Interrupted */
}
+ /* Do a read retry if we didn't get enough data on first read */
+ if (readbytes != (size_t) -1 && readbytes != 0 &&
+ (MyFlags & MY_FULL_IO))
+ {
+ Buffer+= readbytes;
+ Count-= readbytes;
+ save_count+= readbytes;
+ continue;
+ }
+
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
if (readbytes == (size_t) -1)
my_error(EE_READ,
MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
- my_filename(Filedes),my_errno);
+ my_filename(Filedes), got_errno);
else if (MyFlags & (MY_NABP | MY_FNABP))
my_error(EE_EOFERR,
MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
- my_filename(Filedes),my_errno);
+ my_filename(Filedes), got_errno);
}
if (readbytes == (size_t) -1 ||
((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO)))
- DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
- if (readbytes != (size_t) -1 && (MyFlags & MY_FULL_IO))
- {
- Buffer+= readbytes;
- Count-= readbytes;
- continue;
- }
+ DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
}
if (MyFlags & (MY_NABP | MY_FNABP))
- readbytes= 0; /* Ok on read */
- else if (MyFlags & MY_FULL_IO)
- readbytes= save_count;
+ readbytes= 0; /* Ok on read */
+ else
+ readbytes+= save_count;
break;
}
DBUG_RETURN(readbytes);
1
0