1
by brian
clean slate |
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 are using some debug-only features in this test
|
|
11 |
--source include/have_debug.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 |
||
16 |
# Create auxilliary connections
|
|
17 |
connect (addconroot1, localhost, root,,); |
|
18 |
connect (addconroot2, localhost, root,,); |
|
19 |
connect (addconroot3, localhost, root,,); |
|
20 |
connection default; |
|
21 |
||
22 |
--disable_warnings |
|
23 |
drop table if exists t1,t2,t3,t4,t5; |
|
24 |
--enable_warnings |
|
25 |
||
26 |
||
27 |
#
|
|
28 |
# Tests for concurrency problems in CREATE TABLE ... SELECT
|
|
29 |
#
|
|
30 |
# We introduce delays between various stages of table creation
|
|
31 |
# and check that other statements dealing with this table cannot
|
|
32 |
# interfere during those delays.
|
|
33 |
#
|
|
34 |
# What happens in situation when other statement messes with
|
|
35 |
# table to be created before it is created ?
|
|
36 |
# Concurrent CREATE TABLE
|
|
37 |
set session debug="+d,sleep_create_select_before_create"; |
|
38 |
--send create table t1 select 1 as i; |
|
39 |
connection addconroot1; |
|
40 |
--sleep 2 |
|
41 |
--error ER_TABLE_EXISTS_ERROR |
|
42 |
create table t1 (j char(5)); |
|
43 |
connection default; |
|
44 |
--reap |
|
45 |
show create table t1; |
|
46 |
drop table t1; |
|
47 |
# Concurrent CREATE TABLE ... SELECT
|
|
48 |
--send create table t1 select 1 as i; |
|
49 |
connection addconroot1; |
|
50 |
--sleep 2 |
|
51 |
--error ER_TABLE_EXISTS_ERROR |
|
52 |
create table t1 select "Test" as j; |
|
53 |
connection default; |
|
54 |
--reap |
|
55 |
show create table t1; |
|
56 |
drop table t1; |
|
57 |
# Concurrent CREATE TABLE LIKE
|
|
58 |
create table t3 (j char(5)); |
|
59 |
--send create table t1 select 1 as i; |
|
60 |
connection addconroot1; |
|
61 |
--sleep 2 |
|
62 |
--error ER_TABLE_EXISTS_ERROR |
|
63 |
create table t1 like t3; |
|
64 |
connection default; |
|
65 |
--reap |
|
66 |
show create table t1; |
|
67 |
drop table t1; |
|
68 |
# Concurrent RENAME TABLE
|
|
69 |
--send create table t1 select 1 as i; |
|
70 |
connection addconroot1; |
|
71 |
--sleep 2 |
|
72 |
--error ER_TABLE_EXISTS_ERROR |
|
73 |
rename table t3 to t1; |
|
74 |
connection default; |
|
75 |
--reap |
|
76 |
show create table t1; |
|
77 |
drop table t1; |
|
78 |
# Concurrent ALTER TABLE RENAME
|
|
79 |
--send create table t1 select 1 as i; |
|
80 |
connection addconroot1; |
|
81 |
--sleep 2 |
|
82 |
--error ER_TABLE_EXISTS_ERROR |
|
83 |
alter table t3 rename to t1; |
|
84 |
connection default; |
|
85 |
--reap |
|
86 |
show create table t1; |
|
87 |
drop table t1; |
|
88 |
# Concurrent ALTER TABLE RENAME which also adds column
|
|
89 |
--send create table t1 select 1 as i; |
|
90 |
connection addconroot1; |
|
91 |
--sleep 2 |
|
92 |
--error ER_TABLE_EXISTS_ERROR |
|
93 |
alter table t3 rename to t1, add k int; |
|
94 |
connection default; |
|
95 |
--reap |
|
96 |
show create table t1; |
|
97 |
drop table t1, t3; |
|
98 |
# What happens if other statement sneaks in after the table
|
|
99 |
# creation but before its opening ?
|
|
100 |
set session debug="-d,sleep_create_select_before_create:+d,sleep_create_select_before_open"; |
|
101 |
# Concurrent DROP TABLE
|
|
102 |
--send create table t1 select 1 as i; |
|
103 |
connection addconroot1; |
|
104 |
--sleep 2 |
|
105 |
drop table t1; |
|
106 |
connection default; |
|
107 |
--reap |
|
108 |
# Concurrent RENAME TABLE
|
|
109 |
--send create table t1 select 1 as i; |
|
110 |
connection addconroot1; |
|
111 |
--sleep 2 |
|
112 |
rename table t1 to t2; |
|
113 |
connection default; |
|
114 |
--reap |
|
115 |
drop table t2; |
|
116 |
# Concurrent SELECT
|
|
117 |
--send create table t1 select 1 as i; |
|
118 |
connection addconroot1; |
|
119 |
--sleep 2 |
|
120 |
select * from t1; |
|
121 |
connection default; |
|
122 |
--reap |
|
123 |
drop table t1; |
|
124 |
# Concurrent INSERT
|
|
125 |
--send create table t1 select 1 as i; |
|
126 |
connection addconroot1; |
|
127 |
--sleep 2 |
|
128 |
insert into t1 values (2); |
|
129 |
connection default; |
|
130 |
--reap |
|
131 |
select * from t1; |
|
132 |
drop table t1; |
|
133 |
# Concurrent CREATE TRIGGER
|
|
134 |
set @a:=0; |
|
135 |
--send create table t1 select 1 as i; |
|
136 |
connection addconroot1; |
|
137 |
--sleep 2 |
|
138 |
create trigger t1_bi before insert on t1 for each row set @a:=1; |
|
139 |
connection default; |
|
140 |
--reap |
|
141 |
select @a; |
|
142 |
drop table t1; |
|
143 |
# Okay, now the same tests for the potential gap between open and lock
|
|
144 |
set session debug="-d,sleep_create_select_before_open:+d,sleep_create_select_before_lock"; |
|
145 |
# Concurrent DROP TABLE
|
|
146 |
--send create table t1 select 1 as i; |
|
147 |
connection addconroot1; |
|
148 |
--sleep 2 |
|
149 |
drop table t1; |
|
150 |
connection default; |
|
151 |
--reap |
|
152 |
# Concurrent RENAME TABLE
|
|
153 |
--send create table t1 select 1 as i; |
|
154 |
connection addconroot1; |
|
155 |
--sleep 2 |
|
156 |
rename table t1 to t2; |
|
157 |
connection default; |
|
158 |
--reap |
|
159 |
drop table t2; |
|
160 |
# Concurrent SELECT
|
|
161 |
--send create table t1 select 1 as i; |
|
162 |
connection addconroot1; |
|
163 |
--sleep 2 |
|
164 |
select * from t1; |
|
165 |
connection default; |
|
166 |
--reap |
|
167 |
drop table t1; |
|
168 |
# Concurrent INSERT
|
|
169 |
--send create table t1 select 1 as i; |
|
170 |
connection addconroot1; |
|
171 |
--sleep 2 |
|
172 |
insert into t1 values (2); |
|
173 |
connection default; |
|
174 |
--reap |
|
175 |
select * from t1; |
|
176 |
drop table t1; |
|
177 |
# Concurrent CREATE TRIGGER
|
|
178 |
set @a:=0; |
|
179 |
--send create table t1 select 1 as i; |
|
180 |
connection addconroot1; |
|
181 |
--sleep 2 |
|
182 |
create trigger t1_bi before insert on t1 for each row set @a:=1; |
|
183 |
connection default; |
|
184 |
--reap |
|
185 |
select @a; |
|
186 |
drop table t1; |
|
187 |
# Some tests for case with existing table
|
|
188 |
set session debug="-d,sleep_create_select_before_lock:+d,sleep_create_select_before_check_if_exists"; |
|
189 |
create table t1 (i int); |
|
190 |
# Concurrent DROP TABLE
|
|
191 |
--send create table if not exists t1 select 1 as i; |
|
192 |
connection addconroot1; |
|
193 |
--sleep 2 |
|
194 |
drop table t1; |
|
195 |
connection default; |
|
196 |
--reap |
|
197 |
# Concurrent CREATE TRIGGER
|
|
198 |
create table t1 (i int); |
|
199 |
set @a:=0; |
|
200 |
--send create table if not exists t1 select 1 as i; |
|
201 |
connection addconroot1; |
|
202 |
--sleep 2 |
|
203 |
create trigger t1_bi before insert on t1 for each row set @a:=1; |
|
204 |
connection default; |
|
205 |
--reap |
|
206 |
select @a; |
|
207 |
select * from t1; |
|
208 |
drop table t1; |
|
209 |
set session debug="-d,sleep_create_select_before_check_if_exists"; |
|
210 |
||
211 |
||
212 |
# Test for some details of CREATE TABLE ... SELECT implementation.
|
|
213 |
#
|
|
214 |
# We check that create placeholder is handled properly if we have
|
|
215 |
# to reopen tables in open_tables().
|
|
216 |
# This test heavily relies on current implementation of name-locking/
|
|
217 |
# table cache so it may stop working if it changes. OTOH it such problem
|
|
218 |
# will serve as warning that such changes should not be done lightly.
|
|
219 |
create table t2 (a int); |
|
220 |
create table t4 (b int); |
|
221 |
connection addconroot2; |
|
222 |
lock table t4 write; |
|
223 |
select 1; |
|
224 |
connection addconroot1; |
|
225 |
# Create placeholder/name-lock for t3
|
|
226 |
--send create table t3 as select * from t4; |
|
227 |
--sleep 2 |
|
228 |
connection default; |
|
229 |
# This statement creates placeholder for t1, then opens t2,
|
|
230 |
# then meets name-lock for t3 and then reopens all tables
|
|
231 |
--send create table t1 select * from t2, t3; |
|
232 |
--sleep 2 |
|
233 |
connection addconroot2; |
|
234 |
unlock tables; |
|
235 |
connection addconroot1; |
|
236 |
--reap |
|
237 |
connection default; |
|
238 |
--reap |
|
239 |
select * from t1; |
|
240 |
show create table t1; |
|
241 |
drop table t1, t3; |
|
242 |
# Now similar test which proves that we really temporarily
|
|
243 |
# remove placeholder when we reopen tables.
|
|
244 |
connection addconroot2; |
|
245 |
lock table t4 read; |
|
246 |
select 1; |
|
247 |
connection addconroot1; |
|
248 |
# Create name-lock for t3
|
|
249 |
--send rename table t4 to t3; |
|
250 |
--sleep 2 |
|
251 |
connection default; |
|
252 |
# This statement creates placeholder for t1, then opens t2,
|
|
253 |
# then meets name-lock for t3 and then reopens all tables
|
|
254 |
--send create table if not exists t1 select 1 as i from t2, t3; |
|
255 |
--sleep 2 |
|
256 |
connection addconroot3; |
|
257 |
# We should be able to take name-lock on table t1 as we should not have
|
|
258 |
# open placeholder for it at this point (otherwise it is possible to
|
|
259 |
# come-up with situation which will lead to deadlock, e.g. think of
|
|
260 |
# concurrent CREATE TABLE t1 SELECT * FROM t2 and RENAME TABLE t2 TO t1)
|
|
261 |
create table t5 (j int); |
|
262 |
# This statement takes name-lock on t1 and therefore proves
|
|
263 |
# that there is no active open placeholder for it.
|
|
264 |
rename table t5 to t1; |
|
265 |
connection addconroot2; |
|
266 |
unlock tables; |
|
267 |
connection addconroot1; |
|
268 |
--reap |
|
269 |
connection default; |
|
270 |
--reap |
|
271 |
select * from t1; |
|
272 |
show create table t1; |
|
273 |
drop table t1, t2, t3; |
|
274 |
||
275 |
||
276 |
# Tests for possible concurrency issues with CREATE TABLE ... LIKE
|
|
277 |
#
|
|
278 |
# Bug #18950 "create table like does not obtain LOCK_open"
|
|
279 |
# Bug #23667 "CREATE TABLE LIKE is not isolated from alteration by other
|
|
280 |
# connections"
|
|
281 |
#
|
|
282 |
# Again the idea of this test is that we introduce artificial delays on
|
|
283 |
# various stages of table creation and check that concurrent statements
|
|
284 |
# for tables from CREATE TABLE ... LIKE are not interfering.
|
|
285 |
||
286 |
--disable_warnings |
|
287 |
drop table if exists t1,t2; |
|
288 |
--enable_warnings |
|
289 |
||
290 |
# What happens if some statements sneak in right after we have
|
|
291 |
# opened source table ?
|
|
292 |
create table t1 (i int); |
|
293 |
set session debug="+d,sleep_create_like_before_check_if_exists"; |
|
294 |
# Reset binlog to have clear start
|
|
295 |
reset master; |
|
296 |
--send create table t2 like t1; |
|
297 |
connection addconroot1; |
|
298 |
--sleep 2 |
|
299 |
# DML on source table should be allowed to run concurrently
|
|
300 |
insert into t1 values (1); |
|
301 |
# And DDL should wait
|
|
302 |
drop table t1; |
|
303 |
connection default; |
|
304 |
--reap |
|
305 |
show create table t2; |
|
306 |
drop table t2; |
|
307 |
# Let us check that statements were executed/binlogged in correct order
|
|
308 |
--replace_column 2 # 5 # |
|
309 |
show binlog events in 'master-bin.000001' from 106; |
|
310 |
||
311 |
# Now let us check the gap between check for target table
|
|
312 |
# existance and copying of .frm file.
|
|
313 |
create table t1 (i int); |
|
314 |
set session debug="-d,sleep_create_like_before_check_if_exists:+d,sleep_create_like_before_copy"; |
|
315 |
# It should be impossible to create target table concurrently
|
|
316 |
--send create table t2 like t1; |
|
317 |
connection addconroot1; |
|
318 |
--sleep 2 |
|
319 |
create table if not exists t2 (j int); |
|
320 |
connection default; |
|
321 |
--reap |
|
322 |
show create table t2; |
|
323 |
drop table t2; |
|
324 |
# And concurrent DDL on the source table should be still disallowed
|
|
325 |
reset master; |
|
326 |
--send create table t2 like t1; |
|
327 |
connection addconroot1; |
|
328 |
--sleep 2 |
|
329 |
drop table t1; |
|
330 |
connection default; |
|
331 |
--reap |
|
332 |
drop table t2; |
|
333 |
--replace_column 2 # 5 # |
|
334 |
show binlog events in 'master-bin.000001' from 106; |
|
335 |
||
336 |
# And now he gap between copying of .frm file and ha_create_table() call.
|
|
337 |
create table t1 (i int); |
|
338 |
set session debug="-d,sleep_create_like_before_copy:+d,sleep_create_like_before_ha_create"; |
|
339 |
# Both DML and DDL on target table should wait till operation completes
|
|
340 |
reset master; |
|
341 |
--send create table t2 like t1; |
|
342 |
connection addconroot1; |
|
343 |
--sleep 2 |
|
344 |
insert into t2 values (1); |
|
345 |
connection default; |
|
346 |
--reap |
|
347 |
drop table t2; |
|
348 |
--send create table t2 like t1; |
|
349 |
connection addconroot1; |
|
350 |
--sleep 2 |
|
351 |
drop table t2; |
|
352 |
connection default; |
|
353 |
--reap |
|
354 |
# Concurrent DDL on the source table still waits
|
|
355 |
--send create table t2 like t1; |
|
356 |
connection addconroot1; |
|
357 |
--sleep 2 |
|
358 |
drop table t1; |
|
359 |
connection default; |
|
360 |
--reap |
|
361 |
drop table t2; |
|
362 |
--replace_column 2 # 5 # |
|
363 |
show binlog events in 'master-bin.000001' from 106; |
|
364 |
||
365 |
# Finally we check the gap between ha_create_table() and binlogging
|
|
366 |
create table t1 (i int); |
|
367 |
set session debug="-d,sleep_create_like_before_ha_create:+d,sleep_create_like_before_binlogging"; |
|
368 |
reset master; |
|
369 |
--send create table t2 like t1; |
|
370 |
connection addconroot1; |
|
371 |
--sleep 2 |
|
372 |
insert into t2 values (1); |
|
373 |
connection default; |
|
374 |
--reap |
|
375 |
drop table t2; |
|
376 |
--send create table t2 like t1; |
|
377 |
connection addconroot1; |
|
378 |
--sleep 2 |
|
379 |
drop table t2; |
|
380 |
connection default; |
|
381 |
--reap |
|
382 |
--send create table t2 like t1; |
|
383 |
connection addconroot1; |
|
384 |
--sleep 2 |
|
385 |
drop table t1; |
|
386 |
connection default; |
|
387 |
--reap |
|
388 |
drop table t2; |
|
389 |
--replace_column 2 # 5 # |
|
390 |
show binlog events in 'master-bin.000001' from 106; |
|
391 |
||
392 |
set session debug="-d,sleep_create_like_before_binlogging"; |