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