1# Tests for various concurrency-related aspects of CREATE TABLE ... SELECT
2# and CREATE TABLE like implementation.
3#
4# Note that we don't test general CREATE TABLE ... SELECT/LIKE functionality
5# here as it is already covered by create.test. We are more interested in
6# extreme cases.
7#
8# This test takes rather long time so let us run it only in --big-test mode
9--source include/big_test.inc
10# We need the Debug Sync Facility.
11--source include/have_debug_sync.inc
12# Some of tests below also use binlog to check that statements are
13# executed and logged in correct order
14--source include/have_binlog_format_mixed_or_statement.inc
15# Save the initial number of concurrent sessions.
16--source include/count_sessions.inc
17
18# Create auxilliary connections
19connect (addconroot1, localhost, root,,);
20connect (addconroot2, localhost, root,,);
21connect (addconroot3, localhost, root,,);
22connection default;
23
24--disable_warnings
25drop table if exists t1,t2,t3,t4,t5;
26--enable_warnings
27set debug_sync='RESET';
28
29#
30# Tests for concurrency problems in CREATE TABLE ... SELECT
31#
32# We introduce delays between various stages of table creation
33# and check that other statements dealing with this table cannot
34# interfere during those delays.
35#
36# What happens in situation when other statement messes with
37# table to be created before it is created ?
38# Concurrent CREATE TABLE
39set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
40--send create table t1 select 1 as i;
41connection addconroot1;
42set debug_sync='now WAIT_FOR parked';
43--send create table t1 (j char(5));
44connection addconroot2;
45let $wait_condition=
46    select count(*) = 1 from information_schema.processlist
47    where state = "Waiting for table metadata lock" and
48          info = "create table t1 (j char(5))";
49--source include/wait_condition.inc
50set debug_sync='now SIGNAL go';
51connection default;
52--reap
53connection addconroot1;
54--error ER_TABLE_EXISTS_ERROR
55--reap
56connection default;
57show create table t1;
58drop table t1;
59
60# Concurrent CREATE TABLE ... SELECT
61set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
62--send create table t1 select 1 as i;
63connection addconroot1;
64set debug_sync='now WAIT_FOR parked';
65--send create table t1 select 'Test' as j;
66connection addconroot2;
67# Wait until the above CREATE TABLE t1 is blocked due to CREATE
68let $wait_condition=
69    select count(*) = 1 from information_schema.processlist
70    where state = "Waiting for table metadata lock" and
71          info = "create table t1 select 'Test' as j";
72--source include/wait_condition.inc
73set debug_sync='now SIGNAL go';
74connection default;
75--reap
76connection addconroot1;
77--error ER_TABLE_EXISTS_ERROR
78--reap
79connection default;
80show create table t1;
81drop table t1;
82
83# Concurrent CREATE TABLE LIKE
84create table t3 (j char(5));
85set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
86--send create table t1 select 1 as i;
87connection addconroot1;
88set debug_sync='now WAIT_FOR parked';
89--send create table t1 like t3;
90connection addconroot2;
91# Wait until the above CREATE TABLE t1 is blocked due to CREATE
92let $wait_condition=
93    select count(*) = 1 from information_schema.processlist
94    where state = "Waiting for table metadata lock" and
95          info = "create table t1 like t3";
96--source include/wait_condition.inc
97set debug_sync='now SIGNAL go';
98connection default;
99--reap
100connection addconroot1;
101--error ER_TABLE_EXISTS_ERROR
102--reap
103connection default;
104show create table t1;
105drop table t1;
106
107# Concurrent RENAME TABLE
108set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
109--send create table t1 select 1 as i;
110connection addconroot1;
111set debug_sync='now WAIT_FOR parked';
112--send rename table t3 to t1;
113connection addconroot2;
114# Wait until the above RENAME TABLE is blocked due to CREATE
115let $wait_condition=
116    select count(*) = 1 from information_schema.processlist
117    where state = "Waiting for table metadata lock" and
118          info = "rename table t3 to t1";
119--source include/wait_condition.inc
120set debug_sync='now SIGNAL go';
121connection default;
122--reap
123connection addconroot1;
124--error ER_TABLE_EXISTS_ERROR
125--reap
126connection default;
127show create table t1;
128drop table t1;
129
130# Concurrent ALTER TABLE RENAME
131set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
132--send create table t1 select 1 as i;
133connection addconroot1;
134set debug_sync='now WAIT_FOR parked';
135--send alter table t3 rename to t1
136connection addconroot2;
137# Wait until the above ALTER TABLE RENAME is blocked due to CREATE
138let $wait_condition=
139    select count(*) = 1 from information_schema.processlist
140    where state = "Waiting for table metadata lock" and
141          info = "alter table t3 rename to t1";
142--source include/wait_condition.inc
143set debug_sync='now SIGNAL go';
144connection default;
145--reap
146connection addconroot1;
147--error ER_TABLE_EXISTS_ERROR
148--reap
149connection default;
150show create table t1;
151drop table t1;
152
153# Concurrent ALTER TABLE RENAME which also adds column
154set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
155--send create table t1 select 1 as i;
156connection addconroot1;
157set debug_sync='now WAIT_FOR parked';
158--send alter table t3 rename to t1, add k int
159connection addconroot2;
160# Wait until the above ALTER TABLE RENAME is blocked due to CREATE
161let $wait_condition=
162    select count(*) = 1 from information_schema.processlist
163    where state = "Waiting for table metadata lock" and
164          info = "alter table t3 rename to t1, add k int";
165--source include/wait_condition.inc
166set debug_sync='now SIGNAL go';
167connection default;
168--reap
169connection addconroot1;
170--error ER_TABLE_EXISTS_ERROR
171--reap
172connection default;
173show create table t1;
174drop table t1,t3;
175
176# What happens if other statement sneaks in after the table
177# creation but before its opening ?
178set debug_sync='create_table_select_before_open SIGNAL parked WAIT_FOR go';
179connection default;
180
181# Concurrent DROP TABLE
182set debug_sync='create_table_select_before_open SIGNAL parked WAIT_FOR go';
183--send create table t1 select 1 as i;
184connection addconroot1;
185set debug_sync='now WAIT_FOR parked';
186--send drop table t1;
187connection addconroot2;
188# Wait until the above DROP TABLE is blocked due to CREATE
189let $wait_condition=
190    select count(*) = 1 from information_schema.processlist
191    where state = "Waiting for table metadata lock" and
192          info = "drop table t1";
193--source include/wait_condition.inc
194set debug_sync='now SIGNAL go';
195connection default;
196--reap
197connection addconroot1;
198--reap
199connection default;
200
201# Concurrent RENAME TABLE
202set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
203--send create table t1 select 1 as i;
204connection addconroot1;
205set debug_sync='now WAIT_FOR parked';
206--send rename table t1 to t2;
207connection addconroot2;
208# Wait until the above RENAME TABLE is blocked due to CREATE
209let $wait_condition=
210    select count(*) = 1 from information_schema.processlist
211    where state = "Waiting for table metadata lock" and
212          info = "rename table t1 to t2";
213--source include/wait_condition.inc
214set debug_sync='now SIGNAL go';
215connection default;
216--reap
217connection addconroot1;
218--reap
219connection default;
220drop table t2;
221
222# Concurrent SELECT
223set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
224--send create table t1 select 1 as i;
225connection addconroot1;
226set debug_sync='now WAIT_FOR parked';
227--send select * from t1;
228connection addconroot2;
229# Wait until the above SELECT is blocked due to CREATE
230let $wait_condition=
231    select count(*) = 1 from information_schema.processlist
232    where state = "Waiting for table metadata lock" and
233          info = "select * from t1";
234--source include/wait_condition.inc
235set debug_sync='now SIGNAL go';
236connection default;
237--reap
238connection addconroot1;
239--reap
240connection default;
241drop table t1;
242
243# Concurrent INSERT
244set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
245--send create table t1 select 1 as i;
246connection addconroot1;
247set debug_sync='now WAIT_FOR parked';
248--send insert into t1 values (2);
249connection addconroot2;
250# Wait until the above INSERT is blocked due to CREATE
251let $wait_condition=
252    select count(*) = 1 from information_schema.processlist
253    where state = "Waiting for table metadata lock" and
254          info = "insert into t1 values (2)";
255--source include/wait_condition.inc
256set debug_sync='now SIGNAL go';
257connection default;
258--reap
259connection addconroot1;
260--reap
261connection default;
262select * from t1;
263drop table t1;
264
265# Concurrent CREATE TRIGGER
266set @a:=0;
267set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
268--send create table t1 select 1 as i;
269connection addconroot1;
270set debug_sync='now WAIT_FOR parked';
271--send create trigger t1_bi before insert on t1 for each row set @a:=1;
272connection addconroot2;
273# Wait until the above CREATE TRIGGER is blocked due to CREATE TABLE
274let $wait_condition=
275    select count(*) = 1 from information_schema.processlist
276    where state = "Waiting for table metadata lock" and
277          info = "create trigger t1_bi before insert on t1 for each row set @a:=1";
278--source include/wait_condition.inc
279set debug_sync='now SIGNAL go';
280connection default;
281--reap
282connection addconroot1;
283--reap
284connection default;
285select @a;
286drop table t1;
287
288# Okay, now the same tests for the potential gap between open and lock
289set debug_sync='create_table_select_before_lock SIGNAL parked WAIT_FOR go';
290
291# Concurrent DROP TABLE
292--send create table t1 select 1 as i;
293connection addconroot1;
294set debug_sync='now WAIT_FOR parked';
295--send drop table t1;
296connection addconroot2;
297# Wait until the above DROP TABLE is blocked due to CREATE TABLE
298let $wait_condition=
299    select count(*) = 1 from information_schema.processlist
300    where state = "Waiting for table metadata lock" and
301          info = "drop table t1";
302--source include/wait_condition.inc
303set debug_sync='now SIGNAL go';
304connection default;
305--reap
306connection addconroot1;
307--reap
308connection default;
309
310# Concurrent RENAME TABLE
311set debug_sync='create_table_select_before_lock SIGNAL parked WAIT_FOR go';
312--send create table t1 select 1 as i;
313connection addconroot1;
314set debug_sync='now WAIT_FOR parked';
315--send rename table t1 to t2;
316connection addconroot2;
317# Wait until the above RENAME TABLE is blocked due to CREATE TABLE
318let $wait_condition=
319    select count(*) = 1 from information_schema.processlist
320    where state = "Waiting for table metadata lock" and
321          info = "rename table t1 to t2";
322--source include/wait_condition.inc
323set debug_sync='now SIGNAL go';
324connection default;
325--reap
326connection addconroot1;
327--reap
328connection default;
329drop table t2;
330
331# Concurrent SELECT
332set debug_sync='create_table_select_before_lock SIGNAL parked WAIT_FOR go';
333--send create table t1 select 1 as i;
334connection addconroot1;
335set debug_sync='now WAIT_FOR parked';
336--send select * from t1;
337connection addconroot2;
338# Wait until the above SELECT is blocked due to CREATE TABLE
339let $wait_condition=
340    select count(*) = 1 from information_schema.processlist
341    where state = "Waiting for table metadata lock" and
342          info = "select * from t1";
343--source include/wait_condition.inc
344set debug_sync='now SIGNAL go';
345connection default;
346--reap
347connection addconroot1;
348--reap
349connection default;
350drop table t1;
351
352# Concurrent INSERT
353set debug_sync='create_table_select_before_lock SIGNAL parked WAIT_FOR go';
354--send create table t1 select 1 as i;
355connection addconroot1;
356set debug_sync='now WAIT_FOR parked';
357--send insert into t1 values (2);
358connection addconroot2;
359# Wait until the above INSERT INTO t1 is blocked due to CREATE TABLE
360let $wait_condition=
361    select count(*) = 1 from information_schema.processlist
362    where state = "Waiting for table metadata lock" and
363          info = "insert into t1 values (2)";
364--source include/wait_condition.inc
365set debug_sync='now SIGNAL go';
366connection default;
367--reap
368connection addconroot1;
369--reap
370connection default;
371select * from t1;
372drop table t1;
373
374# Concurrent CREATE TRIGGER
375set @a:=0;
376set debug_sync='create_table_select_before_lock SIGNAL parked WAIT_FOR go';
377--send create table t1 select 1 as i;
378connection addconroot1;
379set debug_sync='now WAIT_FOR parked';
380--send create trigger t1_bi before insert on t1 for each row set @a:=1;
381connection addconroot2;
382# Wait until the above CREATE TRIGGER is blocked due to CREATE TABLE
383let $wait_condition=
384    select count(*) = 1 from information_schema.processlist
385    where state = "Waiting for table metadata lock" and
386          info = "create trigger t1_bi before insert on t1 for each row set @a:=1";
387--source include/wait_condition.inc
388set debug_sync='now SIGNAL go';
389connection default;
390--reap
391connection addconroot1;
392--reap
393connection default;
394select @a;
395drop table t1;
396
397# Concurrent DROP TABLE
398set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go';
399--send create table if not exists t1 select 1 as i
400connection addconroot1;
401set debug_sync='now WAIT_FOR parked';
402--send drop table t1
403connection addconroot2;
404# Wait until the above DROP TABLE is blocked due to CREATE TABLE
405let $wait_condition=
406    select count(*) = 1 from information_schema.processlist
407    where state = "Waiting for table metadata lock" and
408          info = "drop table t1";
409--source include/wait_condition.inc
410set debug_sync='now SIGNAL go';
411connection default;
412--reap
413connection addconroot1;
414--reap
415connection default;
416
417# Concurrent CREATE TRIGGER
418create table t1 (i int);
419set @a:=0;
420set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go';
421--send create table if not exists t1 select 1 as i
422connection addconroot1;
423set debug_sync='now WAIT_FOR parked';
424--send create trigger t1_bi before insert on t1 for each row set @a:=1
425connection addconroot2;
426# Wait until the above DROP TABLE is blocked due to CREATE TABLE
427let $wait_condition=
428    select count(*) = 1 from information_schema.processlist
429    where state = "Waiting for table metadata lock" and
430          info like "create trigger%";
431--source include/wait_condition.inc
432set debug_sync='now SIGNAL go';
433connection default;
434--reap
435connection addconroot1;
436--reap
437connection default;
438select @a;
439select * from t1;
440drop table t1;
441
442# Tests for possible concurrency issues with CREATE TABLE ... LIKE
443#
444# Bug #18950 "create table like does not obtain LOCK_open"
445# Bug #23667 "CREATE TABLE LIKE is not isolated from alteration by other
446#             connections"
447#
448# Again the idea of this test is that we introduce artificial delays on
449# various stages of table creation and check that concurrent statements
450# for tables from CREATE TABLE ... LIKE are not interfering.
451
452--disable_warnings
453drop table if exists t1,t2;
454--enable_warnings
455set debug_sync='RESET';
456
457# What happens if some statements sneak in right after we have
458# acquired locks and opened source table ?
459create table t1 (i int);
460set debug_sync='create_table_like_after_open SIGNAL parked WAIT_FOR go';
461# Reset binlog to have clear start
462reset master;
463--send create table t2 like t1;
464connection addconroot1;
465set debug_sync='now WAIT_FOR parked';
466# DML on source table should be allowed to run concurrently
467insert into t1 values (1);
468# And DDL should wait
469--send drop table t1;
470connection addconroot2;
471let $wait_condition=
472    select count(*) = 1 from information_schema.processlist
473    where state = "Waiting for table metadata lock" and
474          info = "drop table t1";
475--source include/wait_condition.inc
476set debug_sync='now SIGNAL go';
477connection default;
478--reap
479connection addconroot1;
480--reap
481connection default;
482show create table t2;
483drop table t2;
484# Let us check that statements were executed/binlogged in correct order
485source include/show_binlog_events.inc;
486
487# Now check the gap between table creation and binlogging
488create table t1 (i int);
489set debug_sync='create_table_like_before_binlog SIGNAL parked WAIT_FOR go';
490reset master;
491--send create table t2 like t1;
492connection addconroot1;
493set debug_sync='now WAIT_FOR parked';
494--send insert into t2 values (1);
495connection addconroot2;
496let $wait_condition=
497    select count(*) = 1 from information_schema.processlist
498    where state = "Waiting for table metadata lock" and
499          info = "insert into t2 values (1)";
500--source include/wait_condition.inc
501set debug_sync='now SIGNAL go';
502connection default;
503--reap
504
505connection addconroot1;
506--reap
507connection default;
508drop table t2;
509set debug_sync='create_table_like_before_binlog SIGNAL parked WAIT_FOR go';
510--send create table t2 like t1;
511connection addconroot1;
512set debug_sync='now WAIT_FOR parked';
513--send drop table t2;
514connection addconroot2;
515let $wait_condition=
516    select count(*) = 1 from information_schema.processlist
517    where state = "Waiting for table metadata lock" and
518          info = "drop table t2";
519--source include/wait_condition.inc
520set debug_sync='now SIGNAL go';
521connection default;
522--reap
523connection addconroot1;
524--reap
525connection default;
526set debug_sync='create_table_like_before_binlog SIGNAL parked WAIT_FOR go';
527--send create table t2 like t1;
528connection addconroot1;
529set debug_sync='now WAIT_FOR parked';
530--send drop table t1;
531connection addconroot2;
532let $wait_condition=
533    select count(*) = 1 from information_schema.processlist
534    where state = "Waiting for table metadata lock" and
535          info = "drop table t1";
536--source include/wait_condition.inc
537set debug_sync='now SIGNAL go';
538connection default;
539--reap
540connection addconroot1;
541--reap
542connection default;
543drop table t2;
544disconnect addconroot1;
545disconnect addconroot2;
546disconnect addconroot3;
547
548set debug_sync='RESET';
549source include/show_binlog_events.inc;
550# Check that all connections opened by test cases in this file are really
551# gone so execution of other tests won't be affected by their presence.
552--source include/wait_until_count_sessions.inc
553