mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug #18806829 OPENING INNODB TABLES WITH MANY FOREIGN KEY REFERENCES IS
SLOW/CRASHES SEMAPHORE Problem: There are 2 lakh tables - fk_000001, fk_000002 ... fk_200000. All of them are related to the same parent_table through a foreign key constraint. When the parent_table is loaded into the dictionary cache, all the child table will also be loaded. This is taking lot of time. Since this operation happens when the dictionary latch is taken, the scenario leads to "long semaphore wait" situation and the server gets killed. Analysis: A simple performance analysis showed that the slowness is because of the dict_foreign_find() function. It does a linear search on two linked list table->foreign_list and table->referenced_list, looking for a particular foreign key object based on foreign->id as the key. This is called two times for each foreign key object. Solution: Introduce a rb tree in table->foreign_rbt and table->referenced_rbt, which are some sort of index on table->foreign_list and table->referenced_list respectively, using foreign->id as the key. These rbt structures will be solely used by dict_foreign_find(). rb#5599 approved by Vasil
This commit is contained in:
35
mysql-test/suite/innodb/r/innodb-fk.result
Normal file
35
mysql-test/suite/innodb/r/innodb-fk.result
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Bug #18806829 OPENING INNODB TABLES WITH MANY FOREIGN KEY
|
||||
# REFERENCES IS SLOW/CRASHES SEMAPHORE
|
||||
#
|
||||
create table t1 (f1 int primary key) engine=innodb;
|
||||
insert into t1 values (5);
|
||||
insert into t1 values (2882);
|
||||
insert into t1 values (10);
|
||||
update t1 set f1 = 28 where f1 = 2882;
|
||||
select * from fk_120;
|
||||
f1
|
||||
5
|
||||
10
|
||||
28
|
||||
select * from fk_1;
|
||||
f1
|
||||
5
|
||||
10
|
||||
28
|
||||
select * from fk_50;
|
||||
f1
|
||||
5
|
||||
10
|
||||
28
|
||||
drop table t1;
|
||||
#
|
||||
# Check if restrict is working fine.
|
||||
#
|
||||
create table t1 (f1 int primary key) engine=innodb;
|
||||
delete from t1 where f1 = 29;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`fk_29`, CONSTRAINT `pc29` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`))
|
||||
select * from fk_29;
|
||||
f1
|
||||
29
|
||||
drop table t1;
|
86
mysql-test/suite/innodb/t/innodb-fk.test
Normal file
86
mysql-test/suite/innodb/t/innodb-fk.test
Normal file
@ -0,0 +1,86 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # Bug #18806829 OPENING INNODB TABLES WITH MANY FOREIGN KEY
|
||||
--echo # REFERENCES IS SLOW/CRASHES SEMAPHORE
|
||||
--echo #
|
||||
|
||||
create table t1 (f1 int primary key) engine=innodb;
|
||||
insert into t1 values (5);
|
||||
insert into t1 values (2882);
|
||||
insert into t1 values (10);
|
||||
|
||||
let $fk_tables = 120;
|
||||
|
||||
--disable_query_log
|
||||
let $i = $fk_tables;
|
||||
while ($i)
|
||||
{
|
||||
eval create table fk_$i (f1 int primary key,
|
||||
constraint pc$i foreign key (f1) references t1(f1)
|
||||
on delete cascade on update cascade);
|
||||
eval insert into fk_$i values (5);
|
||||
eval insert into fk_$i values (2882);
|
||||
eval insert into fk_$i values (10);
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
update t1 set f1 = 28 where f1 = 2882;
|
||||
|
||||
select * from fk_120;
|
||||
select * from fk_1;
|
||||
select * from fk_50;
|
||||
|
||||
--disable_query_log
|
||||
let $i = $fk_tables;
|
||||
while ($i)
|
||||
{
|
||||
eval drop table fk_$i;
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # Check if restrict is working fine.
|
||||
--echo #
|
||||
|
||||
create table t1 (f1 int primary key) engine=innodb;
|
||||
|
||||
let $fk_tables = 30;
|
||||
|
||||
--disable_query_log
|
||||
let $i = $fk_tables;
|
||||
while ($i)
|
||||
{
|
||||
eval create table fk_$i (f1 int primary key,
|
||||
constraint pc$i foreign key (f1) references t1(f1)
|
||||
on delete restrict on update restrict);
|
||||
eval insert into t1 values ($i);
|
||||
eval insert into fk_$i values ($i);
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
delete from t1 where f1 = 29;
|
||||
select * from fk_29;
|
||||
|
||||
--disable_query_log
|
||||
let $i = $fk_tables;
|
||||
while ($i)
|
||||
{
|
||||
eval drop table fk_$i;
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
drop table t1;
|
||||
|
Reference in New Issue
Block a user