1--source include/have_tokudb.inc
2--source include/have_debug.inc
3--source include/have_debug_sync.inc
4--source include/master-slave.inc
5
6--connection master
7ALTER TABLE mysql.gtid_slave_pos ENGINE=TokuDB;
8CREATE TABLE t1 (a int PRIMARY KEY, b INT, UNIQUE KEY (b)) ENGINE=TokuDB;
9--save_master_pos
10
11--connection slave
12--sync_with_master
13SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
14--source include/stop_slave.inc
15SET GLOBAL slave_parallel_threads=10;
16CHANGE MASTER TO master_use_gtid=slave_pos;
17SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
18SET GLOBAL slave_parallel_mode='optimistic';
19
20
21--connection master
22
23INSERT INTO t1 VALUES(1,1);
24BEGIN;
25INSERT INTO t1 VALUES(2,2);
26INSERT INTO t1 VALUES(3,3);
27COMMIT;
28
29# Do a bunch of INSERT/DELETE on the same rows, bound to conflict.
30# We will get a lot of rollbacks, probably, but they should be handled without
31# any visible errors.
32
33DELETE FROM t1 WHERE a=2;
34INSERT INTO t1 VALUES (2,2);
35DELETE FROM t1 WHERE a=2;
36INSERT INTO t1 VALUES (2,6);
37DELETE FROM t1 WHERE a=2;
38INSERT INTO t1 VALUES (2,4);
39DELETE FROM t1 WHERE a=2;
40INSERT INTO t1 VALUES (2,5);
41
42DELETE FROM t1 WHERE a=3;
43INSERT INTO t1 VALUES(3,3);
44DELETE FROM t1 WHERE a=1;
45INSERT INTO t1 VALUES(1,4);
46DELETE FROM t1 WHERE a=3;
47INSERT INTO t1 VALUES(3,3);
48
49DELETE FROM t1 WHERE a=2;
50INSERT INTO t1 VALUES (2,6);
51--source include/save_master_gtid.inc
52SELECT * FROM t1 ORDER BY a;
53
54--connection slave
55--source include/start_slave.inc
56--source include/sync_with_master_gtid.inc
57SELECT * FROM t1 ORDER BY a;
58#SHOW STATUS LIKE 'Slave_retried_transactions';
59
60
61--echo *** Test a bunch of non-transactional/DDL event groups. ***
62
63--connection slave
64--source include/stop_slave.inc
65
66--connection master
67
68INSERT INTO t1 VALUES (4,8);
69INSERT INTO t1 VALUES (5,9);
70CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB;
71INSERT INTO t2 VALUES (1);
72CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=MyISAM;
73ALTER TABLE t2 ADD b INT;
74INSERT INTO t2 VALUES (2,2);
75ALTER TABLE t2 DROP b;
76INSERT INTO t2 VALUES (3);
77ALTER TABLE t2 ADD c INT;
78INSERT INTO t2 VALUES (4,5);
79INSERT INTO t2 VALUES (5,5);
80INSERT INTO t3 VALUES (1);
81UPDATE t2 SET c=NULL WHERE a=4;
82ALTER TABLE t2 ADD UNIQUE (c);
83INSERT INTO t2 VALUES (6,6);
84UPDATE t2 SET c=c+100 WHERE a=2;
85INSERT INTO t3(a) VALUES (2);
86DELETE FROM t3 WHERE a=2;
87INSERT INTO t3(a) VALUES (2);
88DELETE FROM t3 WHERE a=2;
89ALTER TABLE t3 CHANGE a c INT NOT NULL;
90INSERT INTO t3(c) VALUES (2);
91DELETE FROM t3 WHERE c=2;
92INSERT INTO t3 SELECT a+200 FROM t2;
93DELETE FROM t3 WHERE c >= 200;
94INSERT INTO t3 SELECT a+200 FROM t2;
95--source include/save_master_gtid.inc
96SELECT * FROM t1 ORDER BY a;
97SELECT * FROM t2 ORDER BY a;
98SELECT * FROM t3 ORDER BY c;
99
100--connection slave
101--source include/start_slave.inc
102--source include/sync_with_master_gtid.inc
103SELECT * FROM t1 ORDER BY a;
104SELECT * FROM t2 ORDER BY a;
105SELECT * FROM t3 ORDER BY c;
106#SHOW STATUS LIKE 'Slave_retried_transactions';
107
108
109--echo *** Test @@skip_parallel_replication. ***
110
111--connection slave
112--source include/stop_slave.inc
113--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
114
115--connection master
116# We do a bunch of conflicting transactions on the master with
117# skip_parallel_replication set to true, and check that we do not
118# get any retries on the slave.
119
120UPDATE t1 SET b=10 WHERE a=3;
121SET SESSION skip_parallel_replication=1;
122UPDATE t1 SET b=20 WHERE a=3;
123UPDATE t1 SET b=30 WHERE a=3;
124UPDATE t1 SET b=50 WHERE a=3;
125UPDATE t1 SET b=80 WHERE a=3;
126UPDATE t1 SET b=130 WHERE a=3;
127UPDATE t1 SET b=210 WHERE a=3;
128UPDATE t1 SET b=340 WHERE a=3;
129UPDATE t1 SET b=550 WHERE a=3;
130UPDATE t1 SET b=890 WHERE a=3;
131SET SESSION skip_parallel_replication=0;
132SELECT * FROM t1 ORDER BY a;
133--source include/save_master_gtid.inc
134
135--connection slave
136--source include/start_slave.inc
137--source include/sync_with_master_gtid.inc
138SELECT * FROM t1 ORDER BY a;
139--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
140--disable_query_log
141eval SELECT IF($retry1=$retry2, "Ok, no retry",
142       CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
143              $retry1, " now ", $retry2, ")")) AS status;
144--enable_query_log
145
146
147--echo *** Test that we do not replicate in parallel transactions that had row lock waits on the master ***
148
149--connection slave
150--source include/stop_slave.inc
151--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
152
153--connection master
154# Setup a bunch of transactions that all needed to wait.
155--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
156--connect (m2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
157--connect (m3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
158--connect (m4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
159--connect (m5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
160--connect (m6,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
161--connect (m7,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
162--connect (m8,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
163
164--connection default
165BEGIN; UPDATE t1 SET b=b+1 WHERE a=3;
166
167--connection m1
168SET debug_sync='thd_report_wait_for SIGNAL waiting1';
169send UPDATE t1 SET b=1001 WHERE a=3;
170--connection default
171SET debug_sync='now WAIT_FOR waiting1';
172
173--connection m2
174BEGIN;
175UPDATE t1 SET b=1002 WHERE a=5;
176SET debug_sync='thd_report_wait_for SIGNAL waiting2';
177send UPDATE t1 SET b=102 WHERE a=3;
178--connection default
179SET debug_sync='now WAIT_FOR waiting2';
180
181UPDATE t1 SET b=1000 WHERE a=1;
182--connection m3
183SET debug_sync='thd_report_wait_for SIGNAL waiting3';
184send UPDATE t1 SET b=1003 WHERE a=5;
185--connection default
186SET debug_sync='now WAIT_FOR waiting3';
187
188--connection m4
189SET debug_sync='thd_report_wait_for SIGNAL waiting4';
190send UPDATE t1 SET b=1004 WHERE a=3;
191--connection default
192SET debug_sync='now WAIT_FOR waiting4';
193
194--connection m5
195SET debug_sync='thd_report_wait_for SIGNAL waiting5';
196send UPDATE t1 SET b=1005 WHERE a=5;
197--connection default
198SET debug_sync='now WAIT_FOR waiting5';
199
200--connection m6
201SET debug_sync='thd_report_wait_for SIGNAL waiting6';
202send UPDATE t1 SET b=1006 WHERE a=1;
203--connection default
204SET debug_sync='now WAIT_FOR waiting6';
205
206--connection m7
207SET debug_sync='thd_report_wait_for SIGNAL waiting7';
208send UPDATE t1 SET b=1007 WHERE a=5;
209--connection default
210SET debug_sync='now WAIT_FOR waiting7';
211
212--connection m8
213SET debug_sync='thd_report_wait_for SIGNAL waiting8';
214send UPDATE t1 SET b=1008 WHERE a=3;
215--connection default
216SET debug_sync='now WAIT_FOR waiting8';
217
218--connection default
219COMMIT;
220--connection m1
221REAP;
222--connection m2
223REAP;
224COMMIT;
225--connection m3
226REAP;
227--connection m4
228REAP;
229--connection m5
230REAP;
231--connection m6
232REAP;
233--connection m7
234REAP;
235--connection m8
236REAP;
237--connection default
238SET debug_sync='RESET';
239
240--source include/save_master_gtid.inc
241# It is not deterministic in which order the parallel conflicting
242# updates will run. Eg. for key a=5, we could get 1003, 1005, or
243# 1007. As long as we get the same on the slave, it is ok.
244--let $master_value= `SELECT GROUP_CONCAT(CONCAT("(", a, ",", b, ")") ORDER BY a, b SEPARATOR "/") FROM t1`
245
246--connection slave
247--source include/start_slave.inc
248--source include/sync_with_master_gtid.inc
249--let $slave_value= `SELECT GROUP_CONCAT(CONCAT("(", a, ",", b, ")") ORDER BY a, b SEPARATOR "/") FROM t1`
250--disable_query_log
251eval SET @master_value="$master_value";
252eval SET @slave_value="$slave_value";
253--enable_query_log
254SELECT 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;
255--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
256--disable_query_log
257eval SELECT IF($retry1=$retry2, "Ok, no retry",
258       CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
259              $retry1, " now ", $retry2, ")")) AS status;
260--enable_query_log
261
262
263--echo *** Test that we replicate correctly when using READ COMMITTED and binlog_format=MIXED on the slave ***
264
265--connection slave
266--source include/stop_slave.inc
267SET @old_format= @@GLOBAL.binlog_format;
268# Use MIXED format; we cannot binlog ROW events on slave in STATEMENT format.
269SET GLOBAL binlog_format= MIXED;
270SET @old_isolation= @@GLOBAL.tx_isolation;
271SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
272# Reset the worker threads to make the new settings take effect.
273SET GLOBAL slave_parallel_threads=0;
274SET GLOBAL slave_parallel_threads=10;
275
276--connection master
277DROP TABLE t1, t2;
278CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=TokuDB;
279CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=TokuDB;
280INSERT INTO t1 VALUES (1,0), (2,0), (3,0);
281INSERT INTO t2 VALUES (1,0), (2,0);
282INSERT INTO t1 SELECT 4, COUNT(*) FROM t2;
283INSERT INTO t2 SELECT 4, COUNT(*) FROM t1;
284
285INSERT INTO t1 SELECT 5, COUNT(*) FROM t2;
286INSERT INTO t2 SELECT 5, COUNT(*) FROM t1;
287
288INSERT INTO t2 SELECT 6, COUNT(*) FROM t1;
289INSERT INTO t1 SELECT 6, COUNT(*) FROM t2;
290
291INSERT INTO t1 SELECT 7, COUNT(*) FROM t2;
292INSERT INTO t2 SELECT 7, COUNT(*) FROM t1;
293
294INSERT INTO t2 SELECT 8, COUNT(*) FROM t1;
295INSERT INTO t1 SELECT 8, COUNT(*) FROM t2;
296
297INSERT INTO t2 SELECT 9, COUNT(*) FROM t1;
298INSERT INTO t1 SELECT 9, COUNT(*) FROM t2;
299
300INSERT INTO t1 SELECT 10, COUNT(*) FROM t2;
301INSERT INTO t2 SELECT 10, COUNT(*) FROM t1;
302
303SELECT * FROM t1 ORDER BY a;
304SELECT * FROM t2 ORDER BY a;
305--source include/save_master_gtid.inc
306
307--connection slave
308--source include/start_slave.inc
309--source include/sync_with_master_gtid.inc
310SELECT * FROM t1 ORDER BY a;
311SELECT * FROM t2 ORDER BY a;
312
313--source include/stop_slave.inc
314SET GLOBAL binlog_format= @old_format;
315SET GLOBAL tx_isolation= @old_isolation;
316--source include/start_slave.inc
317
318
319--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
320
321--connection master
322DROP TABLE t1, t2, t3;
323CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=TokuDB;
324CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=TokuDB;
325CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=MyISAM;
326INSERT INTO t2 VALUES (1,1), (2,1), (3,1), (4,1), (5,1);
327--source include/save_master_gtid.inc
328
329--connection slave
330--source include/sync_with_master_gtid.inc
331--source include/stop_slave.inc
332SET @old_dbug= @@GLOBAL.debug_dbug;
333SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
334
335--connection master
336# The bug was that ANALYZE TABLE would call
337# wakeup_subsequent_commits() too early, allowing the following
338# transaction in the same group to run ahead and binlog and free the
339# GCO. Then we get wrong binlog order and later access freed GCO,
340# which causes lost wakeup of following GCO and thus replication hang.
341# We injected a small sleep in ANALYZE to make the race easier to hit (this
342# can only cause false negatives in versions with the bug, not false positives,
343# so sleep is ok here. And it's in general not possible to trigger reliably
344# the race with debug_sync, since the bugfix makes the race impossible).
345
346ALTER TABLE t2 COMMENT "123abc";
347ANALYZE TABLE t2;
348INSERT INTO t1 VALUES (1,2);
349INSERT INTO t1 VALUES (2,2);
350INSERT INTO t1 VALUES (3,2);
351INSERT INTO t1 VALUES (4,2);
352INSERT INTO t3 VALUES (1,3);
353ALTER TABLE t2 COMMENT "hello, world";
354BEGIN;
355INSERT INTO t1 VALUES (5,4);
356INSERT INTO t1 VALUES (6,4);
357INSERT INTO t1 VALUES (7,4);
358INSERT INTO t1 VALUES (8,4);
359INSERT INTO t1 VALUES (9,4);
360INSERT INTO t1 VALUES (10,4);
361INSERT INTO t1 VALUES (11,4);
362INSERT INTO t1 VALUES (12,4);
363INSERT INTO t1 VALUES (13,4);
364INSERT INTO t1 VALUES (14,4);
365INSERT INTO t1 VALUES (15,4);
366INSERT INTO t1 VALUES (16,4);
367INSERT INTO t1 VALUES (17,4);
368INSERT INTO t1 VALUES (18,4);
369INSERT INTO t1 VALUES (19,4);
370INSERT INTO t1 VALUES (20,4);
371COMMIT;
372INSERT INTO t1 VALUES (21,5);
373INSERT INTO t1 VALUES (22,5);
374
375SELECT * FROM t1 ORDER BY a;
376SELECT * FROM t2 ORDER BY a;
377SELECT * FROM t3 ORDER BY a;
378--source include/save_master_gtid.inc
379
380--connection slave
381--source include/start_slave.inc
382--source include/sync_with_master_gtid.inc
383
384SELECT * FROM t1 ORDER BY a;
385SELECT * FROM t2 ORDER BY a;
386SELECT * FROM t3 ORDER BY a;
387
388--source include/stop_slave.inc
389SET GLOBAL debug_dbug= @old_debug;
390--source include/start_slave.inc
391
392--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
393
394--connection slave
395--source include/stop_slave.inc
396SET @old_dbug= @@GLOBAL.debug_dbug;
397# The bug was that record_gtid(), when there is no existing transaction from
398# a DML event being replicated, would commit its own transaction. This wrongly
399# caused wakeup_subsequent_commits(), with similar consequences as MDEV-7888
400# above. We simulate this condition with a small sleep in record_gtid() for
401# a specific ANALYZE that we binlog with server id 100.
402SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
403
404--connection master
405
406ALTER TABLE t3 COMMENT "DDL statement 1";
407INSERT INTO t1 VALUES (30,0);
408INSERT INTO t1 VALUES (31,0);
409INSERT INTO t1 VALUES (32,0);
410INSERT INTO t1 VALUES (33,0);
411INSERT INTO t1 VALUES (34,0);
412INSERT INTO t1 VALUES (35,0);
413INSERT INTO t1 VALUES (36,0);
414SET @old_server_id= @@SESSION.server_id;
415SET SESSION server_id= 100;
416ANALYZE TABLE t2;
417SET SESSION server_id= @old_server_id;
418INSERT INTO t1 VALUES (37,0);
419ALTER TABLE t3 COMMENT "DDL statement 2";
420INSERT INTO t1 VALUES (38,0);
421INSERT INTO t1 VALUES (39,0);
422ALTER TABLE t3 COMMENT "DDL statement 3";
423
424SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
425
426--source include/save_master_gtid.inc
427
428
429--connection slave
430--source include/start_slave.inc
431--source include/sync_with_master_gtid.inc
432SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
433
434
435--source include/stop_slave.inc
436SET GLOBAL debug_dbug= @old_debug;
437--source include/start_slave.inc
438
439
440--echo *** MDEV-8113: ALTER TABLE causes slave hang in optimistic parallel replication ***
441
442--connection slave
443--source include/stop_slave.inc
444
445--connection master
446ALTER TABLE t2 ADD c INT;
447INSERT INTO t2 (a,b) VALUES (50, 0);
448INSERT INTO t2 (a,b) VALUES (51, 1);
449INSERT INTO t2 (a,b) VALUES (52, 2);
450INSERT INTO t2 (a,b) VALUES (53, 3);
451INSERT INTO t2 (a,b) VALUES (54, 4);
452INSERT INTO t2 (a,b) VALUES (55, 5);
453INSERT INTO t2 (a,b) VALUES (56, 6);
454INSERT INTO t2 (a,b) VALUES (57, 7);
455INSERT INTO t2 (a,b) VALUES (58, 8);
456INSERT INTO t2 (a,b) VALUES (59, 9);
457ALTER TABLE t2 DROP COLUMN c;
458SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
459--source include/save_master_gtid.inc
460
461--connection slave
462--source include/start_slave.inc
463--source include/sync_with_master_gtid.inc
464SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
465
466
467# Clean up.
468
469--connection slave
470--source include/stop_slave.inc
471SET GLOBAL slave_parallel_mode=@old_parallel_mode;
472SET GLOBAL slave_parallel_threads=@old_parallel_threads;
473--source include/start_slave.inc
474
475--connection master
476DROP TABLE t1, t2, t3;
477
478--source include/rpl_end.inc
479