File: rpl_parallel_start_stop.test

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (423 lines) | stat: -rw-r--r-- 10,635 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
#
# WL#5569/7165 MTS
#
# The test checks START and STOP, graceful, killing or
# due to an error of a Worker.
# START is considered to be with UNTIL that forces the sequential execution mode
# and with non-zero @@global.sql_replica_skip_counter that is compatible to
# the parallel mode.
# The test is MTS scheduler agnostic.
#

--source include/have_binlog_format_row.inc
--source include/force_myisam_default.inc
--source include/have_myisam.inc
--source include/master-slave.inc

# sql_replica_skip_counter is not supported with compression
--source include/not_binlog_transaction_compression_on.inc

--connection slave

call mtr.add_suppression("Replica SQL for channel '':.* Could not execute Write_rows event on table test.t1");
call mtr.add_suppression("Replica SQL for channel '':.* Could not execute Update_rows event on table d1.t1; Deadlock found when trying to get lock");
call mtr.add_suppression("The replica coordinator and worker threads are stopped, possibly leaving data in inconsistent state");

create view worker_proc_list as SELECT id  from Information_Schema.processlist
       where state like 'Waiting for an event from Coordinator';
create view coord_proc_list  as SELECT id from Information_Schema.processlist where state like 'Replica has read all relay log%';

source include/stop_slave.inc;

set @save.replica_parallel_workers= @@global.replica_parallel_workers;
set @@global.replica_parallel_workers= 4;

source include/start_slave.inc;

let $count= `select @@global.replica_parallel_workers`;
let $table= worker_proc_list;
source include/wait_until_rows_count.inc;

#
# KILL of a Worker stops the pool and the Coordinator
#
select min(id) from worker_proc_list into @w_id;
kill query @w_id;

let $count= 0;
let $table= worker_proc_list;
source include/wait_until_rows_count.inc;

--let $slave_sql_errno= convert_error(ER_MTA_INCONSISTENT_DATA)
source include/wait_for_slave_sql_to_stop.inc;

#
# KILL of the Coordinator stops the pool as well
#
source include/start_slave.inc;

# testing of the poll is up

let $count= `select @@global.replica_parallel_workers`;
let $table= worker_proc_list;
source include/wait_until_rows_count.inc;

let $count= 1;
let $table= coord_proc_list;
source include/wait_until_rows_count.inc;

select id from coord_proc_list into @c_id;

kill query @c_id;

let $count= 0;
let $table= worker_proc_list;
source include/wait_until_rows_count.inc;

let $slave_sql_errno= 1756; # ER_MTA_PARALLEL_INCONSISTENT_DATA
source include/wait_for_slave_sql_error.inc;

source include/start_slave.inc;

##
# Errored-out Worker stops the pool and the Coordinator
##

#
# A. A regular error case
#
--connection master

# make some load

CREATE TABLE t1 (a int primary key) engine=innodb;

insert into t1 values (1),(2);

--source include/sync_slave_sql_with_master.inc
#connection slave;

let $count= 2;
let $table= t1;
source include/wait_until_rows_count.inc;

# create an offending record
insert into t1 values (3);

--connection master

# hit it
insert into t1 values (3);

--connection slave

let $count= 0;
let $table= worker_proc_list;
source include/wait_until_rows_count.inc;

--let $slave_sql_errno= convert_error(ER_DUP_ENTRY)
source include/wait_for_slave_sql_to_stop.inc;
delete from t1 where a=3;

set @save.replica_transaction_retries= @@global.replica_transaction_retries;
set @@global.replica_transaction_retries= 10;
source include/start_slave.inc;

--connection master

--source include/sync_slave_sql_with_master.inc
#connection slave;

if (`select count(*) != 3 from t1`)
{
    query_vertical show slave status;
    --die Wrong recovery after restart
}

# cleanup but leaving on t1

--connection master
delete from t1;

--source include/sync_slave_sql_with_master.inc
#connection slave;

#
# B. In a temporary error execution is retried
#

--connection master
insert into t1 values (1),(2),(3);
create table t2m (a int) engine=myisam; # non-trans engine to detect deadlock
insert into t2m values (1);

--source include/sync_slave_sql_with_master.inc
#connection slave;

begin;
# set up a deadlock
update t1 set a=31 where a=3;
insert into t1 values (5),(6),(7);
update t1 set a=a+10;

--connection master

begin;
update t1 set a=20 where a=2;
insert into t2m values (2);
update t1 set a=30 where a=3;
commit;


--connection slave

let $count= 2;
let $table= t2m;
source include/wait_until_rows_count.inc;

# must victimize the master trans because of deadlock or timeout
update t1 set a=21 where a=2;

rollback;

--connection master

# recovery is proved
#--connection slave
--source include/sync_slave_sql_with_master.inc

#
# Skipping works with Parallel slave
#

--connection slave
stop slave sql_thread;
set @@global.sql_replica_skip_counter=7;

--connection master

# the following creates 8 events
begin;
select max(a) + 1 from t1 into @a;
insert into t1 set a=@a;
commit;
begin;
select max(a) + 1 from t1 into @a;
insert into t1 set a=@a;
commit;

# which will force to skip the two above transactions by the slave
# And the third will be executed:

begin;
select max(a) + 1 from t1 into @a;
insert into t1 set a=@a;
commit;

--connection slave

start slave sql_thread;

--connection master
let $a=`select max(a) from t1`;

--source include/sync_slave_sql_with_master.inc
#connection slave;

if (`select $a - max(a) from t1`)
{
    eval select $a as 'max(a) from t1 on master';
    eval select max(a) as 'max(a) from t1 on slave' from t1;
    --die Wrong skipping logics or a flaw in the test
}

#
# UNTIL condition other than SQL_AFTER_MTS_GAPS
# is not supported by Parallel slave to reject
# with a warning and no Worker thread is started
#

--connection slave
source include/stop_slave.inc;

--connection master
create table t2 (a int);

let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1);
let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1);

insert into t2 values (1);

--connection slave
--replace_regex /SOURCE_LOG_POS=[0-9]+/SOURCE_LOG_POS=MASTER_LOG_POS/
eval start slave until SOURCE_LOG_FILE='$master_log_file', SOURCE_LOG_POS=$master_log_pos;

source include/wait_for_slave_sql_to_stop.inc;
if (`select count(*) from t2`)
{
    select count(*) from t2;
    --die Wrong UNTIL condtion handling or a flaw in the test
}

source include/start_slave.inc;

##
# cleanup
##
--connection master
drop table t1;
drop table t2m;
drop table t2;

--source include/sync_slave_sql_with_master.inc
drop view worker_proc_list;
drop view coord_proc_list;

#
# START SLAVE UNTIL SQL_AFTER_MTS_GAPS
#
# A new UNTIL condition is introduced as a tool to
# fill gaps in the sequence of executed transaction started
# at Exec_Master_Log_Pos.
# The gaps could be caused by the previous slave session stop
# with an error, or it was killed, or the server crashed.
#

--connection slave

#
# Retry is supported now, but the following block of the test is written
# in assumption that it's not yet.
#
set @@global.replica_transaction_retries= 0;
source include/stop_slave.inc;

# Show SQL_AFTER_MTS_GAPS is meaningless in combination with coordinates
# related options
--error 1064
start slave until sql_after_mts_gaps relay_log_file='dummy';
--error 1064
start slave until sql_after_mts_gaps relay_log_pos=0;
--error 1064
start slave until sql_after_mts_gaps SOURCE_LOG_FILE='dummy';
--error 1064
start slave until sql_after_mts_gaps SOURCE_LOG_POS=0;
--error 1064
start slave until sql_after_mts_gaps SQL_BEFORE_GTIDS='dummy';

call mtr.add_suppression('Replica SQL for channel '': Could not execute Update_rows event on table d1.t1; Deadlock found when trying to get lock');

# regular start now
source include/start_slave.inc;

# set up gaps when slave sql errors out
--connection master

create database d1;
create database d2;
create table d1.t1 (a int primary key) engine=innodb;
create table d2.t1 (a int primary key) engine=innodb;
create table d1.t2m (a int) engine=myisam; # non-trans engine to detect deadlock
insert into d1.t1 values (1),(2),(3);
insert into d2.t1 values (1),(2),(3);
insert into d1.t2m values (1);

--source include/sync_slave_sql_with_master.inc
#connection slave;
begin; # the blocker
# set up a deadlock at the 1st job
update d1.t1 set a=31 where a=3;
insert into d1.t1 values (5),(6),(7);

# create the 1st job to get blocked on the slave
--connection master
begin;
update d1.t1 set a=20 where a=2;
insert into d1.t2m values (2);
update d1.t1 set a=30 where a=3;
insert into d1.t1 values (4);

# create the 2nd job for another worker
--connection master1
begin;
delete from d2.t1;

# the two jobs are parallelizable now regardless of the type of MTS scheduler
--connection master
commit;
--connection master1
commit;

--connection master
# create the 3nd job to help UNTIL SQL_AFTER_MTS_GAPS be reached
# (todo: if the last gap event ends the relay-log SQL thread will
# hang - to be fixed with MTS support for regular UNTIL:s)
delete from d1.t1;

# wait till the 2nd job will be done
connection slave1;
let $count= 0;
let $table= d2.t1;
source include/wait_until_rows_count.inc;

# proceed with 1st job into its middle
--connection slave
let $count= 2;
let $table= d1.t2m;
source include/wait_until_rows_count.inc;

# must victimize the master trans because of deadlock or timeout
update d1.t1 set a=21 where a=2;

# slave is stopped
# setting timeout to be as twice as greater than innodb's.
--let $slave_timeout=`select 2*@@global.innodb_lock_wait_timeout`

let $slave_sql_errno= 1213, 1205;
source include/wait_for_slave_sql_error.inc;

rollback; # the blocker

# find out Exec_Master_Log_Pos to store it in Exec_0
let $exec_pos_0= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);

start slave until sql_after_mts_gaps;

# Efficiency of UNTIL proof:
source include/wait_for_slave_sql_to_stop.inc;

# Consistency proof:

if (`select count(*) <> 4 from d1.t1`)
{
    --echo *** Something is wrong in recovery ***
    --die
}

# Efficiency of gap filling proof:
# find out Exec_Master_Log_Pos and compare with Exec_0
let $exec_pos_1= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);

if (`select $exec_pos_1 - $exec_pos_0 <= 0`)
{
    --echo *** No gap transaction is executed as expected ***
    --connection slave
    show slave status;
    --connection master
    show master status;
    --die
}

# UNTIL SQL_AFTER_MTS_GAPS cleanup
--disable_warnings
set @@global.replica_parallel_workers= @save.replica_parallel_workers;
--enable_warnings
source include/start_slave.inc;
--connection master
drop database d1;
drop database d2;

--source include/sync_slave_sql_with_master.inc
set @@global.replica_transaction_retries= @save.replica_transaction_retries;

--source include/rpl_end.inc