summaryrefslogtreecommitdiff
path: root/mysql-test/t/create-big.test
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/t/create-big.test')
-rw-r--r--mysql-test/t/create-big.test392
1 files changed, 392 insertions, 0 deletions
diff --git a/mysql-test/t/create-big.test b/mysql-test/t/create-big.test
new file mode 100644
index 00000000000..6cd6326cdb8
--- /dev/null
+++ b/mysql-test/t/create-big.test
@@ -0,0 +1,392 @@
+# Tests for various concurrency-related aspects of CREATE TABLE ... SELECT
+# and CREATE TABLE like implementation.
+#
+# Note that we don't test general CREATE TABLE ... SELECT/LIKE functionality
+# here as it is already covered by create.test. We are more interested in
+# extreme cases.
+#
+# This test takes rather long time so let us run it only in --big-test mode
+--source include/big_test.inc
+# We are using some debug-only features in this test
+--source include/have_debug.inc
+# Some of tests below also use binlog to check that statements are
+# executed and logged in correct order
+--source include/have_binlog_format_mixed_or_statement.inc
+
+# Create auxilliary connections
+connect (addconroot1, localhost, root,,);
+connect (addconroot2, localhost, root,,);
+connect (addconroot3, localhost, root,,);
+connection default;
+
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5;
+--enable_warnings
+
+
+#
+# Tests for concurrency problems in CREATE TABLE ... SELECT
+#
+# We introduce delays between various stages of table creation
+# and check that other statements dealing with this table cannot
+# interfere during those delays.
+#
+# What happens in situation when other statement messes with
+# table to be created before it is created ?
+# Concurrent CREATE TABLE
+set session debug="+d,sleep_create_select_before_create";
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+create table t1 (j char(5));
+connection default;
+--reap
+show create table t1;
+drop table t1;
+# Concurrent CREATE TABLE ... SELECT
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+create table t1 select "Test" as j;
+connection default;
+--reap
+show create table t1;
+drop table t1;
+# Concurrent CREATE TABLE LIKE
+create table t3 (j char(5));
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+create table t1 like t3;
+connection default;
+--reap
+show create table t1;
+drop table t1;
+# Concurrent RENAME TABLE
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+rename table t3 to t1;
+connection default;
+--reap
+show create table t1;
+drop table t1;
+# Concurrent ALTER TABLE RENAME
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+alter table t3 rename to t1;
+connection default;
+--reap
+show create table t1;
+drop table t1;
+# Concurrent ALTER TABLE RENAME which also adds column
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+--error ER_TABLE_EXISTS_ERROR
+alter table t3 rename to t1, add k int;
+connection default;
+--reap
+show create table t1;
+drop table t1, t3;
+# What happens if other statement sneaks in after the table
+# creation but before its opening ?
+set session debug="-d,sleep_create_select_before_create:+d,sleep_create_select_before_open";
+# Concurrent DROP TABLE
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+# Concurrent RENAME TABLE
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+rename table t1 to t2;
+connection default;
+--reap
+drop table t2;
+# Concurrent SELECT
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+select * from t1;
+connection default;
+--reap
+drop table t1;
+# Concurrent INSERT
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+insert into t1 values (2);
+connection default;
+--reap
+select * from t1;
+drop table t1;
+# Concurrent CREATE TRIGGER
+set @a:=0;
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+create trigger t1_bi before insert on t1 for each row set @a:=1;
+connection default;
+--reap
+select @a;
+drop table t1;
+# Okay, now the same tests for the potential gap between open and lock
+set session debug="-d,sleep_create_select_before_open:+d,sleep_create_select_before_lock";
+# Concurrent DROP TABLE
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+# Concurrent RENAME TABLE
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+rename table t1 to t2;
+connection default;
+--reap
+drop table t2;
+# Concurrent SELECT
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+select * from t1;
+connection default;
+--reap
+drop table t1;
+# Concurrent INSERT
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+insert into t1 values (2);
+connection default;
+--reap
+select * from t1;
+drop table t1;
+# Concurrent CREATE TRIGGER
+set @a:=0;
+--send create table t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+create trigger t1_bi before insert on t1 for each row set @a:=1;
+connection default;
+--reap
+select @a;
+drop table t1;
+# Some tests for case with existing table
+set session debug="-d,sleep_create_select_before_lock:+d,sleep_create_select_before_check_if_exists";
+create table t1 (i int);
+# Concurrent DROP TABLE
+--send create table if not exists t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+# Concurrent CREATE TRIGGER
+create table t1 (i int);
+set @a:=0;
+--send create table if not exists t1 select 1 as i;
+connection addconroot1;
+--sleep 2
+create trigger t1_bi before insert on t1 for each row set @a:=1;
+connection default;
+--reap
+select @a;
+select * from t1;
+drop table t1;
+set session debug="-d,sleep_create_select_before_check_if_exists";
+
+
+# Test for some details of CREATE TABLE ... SELECT implementation.
+#
+# We check that create placeholder is handled properly if we have
+# to reopen tables in open_tables().
+# This test heavily relies on current implementation of name-locking/
+# table cache so it may stop working if it changes. OTOH it such problem
+# will serve as warning that such changes should not be done lightly.
+create table t2 (a int);
+create table t4 (b int);
+connection addconroot2;
+lock table t4 write;
+select 1;
+connection addconroot1;
+# Create placeholder/name-lock for t3
+--send create table t3 as select * from t4;
+--sleep 2
+connection default;
+# This statement creates placeholder for t1, then opens t2,
+# then meets name-lock for t3 and then reopens all tables
+--send create table t1 select * from t2, t3;
+--sleep 2
+connection addconroot2;
+unlock tables;
+connection addconroot1;
+--reap
+connection default;
+--reap
+select * from t1;
+show create table t1;
+drop table t1, t3;
+# Now similar test which proves that we really temporarily
+# remove placeholder when we reopen tables.
+connection addconroot2;
+lock table t4 read;
+select 1;
+connection addconroot1;
+# Create name-lock for t3
+--send rename table t4 to t3;
+--sleep 2
+connection default;
+# This statement creates placeholder for t1, then opens t2,
+# then meets name-lock for t3 and then reopens all tables
+--send create table if not exists t1 select 1 as i from t2, t3;
+--sleep 2
+connection addconroot3;
+# We should be able to take name-lock on table t1 as we should not have
+# open placeholder for it at this point (otherwise it is possible to
+# come-up with situation which will lead to deadlock, e.g. think of
+# concurrent CREATE TABLE t1 SELECT * FROM t2 and RENAME TABLE t2 TO t1)
+create table t5 (j int);
+# This statement takes name-lock on t1 and therefore proves
+# that there is no active open placeholder for it.
+rename table t5 to t1;
+connection addconroot2;
+unlock tables;
+connection addconroot1;
+--reap
+connection default;
+--reap
+select * from t1;
+show create table t1;
+drop table t1, t2, t3;
+
+
+# Tests for possible concurrency issues with CREATE TABLE ... LIKE
+#
+# Bug #18950 "create table like does not obtain LOCK_open"
+# Bug #23667 "CREATE TABLE LIKE is not isolated from alteration by other
+# connections"
+#
+# Again the idea of this test is that we introduce artificial delays on
+# various stages of table creation and check that concurrent statements
+# for tables from CREATE TABLE ... LIKE are not interfering.
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+# What happens if some statements sneak in right after we have
+# opened source table ?
+create table t1 (i int);
+set session debug="+d,sleep_create_like_before_check_if_exists";
+# Reset binlog to have clear start
+reset master;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+# DML on source table should be allowed to run concurrently
+insert into t1 values (1);
+# And DDL should wait
+drop table t1;
+connection default;
+--reap
+show create table t2;
+drop table t2;
+# Let us check that statements were executed/binlogged in correct order
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000001' from 106;
+
+# Now let us check the gap between check for target table
+# existance and copying of .frm file.
+create table t1 (i int);
+set session debug="-d,sleep_create_like_before_check_if_exists:+d,sleep_create_like_before_copy";
+# It should be impossible to create target table concurrently
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+create table if not exists t2 (j int);
+connection default;
+--reap
+show create table t2;
+drop table t2;
+# And concurrent DDL on the source table should be still disallowed
+reset master;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+drop table t2;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000001' from 106;
+
+# And now he gap between copying of .frm file and ha_create_table() call.
+create table t1 (i int);
+set session debug="-d,sleep_create_like_before_copy:+d,sleep_create_like_before_ha_create";
+# Both DML and DDL on target table should wait till operation completes
+reset master;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+insert into t2 values (1);
+connection default;
+--reap
+drop table t2;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+drop table t2;
+connection default;
+--reap
+# Concurrent DDL on the source table still waits
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+drop table t2;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000001' from 106;
+
+# Finally we check the gap between ha_create_table() and binlogging
+create table t1 (i int);
+set session debug="-d,sleep_create_like_before_ha_create:+d,sleep_create_like_before_binlogging";
+reset master;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+insert into t2 values (1);
+connection default;
+--reap
+drop table t2;
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+drop table t2;
+connection default;
+--reap
+--send create table t2 like t1;
+connection addconroot1;
+--sleep 2
+drop table t1;
+connection default;
+--reap
+drop table t2;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000001' from 106;
+
+set session debug="-d,sleep_create_like_before_binlogging";