Skip to content

Commit 58ebcbd

Browse files
AliSQLAliSQL
authored andcommitted
[Bugfix] Issue alibaba#45 Issue #577 InnoDB crash when master thread evict dict_table_t object
Problem ================ The innodb will crash when master thread wants to evict an unused object. The backtrace: ut_ad(dict_index_is_clust(index)) row_merge_drop_indexes dict_table_remove_from_cache_low dict_make_room_in_cache () srv_master_evict_from_table_cache () srv_master_do_idle_tasks () srv_master_thread (arg=0x0) start_thread (arg=0x2b21c8200700) clone () Solution ================ The wrong position of judgement logic code about variable 'drop_aborted' in function dict_table_close() may be the root cause. We simply move this piece of codes prior to the decrement of table->n_ref_count, thus aborted index will be discard when this table is being closed.
1 parent f3ae387 commit 58ebcbd

3 files changed

Lines changed: 91 additions & 6 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
set global table_definition_cache=400;
2+
set global table_open_cache= 1024;
3+
use test;
4+
create table t_bug(id int primary key, col1 int) engine=innodb;
5+
insert into t_bug values(1, 2);
6+
insert into t_bug values(2, 2);
7+
commit;
8+
alter table t_bug add unique key(col1);
9+
use test;
10+
select * from t_bug;
11+
id col1
12+
1 2
13+
2 2
14+
insert into t_bug values(3, 2);
15+
commit;
16+
ERROR 23000: Duplicate entry '2' for key 'col1'
17+
select sleep(10);
18+
sleep(10)
19+
0
20+
flush tables;
21+
sleep(10)
22+
0
23+
set global table_definition_cache = default;
24+
set global table_open_cache = default;
25+
drop table t_bug;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
connect(con1,localhost,root,,);
2+
connect(con2,localhost,root,,);
3+
4+
connection con1;
5+
set global table_definition_cache=400;
6+
set global table_open_cache= 1024;
7+
8+
use test;
9+
create table t_bug(id int primary key, col1 int) engine=innodb;
10+
insert into t_bug values(1, 2);
11+
insert into t_bug values(2, 2);
12+
commit;
13+
14+
# table->n_ref_count has increased
15+
--send
16+
alter table t_bug add unique key(col1);
17+
18+
connection con2;
19+
use test;
20+
select * from t_bug;
21+
22+
insert into t_bug values(3, 2);
23+
commit;
24+
25+
# So ALTER statement failed, left table->drop_abort=true;
26+
connection con1;
27+
--error 1062
28+
--reap
29+
30+
disconnect con2;
31+
32+
connection con1;
33+
select sleep(10);
34+
35+
# Flush tables, so t_bug table can be evicted by master thread.
36+
flush tables;
37+
38+
# Create 1000 tables, try the best to evict t_bug since table_def_size.
39+
--disable_query_log
40+
let $loop=1000;
41+
while($loop)
42+
{
43+
eval create table t_$loop(id int)engine=innodb;
44+
dec $loop;
45+
}
46+
47+
select sleep(10);
48+
49+
let $loop=1000;
50+
while($loop)
51+
{
52+
eval drop table t_$loop;
53+
dec $loop;
54+
}
55+
56+
--enable_query_log
57+
set global table_definition_cache = default;
58+
set global table_open_cache = default;
59+
drop table t_bug;
60+
61+
disconnect con1;

storage/innobase/dict/dict0dict.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -564,13 +564,18 @@ dict_table_close(
564564
indexes after an aborted online
565565
index creation */
566566
{
567+
ibool drop_aborted;
567568
if (!dict_locked) {
568569
mutex_enter(&dict_sys->mutex);
569570
}
570571

571572
ut_ad(mutex_own(&dict_sys->mutex));
572573
ut_a(table->n_ref_count > 0);
573574

575+
drop_aborted = try_drop
576+
&& table->drop_aborted
577+
&& table->n_ref_count == 1
578+
&& dict_table_get_first_index(table);
574579
--table->n_ref_count;
575580

576581
/* Force persistent stats re-read upon next open of the table
@@ -599,12 +604,6 @@ dict_table_close(
599604

600605
if (!dict_locked) {
601606
table_id_t table_id = table->id;
602-
ibool drop_aborted;
603-
604-
drop_aborted = try_drop
605-
&& table->drop_aborted
606-
&& table->n_ref_count == 1
607-
&& dict_table_get_first_index(table);
608607

609608
mutex_exit(&dict_sys->mutex);
610609

0 commit comments

Comments
 (0)