diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
commit | a175314c3e5827eb193872241446f2f8f5c9d33c (patch) | |
tree | cd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/tokudb/mysql-test/tokudb_rpl/t | |
parent | Initial commit. (diff) | |
download | mariadb-10.5-upstream.tar.xz mariadb-10.5-upstream.zip |
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/tokudb/mysql-test/tokudb_rpl/t')
-rw-r--r-- | storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test | 317 | ||||
-rw-r--r-- | storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_optimistic.test | 478 |
2 files changed, 795 insertions, 0 deletions
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test new file mode 100644 index 00000000..a87da95a --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test @@ -0,0 +1,317 @@ +--source include/have_tokudb.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection server_2 +--source include/stop_slave.inc + +# Set GTID cleanup limit high enough that cleanup will not run and we +# can rely on consistent table output in .result. +--let $old_gtid_cleanup_batch_size=`SELECT @@GLOBAL.gtid_cleanup_batch_size` +SET GLOBAL gtid_cleanup_batch_size = 999999999; + +CHANGE MASTER TO master_use_gtid=slave_pos; +SET sql_log_bin=0; +CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; +ALTER TABLE mysql.gtid_slave_pos_innodb ENGINE=InnoDB; +CREATE TABLE mysql.gtid_slave_pos_tokudb LIKE mysql.gtid_slave_pos; +ALTER TABLE mysql.gtid_slave_pos_tokudb ENGINE=TokuDB; +CREATE TABLE mysql.gtid_slave_pos_myisam_redundant LIKE mysql.gtid_slave_pos; +CREATE TABLE mysql.gtid_slave_pos_innodb_redundant LIKE mysql.gtid_slave_pos; +ALTER TABLE mysql.gtid_slave_pos_innodb_redundant ENGINE=InnoDB; +call mtr.add_suppression("Ignoring redundant table.*since.*has the same storage engine"); +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t3 VALUES (1); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM mysql.gtid_slave_pos ORDER BY sub_id; +SELECT * FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select + ORDER BY sub_id; +SELECT * FROM mysql.gtid_slave_pos_tokudb ORDER BY sub_id; + + +# Test status variable Transactions_multi_engine. +--connection server_2 +FLUSH NO_WRITE_TO_BINLOG STATUS; +SET sql_log_bin=0; +SHOW STATUS LIKE "Transactions_multi_engine"; +INSERT INTO t1 VALUES (100); +SHOW STATUS LIKE "Transactions_multi_engine"; +INSERT INTO t2 VALUES (101); +SHOW STATUS LIKE "Transactions_multi_engine"; +INSERT INTO t3 VALUES (101); +SHOW STATUS LIKE "Transactions_multi_engine"; +BEGIN; +INSERT INTO t3 VALUES (102); +INSERT INTO t2 VALUES (103); +COMMIT; +SHOW STATUS LIKE "Transactions_multi_engine"; +BEGIN; +INSERT INTO t2 VALUES (104); +INSERT INTO t3 VALUES (105); +COMMIT; +SHOW STATUS LIKE "Transactions_multi_engine"; +UPDATE t2, t3 SET t2.a=106, t3.a=107 WHERE t2.a=104 AND t3.a=105; +SHOW STATUS LIKE "Transactions_multi_engine"; +# Try again with binlog enabled. +SET sql_log_bin=1; +INSERT INTO t1 VALUES (200); +SHOW STATUS LIKE "Transactions_multi_engine"; +INSERT INTO t2 VALUES (201); +SHOW STATUS LIKE "Transactions_multi_engine"; +INSERT INTO t3 VALUES (201); +SHOW STATUS LIKE "Transactions_multi_engine"; +BEGIN; +INSERT INTO t3 VALUES (202); +INSERT INTO t2 VALUES (203); +COMMIT; +SHOW STATUS LIKE "Transactions_multi_engine"; +BEGIN; +INSERT INTO t2 VALUES (204); +INSERT INTO t3 VALUES (205); +COMMIT; +SHOW STATUS LIKE "Transactions_multi_engine"; +UPDATE t2, t3 SET t2.a=206, t3.a=207 WHERE t2.a=204 AND t3.a=205; +SHOW STATUS LIKE "Transactions_multi_engine"; + +DELETE FROM t1 WHERE a >= 100; +DELETE FROM t2 WHERE a >= 100; +DELETE FROM t3 WHERE a >= 100; + + +# Create a bunch more GTIDs in mysql.gtid_slave_pos* tables to test with. +--connection server_1 +--disable_query_log +let $i=10; +while ($i) { + eval INSERT INTO t1 VALUES (300+$i); + eval INSERT INTO t2 VALUES (300+$i); + eval INSERT INTO t3 VALUES (300+$i); + dec $i; +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +# Check that we have many rows in mysql.gtid_slave_pos now (since +# @@gtid_cleanup_batch_size was set to a huge value). No need to check +# for an exact number, since that will require changing .result if +# anything changes prior to this point, and we just need to know that +# we have still have some data in the tables to make the following +# test effective. +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos; +SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select; +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_tokudb; + +# Check that old GTID rows will be deleted when batch delete size is +# set reasonably. Old row deletion is not 100% deterministic (by design), so +# we must wait for it to occur, but it should occur eventually. +SET GLOBAL gtid_cleanup_batch_size = 3; +let $i=40; +--disable_query_log +--let $keep_include_silent=1 +while ($i) { + let N=`SELECT 1+($i MOD 3)`; + --connection server_1 + eval UPDATE t$N SET a=a+1 WHERE a=(SELECT MAX(a) FROM t$N); + --source include/save_master_gtid.inc + --connection server_2 + --source include/sync_with_master_gtid.inc + let $j=50; + while ($j) { + let $is_done=`SELECT SUM(a)=1 FROM ( + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos + UNION ALL + SELECT COUNT(*) AS a FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select + UNION ALL + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos_tokudb) outer_select`; + if ($is_done) { + let $j=0; + } + if (!$is_done) { + real_sleep 0.1; + dec $j; + } + } + dec $i; + if ($is_done) { + let $i=0; + } +} +--enable_query_log +--let $keep_include_silent=0 +if (!$is_done) { + --echo Timed out waiting for mysql.gtid_slave_pos* tables to be cleaned up +} + +--disable_query_log +DELETE FROM t1 WHERE a >= 100; +DELETE FROM t2 WHERE a >= 100; +DELETE FROM t3 WHERE a >= 100; +--enable_query_log + + +# Test status variables Rpl_transactions_multi_engine and Transactions_gtid_foreign_engine. +# Have mysql.gtid_slave_pos* for myisam and innodb but not tokudb. +--connection server_2 +--source include/stop_slave.inc +SET sql_log_bin=0; +DROP TABLE mysql.gtid_slave_pos_tokudb; +DROP TABLE mysql.gtid_slave_pos_myisam_redundant; +DROP TABLE mysql.gtid_slave_pos_innodb_redundant; +SET sql_log_bin=1; +FLUSH NO_WRITE_TO_BINLOG STATUS; +--source include/start_slave.inc +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t1 VALUES (100); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t2 VALUES (101); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t3 VALUES (101); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +BEGIN; +INSERT INTO t3 VALUES (102); +INSERT INTO t2 VALUES (103); +COMMIT; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +BEGIN; +INSERT INTO t2 VALUES (104); +INSERT INTO t3 VALUES (105); +COMMIT; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +UPDATE t2, t3 SET t2.a=106, t3.a=107 WHERE t2.a=104 AND t3.a=105; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +# Now the same thing, but without binlogging on the slave. +--connection server_2 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +# Restart without binary log. +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-log-bin +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +SHOW VARIABLES LIKE 'log_bin'; +--source include/start_slave.inc +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t1 VALUES (200); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t2 VALUES (201); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +INSERT INTO t3 VALUES (201); +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +BEGIN; +INSERT INTO t3 VALUES (202); +INSERT INTO t2 VALUES (203); +COMMIT; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +BEGIN; +INSERT INTO t2 VALUES (204); +INSERT INTO t3 VALUES (205); +COMMIT; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + +--connection server_1 +UPDATE t2, t3 SET t2.a=206, t3.a=207 WHERE t2.a=204 AND t3.a=205; +--save_master_pos +--connection server_2 +--sync_with_master +SHOW STATUS LIKE "%transactions%engine"; + + +--connection server_2 +SET sql_log_bin=0; +DROP TABLE mysql.gtid_slave_pos_innodb; +SET sql_log_bin=1; +--disable_query_log +eval SET GLOBAL gtid_cleanup_batch_size = $old_gtid_cleanup_batch_size; +--enable_query_log + +--connection server_1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_optimistic.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_optimistic.test new file mode 100644 index 00000000..c7c7de9d --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_optimistic.test @@ -0,0 +1,478 @@ +--source include/have_tokudb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc + +--connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=TokuDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT, UNIQUE KEY (b)) ENGINE=TokuDB; +--save_master_pos + +--connection slave +--sync_with_master +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--connection master + +INSERT INTO t1 VALUES(1,1); +BEGIN; +INSERT INTO t1 VALUES(2,2); +INSERT INTO t1 VALUES(3,3); +COMMIT; + +# Do a bunch of INSERT/DELETE on the same rows, bound to conflict. +# We will get a lot of rollbacks, probably, but they should be handled without +# any visible errors. + +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,2); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,6); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,4); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,5); + +DELETE FROM t1 WHERE a=3; +INSERT INTO t1 VALUES(3,3); +DELETE FROM t1 WHERE a=1; +INSERT INTO t1 VALUES(1,4); +DELETE FROM t1 WHERE a=3; +INSERT INTO t1 VALUES(3,3); + +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,6); +--source include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +#SHOW STATUS LIKE 'Slave_retried_transactions'; + + +--echo *** Test a bunch of non-transactional/DDL event groups. *** + +--connection slave +--source include/stop_slave.inc + +--connection master + +INSERT INTO t1 VALUES (4,8); +INSERT INTO t1 VALUES (5,9); +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t2 VALUES (1); +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=MyISAM; +ALTER TABLE t2 ADD b INT; +INSERT INTO t2 VALUES (2,2); +ALTER TABLE t2 DROP b; +INSERT INTO t2 VALUES (3); +ALTER TABLE t2 ADD c INT; +INSERT INTO t2 VALUES (4,5); +INSERT INTO t2 VALUES (5,5); +INSERT INTO t3 VALUES (1); +UPDATE t2 SET c=NULL WHERE a=4; +ALTER TABLE t2 ADD UNIQUE (c); +INSERT INTO t2 VALUES (6,6); +UPDATE t2 SET c=c+100 WHERE a=2; +INSERT INTO t3(a) VALUES (2); +DELETE FROM t3 WHERE a=2; +INSERT INTO t3(a) VALUES (2); +DELETE FROM t3 WHERE a=2; +ALTER TABLE t3 CHANGE a c INT NOT NULL; +INSERT INTO t3(c) VALUES (2); +DELETE FROM t3 WHERE c=2; +INSERT INTO t3 SELECT a+200 FROM t2; +DELETE FROM t3 WHERE c >= 200; +INSERT INTO t3 SELECT a+200 FROM t2; +--source include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY c; + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY c; +#SHOW STATUS LIKE 'Slave_retried_transactions'; + + +--echo *** Test @@skip_parallel_replication. *** + +--connection slave +--source include/stop_slave.inc +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) + +--connection master +# We do a bunch of conflicting transactions on the master with +# skip_parallel_replication set to true, and check that we do not +# get any retries on the slave. + +UPDATE t1 SET b=10 WHERE a=3; +SET SESSION skip_parallel_replication=1; +UPDATE t1 SET b=20 WHERE a=3; +UPDATE t1 SET b=30 WHERE a=3; +UPDATE t1 SET b=50 WHERE a=3; +UPDATE t1 SET b=80 WHERE a=3; +UPDATE t1 SET b=130 WHERE a=3; +UPDATE t1 SET b=210 WHERE a=3; +UPDATE t1 SET b=340 WHERE a=3; +UPDATE t1 SET b=550 WHERE a=3; +UPDATE t1 SET b=890 WHERE a=3; +SET SESSION skip_parallel_replication=0; +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +--echo *** Test that we do not replicate in parallel transactions that had row lock waits on the master *** + +--connection slave +--source include/stop_slave.inc +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) + +--connection master +# Setup a bunch of transactions that all needed to wait. +--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m2,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m4,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m5,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m6,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m7,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m8,127.0.0.1,root,,test,$SERVER_MYPORT_1,) + +--connection default +BEGIN; UPDATE t1 SET b=b+1 WHERE a=3; + +--connection m1 +SET debug_sync='thd_report_wait_for SIGNAL waiting1'; +send UPDATE t1 SET b=1001 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting1'; + +--connection m2 +BEGIN; +UPDATE t1 SET b=1002 WHERE a=5; +SET debug_sync='thd_report_wait_for SIGNAL waiting2'; +send UPDATE t1 SET b=102 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting2'; + +UPDATE t1 SET b=1000 WHERE a=1; +--connection m3 +SET debug_sync='thd_report_wait_for SIGNAL waiting3'; +send UPDATE t1 SET b=1003 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting3'; + +--connection m4 +SET debug_sync='thd_report_wait_for SIGNAL waiting4'; +send UPDATE t1 SET b=1004 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting4'; + +--connection m5 +SET debug_sync='thd_report_wait_for SIGNAL waiting5'; +send UPDATE t1 SET b=1005 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting5'; + +--connection m6 +SET debug_sync='thd_report_wait_for SIGNAL waiting6'; +send UPDATE t1 SET b=1006 WHERE a=1; +--connection default +SET debug_sync='now WAIT_FOR waiting6'; + +--connection m7 +SET debug_sync='thd_report_wait_for SIGNAL waiting7'; +send UPDATE t1 SET b=1007 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting7'; + +--connection m8 +SET debug_sync='thd_report_wait_for SIGNAL waiting8'; +send UPDATE t1 SET b=1008 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting8'; + +--connection default +COMMIT; +--connection m1 +REAP; +--connection m2 +REAP; +COMMIT; +--connection m3 +REAP; +--connection m4 +REAP; +--connection m5 +REAP; +--connection m6 +REAP; +--connection m7 +REAP; +--connection m8 +REAP; +--connection default +SET debug_sync='RESET'; + +--source include/save_master_gtid.inc +# It is not deterministic in which order the parallel conflicting +# updates will run. Eg. for key a=5, we could get 1003, 1005, or +# 1007. As long as we get the same on the slave, it is ok. +--let $master_value= `SELECT GROUP_CONCAT(CONCAT("(", a, ",", b, ")") ORDER BY a, b SEPARATOR "/") FROM t1` + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +--let $slave_value= `SELECT GROUP_CONCAT(CONCAT("(", a, ",", b, ")") ORDER BY a, b SEPARATOR "/") FROM t1` +--disable_query_log +eval SET @master_value="$master_value"; +eval SET @slave_value="$slave_value"; +--enable_query_log +SELECT IF(@master_value=@slave_value, "Slave data matches master", CONCAT("ERROR: Slave had different data '", @slave_value, "' than master's '", @master_value, "'!")) as check_result; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +--echo *** Test that we replicate correctly when using READ COMMITTED and binlog_format=MIXED on the slave *** + +--connection slave +--source include/stop_slave.inc +SET @old_format= @@GLOBAL.binlog_format; +# Use MIXED format; we cannot binlog ROW events on slave in STATEMENT format. +SET GLOBAL binlog_format= MIXED; +SET @old_isolation= @@GLOBAL.tx_isolation; +SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; +# Reset the worker threads to make the new settings take effect. +SET GLOBAL slave_parallel_threads=0; +SET GLOBAL slave_parallel_threads=10; + +--connection master +DROP TABLE t1, t2; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=TokuDB; +CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1,0), (2,0), (3,0); +INSERT INTO t2 VALUES (1,0), (2,0); +INSERT INTO t1 SELECT 4, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 4, COUNT(*) FROM t1; + +INSERT INTO t1 SELECT 5, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 5, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 6, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 6, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 7, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 7, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 8, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 8, COUNT(*) FROM t2; + +INSERT INTO t2 SELECT 9, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 9, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 10, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 10, COUNT(*) FROM t1; + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL binlog_format= @old_format; +SET GLOBAL tx_isolation= @old_isolation; +--source include/start_slave.inc + + +--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang *** + +--connection master +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=TokuDB; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=TokuDB; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,1), (2,1), (3,1), (4,1), (5,1); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep'; + +--connection master +# The bug was that ANALYZE TABLE would call +# wakeup_subsequent_commits() too early, allowing the following +# transaction in the same group to run ahead and binlog and free the +# GCO. Then we get wrong binlog order and later access freed GCO, +# which causes lost wakeup of following GCO and thus replication hang. +# We injected a small sleep in ANALYZE to make the race easier to hit (this +# can only cause false negatives in versions with the bug, not false positives, +# so sleep is ok here. And it's in general not possible to trigger reliably +# the race with debug_sync, since the bugfix makes the race impossible). + +ALTER TABLE t2 COMMENT "123abc"; +ANALYZE TABLE t2; +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,2); +INSERT INTO t1 VALUES (3,2); +INSERT INTO t1 VALUES (4,2); +INSERT INTO t3 VALUES (1,3); +ALTER TABLE t2 COMMENT "hello, world"; +BEGIN; +INSERT INTO t1 VALUES (5,4); +INSERT INTO t1 VALUES (6,4); +INSERT INTO t1 VALUES (7,4); +INSERT INTO t1 VALUES (8,4); +INSERT INTO t1 VALUES (9,4); +INSERT INTO t1 VALUES (10,4); +INSERT INTO t1 VALUES (11,4); +INSERT INTO t1 VALUES (12,4); +INSERT INTO t1 VALUES (13,4); +INSERT INTO t1 VALUES (14,4); +INSERT INTO t1 VALUES (15,4); +INSERT INTO t1 VALUES (16,4); +INSERT INTO t1 VALUES (17,4); +INSERT INTO t1 VALUES (18,4); +INSERT INTO t1 VALUES (19,4); +INSERT INTO t1 VALUES (20,4); +COMMIT; +INSERT INTO t1 VALUES (21,5); +INSERT INTO t1 VALUES (22,5); + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL debug_dbug= @old_debug; +--source include/start_slave.inc + +--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. *** + +--connection slave +--source include/stop_slave.inc +SET @old_dbug= @@GLOBAL.debug_dbug; +# The bug was that record_gtid(), when there is no existing transaction from +# a DML event being replicated, would commit its own transaction. This wrongly +# caused wakeup_subsequent_commits(), with similar consequences as MDEV-7888 +# above. We simulate this condition with a small sleep in record_gtid() for +# a specific ANALYZE that we binlog with server id 100. +SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep'; + +--connection master + +ALTER TABLE t3 COMMENT "DDL statement 1"; +INSERT INTO t1 VALUES (30,0); +INSERT INTO t1 VALUES (31,0); +INSERT INTO t1 VALUES (32,0); +INSERT INTO t1 VALUES (33,0); +INSERT INTO t1 VALUES (34,0); +INSERT INTO t1 VALUES (35,0); +INSERT INTO t1 VALUES (36,0); +SET @old_server_id= @@SESSION.server_id; +SET SESSION server_id= 100; +ANALYZE TABLE t2; +SET SESSION server_id= @old_server_id; +INSERT INTO t1 VALUES (37,0); +ALTER TABLE t3 COMMENT "DDL statement 2"; +INSERT INTO t1 VALUES (38,0); +INSERT INTO t1 VALUES (39,0); +ALTER TABLE t3 COMMENT "DDL statement 3"; + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/save_master_gtid.inc + + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + + +--source include/stop_slave.inc +SET GLOBAL debug_dbug= @old_debug; +--source include/start_slave.inc + + +--echo *** MDEV-8113: ALTER TABLE causes slave hang in optimistic parallel replication *** + +--connection slave +--source include/stop_slave.inc + +--connection master +ALTER TABLE t2 ADD c INT; +INSERT INTO t2 (a,b) VALUES (50, 0); +INSERT INTO t2 (a,b) VALUES (51, 1); +INSERT INTO t2 (a,b) VALUES (52, 2); +INSERT INTO t2 (a,b) VALUES (53, 3); +INSERT INTO t2 (a,b) VALUES (54, 4); +INSERT INTO t2 (a,b) VALUES (55, 5); +INSERT INTO t2 (a,b) VALUES (56, 6); +INSERT INTO t2 (a,b) VALUES (57, 7); +INSERT INTO t2 (a,b) VALUES (58, 8); +INSERT INTO t2 (a,b) VALUES (59, 9); +ALTER TABLE t2 DROP COLUMN c; +SELECT * FROM t2 WHERE a >= 50 ORDER BY a; +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t2 WHERE a >= 50 ORDER BY a; + + +# Clean up. + +--connection slave +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1, t2, t3; + +--source include/rpl_end.inc |