mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 23:04:20 +01:00
4cafc8eeec
Bug #20662 "Infinite loop in CREATE TABLE IF NOT EXISTS ... SELECT with locked tables" Bug #20903 "Crash when using CREATE TABLE .. SELECT and triggers" Bug #24738 "CREATE TABLE ... SELECT is not isolated properly" Bug #24508 "Inconsistent results of CREATE TABLE ... SELECT when temporary table exists" Deadlock occured when one tried to execute CREATE TABLE IF NOT EXISTS ... SELECT statement under LOCK TABLES which held read lock on target table. Attempt to execute the same statement for already existing target table with triggers caused server crashes. Also concurrent execution of CREATE TABLE ... SELECT statement and other statements involving target table suffered from various races (some of which might've led to deadlocks). Finally, attempt to execute CREATE TABLE ... SELECT in case when a temporary table with same name was already present led to the insertion of data into this temporary table and creation of empty non-temporary table. All above problems stemmed from the old implementation of CREATE TABLE ... SELECT in which we created, opened and locked target table without any special protection in a separate step and not with the rest of tables used by this statement. This underminded deadlock-avoidance approach used in server and created window for races. It also excluded target table from prelocking causing problems with trigger execution. The patch solves these problems by implementing new approach to handling of CREATE TABLE ... SELECT for base tables. We try to open and lock table to be created at the same time as the rest of tables used by this statement. If such table does not exist at this moment we create and place in the table cache special placeholder for it which prevents its creation or any other usage by other threads. We still use old approach for creation of temporary tables. Note that we have separate fix for 5.0 since there we use slightly different less intrusive approach.
164 lines
3.9 KiB
Text
164 lines
3.9 KiB
Text
drop table if exists t1,t2,t3,t4,t5;
|
|
set session debug="+d,sleep_create_select_before_create";
|
|
create table t1 select 1 as i;;
|
|
create table t1 (j char(5));
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
create table t1 select "Test" as j;
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1;
|
|
create table t3 (j char(5));
|
|
create table t1 select 1 as i;;
|
|
create table t1 like t3;
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
rename table t3 to t1;
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
alter table t3 rename to t1;
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
alter table t3 rename to t1, add k int;
|
|
ERROR 42S01: Table 't1' already exists
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`i` int(1) NOT NULL DEFAULT '0'
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1, t3;
|
|
set session debug="-d,sleep_create_select_before_create:+d,sleep_create_select_before_open";
|
|
create table t1 select 1 as i;;
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
rename table t1 to t2;
|
|
drop table t2;
|
|
create table t1 select 1 as i;;
|
|
select * from t1;
|
|
i
|
|
1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
insert into t1 values (2);
|
|
select * from t1;
|
|
i
|
|
1
|
|
2
|
|
drop table t1;
|
|
set @a:=0;
|
|
create table t1 select 1 as i;;
|
|
create trigger t1_bi before insert on t1 for each row set @a:=1;
|
|
select @a;
|
|
@a
|
|
0
|
|
drop table t1;
|
|
set session debug="-d,sleep_create_select_before_open:+d,sleep_create_select_before_lock";
|
|
create table t1 select 1 as i;;
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
rename table t1 to t2;
|
|
drop table t2;
|
|
create table t1 select 1 as i;;
|
|
select * from t1;
|
|
i
|
|
1
|
|
drop table t1;
|
|
create table t1 select 1 as i;;
|
|
insert into t1 values (2);
|
|
select * from t1;
|
|
i
|
|
1
|
|
2
|
|
drop table t1;
|
|
set @a:=0;
|
|
create table t1 select 1 as i;;
|
|
create trigger t1_bi before insert on t1 for each row set @a:=1;
|
|
select @a;
|
|
@a
|
|
0
|
|
drop table t1;
|
|
set session debug="-d,sleep_create_select_before_lock:+d,sleep_create_select_before_check_if_exists";
|
|
create table t1 (i int);
|
|
create table if not exists t1 select 1 as i;;
|
|
drop table t1;
|
|
Warnings:
|
|
Note 1050 Table 't1' already exists
|
|
create table t1 (i int);
|
|
set @a:=0;
|
|
create table if not exists t1 select 1 as i;;
|
|
create trigger t1_bi before insert on t1 for each row set @a:=1;
|
|
Warnings:
|
|
Note 1050 Table 't1' already exists
|
|
select @a;
|
|
@a
|
|
0
|
|
select * from t1;
|
|
i
|
|
1
|
|
drop table t1;
|
|
set session debug="-d,sleep_create_select_before_check_if_exists";
|
|
create table t2 (a int);
|
|
create table t4 (b int);
|
|
lock table t4 write;
|
|
select 1;
|
|
1
|
|
1
|
|
create table t3 as select * from t4;;
|
|
create table t1 select * from t2, t3;;
|
|
unlock tables;
|
|
select * from t1;
|
|
a b
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`a` int(11) DEFAULT NULL,
|
|
`b` int(11) DEFAULT NULL
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1, t3;
|
|
lock table t4 read;
|
|
select 1;
|
|
1
|
|
1
|
|
rename table t4 to t3;;
|
|
create table if not exists t1 select 1 as i from t2, t3;;
|
|
create table t5 (j int);
|
|
rename table t5 to t1;
|
|
unlock tables;
|
|
Warnings:
|
|
Note 1050 Table 't1' already exists
|
|
select * from t1;
|
|
j
|
|
show create table t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`j` int(11) DEFAULT NULL
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
drop table t1, t2, t3;
|