summaryrefslogtreecommitdiff
path: root/mysql-test/suite
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite')
-rw-r--r--mysql-test/suite/innodb/r/group_commit_binlog_pos.result2
-rw-r--r--mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result2
-rw-r--r--mysql-test/suite/perfschema/r/dml_setup_instruments.result8
-rw-r--r--mysql-test/suite/rpl/r/rpl_incident.result1
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel.result267
-rw-r--r--mysql-test/suite/rpl/t/rpl_incident-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_incident.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel.test353
-rw-r--r--mysql-test/suite/sys_vars/r/binlog_commit_wait_count_basic.result13
-rw-r--r--mysql-test/suite/sys_vars/r/binlog_commit_wait_usec_basic.result13
-rw-r--r--mysql-test/suite/sys_vars/r/slave_parallel_max_queued_basic.result13
-rw-r--r--mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result13
-rw-r--r--mysql-test/suite/sys_vars/t/binlog_commit_wait_count_basic.test14
-rw-r--r--mysql-test/suite/sys_vars/t/binlog_commit_wait_usec_basic.test14
-rw-r--r--mysql-test/suite/sys_vars/t/slave_parallel_max_queued_basic.test14
-rw-r--r--mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test14
16 files changed, 742 insertions, 7 deletions
diff --git a/mysql-test/suite/innodb/r/group_commit_binlog_pos.result b/mysql-test/suite/innodb/r/group_commit_binlog_pos.result
index c8b80a037a7..23f80b01a8d 100644
--- a/mysql-test/suite/innodb/r/group_commit_binlog_pos.result
+++ b/mysql-test/suite/innodb/r/group_commit_binlog_pos.result
@@ -31,6 +31,6 @@ a
1
2
3
-InnoDB: Last MySQL binlog file position 0 922, file name ./master-bin.000001
+InnoDB: Last MySQL binlog file position 0 926, file name ./master-bin.000001
SET DEBUG_SYNC= 'RESET';
DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result b/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result
index 090b574a962..3ef8a4acc0f 100644
--- a/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result
+++ b/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result
@@ -32,6 +32,6 @@ a
1
2
3
-InnoDB: Last MySQL binlog file position 0 922, file name ./master-bin.000001
+InnoDB: Last MySQL binlog file position 0 926, file name ./master-bin.000001
SET DEBUG_SYNC= 'RESET';
DROP TABLE t1;
diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result
index a9fb353aee5..ff3f9ec76fa 100644
--- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result
+++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result
@@ -38,14 +38,14 @@ order by name limit 10;
NAME ENABLED TIMED
wait/synch/cond/sql/COND_flush_thread_cache YES YES
wait/synch/cond/sql/COND_manager YES YES
+wait/synch/cond/sql/COND_parallel_entry YES YES
+wait/synch/cond/sql/COND_prepare_ordered YES YES
wait/synch/cond/sql/COND_queue_state YES YES
+wait/synch/cond/sql/COND_rpl_thread YES YES
+wait/synch/cond/sql/COND_rpl_thread_pool YES YES
wait/synch/cond/sql/COND_server_started YES YES
wait/synch/cond/sql/COND_thread_cache YES YES
wait/synch/cond/sql/COND_thread_count YES YES
-wait/synch/cond/sql/Delayed_insert::cond YES YES
-wait/synch/cond/sql/Delayed_insert::cond_client YES YES
-wait/synch/cond/sql/Event_scheduler::COND_state YES YES
-wait/synch/cond/sql/Item_func_sleep::cond YES YES
select * from performance_schema.setup_instruments
where name='Wait';
select * from performance_schema.setup_instruments
diff --git a/mysql-test/suite/rpl/r/rpl_incident.result b/mysql-test/suite/rpl/r/rpl_incident.result
index d528fb3297a..5e725e36389 100644
--- a/mysql-test/suite/rpl/r/rpl_incident.result
+++ b/mysql-test/suite/rpl/r/rpl_incident.result
@@ -8,6 +8,7 @@ a
1
2
3
+SET GLOBAL debug_dbug= '+d,incident_database_resync_on_replace,*';
REPLACE INTO t1 VALUES (4);
SELECT * FROM t1;
a
diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result
new file mode 100644
index 00000000000..b7fca7ea442
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel.result
@@ -0,0 +1,267 @@
+include/rpl_init.inc [topology=1->2]
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+*** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+LOCK TABLE t1 WRITE;
+SET gtid_domain_id=1;
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+SELECT * FROM t2 ORDER by a;
+a
+1
+2
+3
+4
+5
+6
+SELECT * FROM t1;
+a
+1
+UNLOCK TABLES;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+*** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+include/stop_slave.inc
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+FLUSH LOGS;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+SET debug_sync='now WAIT_FOR ready1';
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+SET debug_sync='now SIGNAL cont4';
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+FLUSH LOGS;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET debug_sync='RESET';
+include/start_slave.inc
+*** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+FLUSH LOGS;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''));
+SET debug_sync='now WAIT_FOR master_queued1';
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''));
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''));
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+master-bin.000002 # Xid # # COMMIT /* XID */
+master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+master-bin.000002 # Xid # # COMMIT /* XID */
+master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+master-bin.000002 # Xid # # COMMIT /* XID */
+master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+master-bin.000002 # Xid # # COMMIT /* XID */
+SET debug_sync='now WAIT_FOR slave_queued3';
+ROLLBACK;
+SET debug_sync='now WAIT_FOR slave_queued1';
+ROLLBACK;
+SET debug_sync='now WAIT_FOR slave_queued2';
+SET debug_sync='now SIGNAL slave_cont1';
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000003 # Binlog_checkpoint # # slave-bin.000003
+slave-bin.000003 # Gtid # # GTID #-#-#
+slave-bin.000003 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+slave-bin.000003 # Gtid # # BEGIN GTID #-#-#
+slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+slave-bin.000003 # Xid # # COMMIT /* XID */
+slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+slave-bin.000003 # Xid # # COMMIT /* XID */
+slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+slave-bin.000003 # Xid # # COMMIT /* XID */
+slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+slave-bin.000003 # Xid # # COMMIT /* XID */
+*** Test STOP SLAVE in parallel mode ***
+include/stop_slave.inc
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+SET binlog_format=@old_format;
+BEGIN;
+INSERT INTO t2 VALUES (21);
+START SLAVE;
+STOP SLAVE;
+ROLLBACK;
+include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+include/start_slave.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+21 21
+22 22
+include/stop_slave.inc
+SET GLOBAL binlog_format=@old_format;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+DROP function foo;
+DROP TABLE t1,t2,t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_incident-master.opt b/mysql-test/suite/rpl/t/rpl_incident-master.opt
deleted file mode 100644
index 912801debc4..00000000000
--- a/mysql-test/suite/rpl/t/rpl_incident-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---loose-debug=+d,incident_database_resync_on_replace
diff --git a/mysql-test/suite/rpl/t/rpl_incident.test b/mysql-test/suite/rpl/t/rpl_incident.test
index d6034009f4f..c591a8261c4 100644
--- a/mysql-test/suite/rpl/t/rpl_incident.test
+++ b/mysql-test/suite/rpl/t/rpl_incident.test
@@ -7,12 +7,19 @@ CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1;
+let $debug_save= `SELECT @@GLOBAL.debug`;
+SET GLOBAL debug_dbug= '+d,incident_database_resync_on_replace,*';
+
# This will generate an incident log event and store it in the binary
# log before the replace statement.
REPLACE INTO t1 VALUES (4);
--save_master_pos
SELECT * FROM t1;
+--disable_query_log
+eval SET GLOBAL debug_dbug= '$debug_save';
+--enable_query_log
+
connection slave;
# Wait until SQL thread stops with error LOST_EVENT on master
call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master.* 1590");
diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test
new file mode 100644
index 00000000000..5709cab19c0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel.test
@@ -0,0 +1,353 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL slave_parallel_threads=10;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+
+--echo *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+
+--connection server_1
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET gtid_domain_id=1;
+# This query will be blocked on the slave until UNLOCK TABLES.
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 6 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+ 'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+
+--connection server_2
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+# First make sure the first insert is ready to commit, but not queued yet.
+SET debug_sync='now WAIT_FOR ready1';
+
+--connection server_1
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+ 'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+
+--connection server_2
+# Now wait for the second insert to queue itself as the leader, and then
+# wait for more commits to queue up.
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+# Now allow the first insert to queue up to participate in group commit.
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+# Finally allow the second insert to proceed and do the group commit.
+SET debug_sync='now SIGNAL cont4';
+
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t2 WHERE a >= 10
+--source include/wait_condition.inc
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+# The two INSERT transactions should have been committed in opposite order,
+# but in the same group commit (seen by precense of cid=# in the SHOW
+# BINLOG output).
+--let $binlog_file= slave-bin.000002
+--source include/show_binlog_events.inc
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+
+# Restart all the slave parallel worker threads, to clear all debug_sync actions.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET debug_sync='RESET';
+--source include/start_slave.inc
+
+
+--echo *** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+--connection server_1
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+# Create some sentinel rows so that the rows inserted in parallel fall into
+# separate gaps and do not cause gap lock conflicts.
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+--save_master_pos
+--connection server_2
+--sync_with_master
+
+# We want to test that the transactions can execute out-of-order on
+# the slave, but still end up committing in-order, and in a single
+# group commit.
+#
+# The idea is to group-commit three transactions together on the master:
+# A, B, and C. On the slave, C will execute the insert first, then A,
+# and then B. But B manages to complete before A has time to commit, so
+# all three end up committing together.
+#
+# So we start by setting up some row locks that will block transactions
+# A and B from executing, allowing C to run first.
+
+--connection con_temp1
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+
+# On the master, queue three INSERT transactions as a single group commit.
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (2, foo(12,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (4, foo(14,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (6, foo(16,
+ 'group_commit_waiting_for_prior SIGNAL slave_queued3',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= master-bin.000002
+--source include/show_binlog_events.inc
+
+# First, wait until insert 3 is ready to queue up for group commit, but is
+# waiting for insert 2 to commit before it can do so itself.
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued3';
+
+# Next, let insert 1 proceed, and allow it to queue up as the group commit
+# leader, but let it wait for insert 2 to also queue up before proceeding.
+--connection con_temp1
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued1';
+
+# Now let insert 2 proceed and queue up.
+--connection con_temp2
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued2';
+# And finally, we can let insert 1 proceed and do the group commit with all
+# three insert transactions together.
+SET debug_sync='now SIGNAL slave_cont1';
+
+# Wait for the commit to complete and check that all three transactions
+# group-committed together (will be seen in the binlog as all three having
+# cid=# on their GTID event).
+--let $wait_condition= SELECT COUNT(*) = 3 FROM t3 WHERE a IN (2,4,6)
+--source include/wait_condition.inc
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= slave-bin.000003
+--source include/show_binlog_events.inc
+
+
+--echo *** Test STOP SLAVE in parallel mode ***
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+# Set up a couple of transactions. The first will be blocked halfway
+# through on a lock, and while it is blocked we initiate STOP SLAVE.
+# We then test that the halfway-initiated transaction is allowed to
+# complete, but no subsequent ones.
+# We have to use statement-based mode and set
+# binlog_direct_non_transactional_updates=0; otherwise the binlog will
+# be split into two event groups, one for the MyISAM part and one for the
+# InnoDB part.
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+--disable_warnings
+INSERT INTO t1 VALUES (20);
+--disable_warnings
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+SET binlog_format=@old_format;
+--save_master_pos
+
+# Start a connection that will block the replicated transaction halfway.
+--connection con_temp1
+BEGIN;
+INSERT INTO t2 VALUES (21);
+
+--connection server_2
+START SLAVE;
+# Wait for the MyISAM change to be visible, after which replication will wait
+# for con_temp1 to roll back.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE a=20
+--source include/wait_condition.inc
+
+--connection con_temp2
+# Initiate slave stop. It will have to wait for the current event group
+# to complete.
+send STOP SLAVE;
+
+--connection con_temp1
+ROLLBACK;
+
+--connection con_temp2
+reap;
+
+--connection server_2
+--source include/wait_for_slave_to_stop.inc
+# We should see the first transaction applied, but not the two others.
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL binlog_format=@old_format;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2,t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/binlog_commit_wait_count_basic.result b/mysql-test/suite/sys_vars/r/binlog_commit_wait_count_basic.result
new file mode 100644
index 00000000000..6837489311a
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/binlog_commit_wait_count_basic.result
@@ -0,0 +1,13 @@
+SET @save_binlog_commit_wait_count= @@GLOBAL.binlog_commit_wait_count;
+SELECT @@GLOBAL.binlog_commit_wait_count as 'must be zero because of default';
+must be zero because of default
+0
+SELECT @@SESSION.binlog_commit_wait_count as 'no session var';
+ERROR HY000: Variable 'binlog_commit_wait_count' is a GLOBAL variable
+SET GLOBAL binlog_commit_wait_count= 0;
+SET GLOBAL binlog_commit_wait_count= DEFAULT;
+SET GLOBAL binlog_commit_wait_count= 10;
+SELECT @@GLOBAL.binlog_commit_wait_count;
+@@GLOBAL.binlog_commit_wait_count
+10
+SET GLOBAL binlog_commit_wait_count = @save_binlog_commit_wait_count;
diff --git a/mysql-test/suite/sys_vars/r/binlog_commit_wait_usec_basic.result b/mysql-test/suite/sys_vars/r/binlog_commit_wait_usec_basic.result
new file mode 100644
index 00000000000..b85af0bc9c7
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/binlog_commit_wait_usec_basic.result
@@ -0,0 +1,13 @@
+SET @save_binlog_commit_wait_usec= @@GLOBAL.binlog_commit_wait_usec;
+SELECT @@GLOBAL.binlog_commit_wait_usec as 'check default';
+check default
+100000
+SELECT @@SESSION.binlog_commit_wait_usec as 'no session var';
+ERROR HY000: Variable 'binlog_commit_wait_usec' is a GLOBAL variable
+SET GLOBAL binlog_commit_wait_usec= 0;
+SET GLOBAL binlog_commit_wait_usec= DEFAULT;
+SET GLOBAL binlog_commit_wait_usec= 10000;
+SELECT @@GLOBAL.binlog_commit_wait_usec;
+@@GLOBAL.binlog_commit_wait_usec
+10000
+SET GLOBAL binlog_commit_wait_usec = @save_binlog_commit_wait_usec;
diff --git a/mysql-test/suite/sys_vars/r/slave_parallel_max_queued_basic.result b/mysql-test/suite/sys_vars/r/slave_parallel_max_queued_basic.result
new file mode 100644
index 00000000000..568ecac6de6
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/slave_parallel_max_queued_basic.result
@@ -0,0 +1,13 @@
+SET @save_slave_parallel_max_queued= @@GLOBAL.slave_parallel_max_queued;
+SELECT @@GLOBAL.slave_parallel_max_queued as 'Check default';
+Check default
+131072
+SELECT @@SESSION.slave_parallel_max_queued as 'no session var';
+ERROR HY000: Variable 'slave_parallel_max_queued' is a GLOBAL variable
+SET GLOBAL slave_parallel_max_queued= 0;
+SET GLOBAL slave_parallel_max_queued= DEFAULT;
+SET GLOBAL slave_parallel_max_queued= 65536;
+SELECT @@GLOBAL.slave_parallel_max_queued;
+@@GLOBAL.slave_parallel_max_queued
+65536
+SET GLOBAL slave_parallel_max_queued = @save_slave_parallel_max_queued;
diff --git a/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result b/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result
new file mode 100644
index 00000000000..2956d04c065
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result
@@ -0,0 +1,13 @@
+SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SELECT @@GLOBAL.slave_parallel_threads as 'must be zero because of default';
+must be zero because of default
+0
+SELECT @@SESSION.slave_parallel_threads as 'no session var';
+ERROR HY000: Variable 'slave_parallel_threads' is a GLOBAL variable
+SET GLOBAL slave_parallel_threads= 0;
+SET GLOBAL slave_parallel_threads= DEFAULT;
+SET GLOBAL slave_parallel_threads= 10;
+SELECT @@GLOBAL.slave_parallel_threads;
+@@GLOBAL.slave_parallel_threads
+10
+SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads;
diff --git a/mysql-test/suite/sys_vars/t/binlog_commit_wait_count_basic.test b/mysql-test/suite/sys_vars/t/binlog_commit_wait_count_basic.test
new file mode 100644
index 00000000000..ebce0da77fe
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/binlog_commit_wait_count_basic.test
@@ -0,0 +1,14 @@
+--source include/not_embedded.inc
+
+SET @save_binlog_commit_wait_count= @@GLOBAL.binlog_commit_wait_count;
+
+SELECT @@GLOBAL.binlog_commit_wait_count as 'must be zero because of default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@SESSION.binlog_commit_wait_count as 'no session var';
+
+SET GLOBAL binlog_commit_wait_count= 0;
+SET GLOBAL binlog_commit_wait_count= DEFAULT;
+SET GLOBAL binlog_commit_wait_count= 10;
+SELECT @@GLOBAL.binlog_commit_wait_count;
+
+SET GLOBAL binlog_commit_wait_count = @save_binlog_commit_wait_count;
diff --git a/mysql-test/suite/sys_vars/t/binlog_commit_wait_usec_basic.test b/mysql-test/suite/sys_vars/t/binlog_commit_wait_usec_basic.test
new file mode 100644
index 00000000000..ad9b6c99630
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/binlog_commit_wait_usec_basic.test
@@ -0,0 +1,14 @@
+--source include/not_embedded.inc
+
+SET @save_binlog_commit_wait_usec= @@GLOBAL.binlog_commit_wait_usec;
+
+SELECT @@GLOBAL.binlog_commit_wait_usec as 'check default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@SESSION.binlog_commit_wait_usec as 'no session var';
+
+SET GLOBAL binlog_commit_wait_usec= 0;
+SET GLOBAL binlog_commit_wait_usec= DEFAULT;
+SET GLOBAL binlog_commit_wait_usec= 10000;
+SELECT @@GLOBAL.binlog_commit_wait_usec;
+
+SET GLOBAL binlog_commit_wait_usec = @save_binlog_commit_wait_usec;
diff --git a/mysql-test/suite/sys_vars/t/slave_parallel_max_queued_basic.test b/mysql-test/suite/sys_vars/t/slave_parallel_max_queued_basic.test
new file mode 100644
index 00000000000..e3d3a9365f1
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/slave_parallel_max_queued_basic.test
@@ -0,0 +1,14 @@
+--source include/not_embedded.inc
+
+SET @save_slave_parallel_max_queued= @@GLOBAL.slave_parallel_max_queued;
+
+SELECT @@GLOBAL.slave_parallel_max_queued as 'Check default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@SESSION.slave_parallel_max_queued as 'no session var';
+
+SET GLOBAL slave_parallel_max_queued= 0;
+SET GLOBAL slave_parallel_max_queued= DEFAULT;
+SET GLOBAL slave_parallel_max_queued= 65536;
+SELECT @@GLOBAL.slave_parallel_max_queued;
+
+SET GLOBAL slave_parallel_max_queued = @save_slave_parallel_max_queued;
diff --git a/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test
new file mode 100644
index 00000000000..8e987489d86
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test
@@ -0,0 +1,14 @@
+--source include/not_embedded.inc
+
+SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
+
+SELECT @@GLOBAL.slave_parallel_threads as 'must be zero because of default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@SESSION.slave_parallel_threads as 'no session var';
+
+SET GLOBAL slave_parallel_threads= 0;
+SET GLOBAL slave_parallel_threads= DEFAULT;
+SET GLOBAL slave_parallel_threads= 10;
+SELECT @@GLOBAL.slave_parallel_threads;
+
+SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads;