Skip to content

Commit ca89489

Browse files
committed
MDEV-26383 fixup: Consistently protect freed_indexes with autoinc_mutex
To avoid potential race conditions between concurrent access to dict_table_t::freed_indexes, let us consistently use dict_table_t::autoinc_mutex. dict_table_remove_from_cache_low(): To avoid extensive hold time of table->autoinc_mutex, unconditionally free the FTS data structures.
1 parent 08e5a3d commit ca89489

File tree

3 files changed

+25
-23
lines changed

3 files changed

+25
-23
lines changed

storage/innobase/btr/btr0sea.cc

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,7 @@ ATTRIBUTE_COLD static void btr_search_lazy_free(dict_index_t *index)
253253
{
254254
ut_ad(index->freed());
255255
dict_table_t *table= index->table;
256-
bool non_exist_table= (table->id == 0);
257-
258-
if (non_exist_table)
259-
{
260-
/* autoinc_mutex should be acquired to avoid the race condition
261-
in case of multiple threads accessing the evicted table
262-
or dropped table. */
263-
mysql_mutex_lock(&table->autoinc_mutex);
264-
}
256+
mysql_mutex_lock(&table->autoinc_mutex);
265257

266258
/* Perform the skipped steps of dict_index_remove_from_cache_low(). */
267259
UT_LIST_REMOVE(table->freed_indexes, index);
@@ -271,15 +263,14 @@ ATTRIBUTE_COLD static void btr_search_lazy_free(dict_index_t *index)
271263
if (!UT_LIST_GET_LEN(table->freed_indexes) &&
272264
!UT_LIST_GET_LEN(table->indexes))
273265
{
274-
ut_ad(non_exist_table);
266+
ut_ad(!table->id);
275267
mysql_mutex_unlock(&table->autoinc_mutex);
276268
mysql_mutex_destroy(&table->autoinc_mutex);
277269
dict_mem_table_free(table);
278270
return;
279271
}
280272

281-
if (non_exist_table)
282-
mysql_mutex_unlock(&table->autoinc_mutex);
273+
mysql_mutex_unlock(&table->autoinc_mutex);
283274
}
284275

285276
/** Clear the adaptive hash index on all pages in the buffer pool. */

storage/innobase/dict/dict0dict.cc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2012, Facebook Inc.
5-
Copyright (c) 2013, 2020, MariaDB Corporation.
5+
Copyright (c) 2013, 2021, MariaDB Corporation.
66
77
This program is free software; you can redistribute it and/or modify it under
88
the terms of the GNU General Public License as published by the Free Software
@@ -1258,6 +1258,7 @@ dict_index_t *dict_index_t::clone_if_needed()
12581258
return this;
12591259
dict_index_t *prev= UT_LIST_GET_PREV(indexes, this);
12601260

1261+
mysql_mutex_lock(&table->autoinc_mutex);
12611262
UT_LIST_REMOVE(table->indexes, this);
12621263
UT_LIST_ADD_LAST(table->freed_indexes, this);
12631264
dict_index_t *index= clone();
@@ -1266,6 +1267,7 @@ dict_index_t *dict_index_t::clone_if_needed()
12661267
UT_LIST_INSERT_AFTER(table->indexes, prev, index);
12671268
else
12681269
UT_LIST_ADD_FIRST(table->indexes, index);
1270+
mysql_mutex_unlock(&table->autoinc_mutex);
12691271
return index;
12701272
}
12711273
#endif /* BTR_CUR_HASH_ADAPT */
@@ -1961,15 +1963,21 @@ dict_table_remove_from_cache_low(
19611963
}
19621964

19631965
#ifdef BTR_CUR_HASH_ADAPT
1964-
if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) {
1965-
if (table->fts) {
1966-
fts_optimize_remove_table(table);
1967-
fts_free(table);
1968-
table->fts = NULL;
1969-
}
1966+
if (table->fts) {
1967+
fts_optimize_remove_table(table);
1968+
fts_free(table);
1969+
table->fts = NULL;
1970+
}
1971+
1972+
mysql_mutex_lock(&table->autoinc_mutex);
1973+
1974+
ulint freed = UT_LIST_GET_LEN(table->freed_indexes);
1975+
1976+
table->vc_templ = NULL;
1977+
table->id = 0;
1978+
mysql_mutex_unlock(&table->autoinc_mutex);
19701979

1971-
table->vc_templ = NULL;
1972-
table->id = 0;
1980+
if (UNIV_UNLIKELY(freed != 0)) {
19731981
return;
19741982
}
19751983
#endif /* BTR_CUR_HASH_ADAPT */
@@ -2244,8 +2252,10 @@ dict_index_remove_from_cache_low(
22442252
zero. See also: dict_table_can_be_evicted() */
22452253

22462254
if (index->n_ahi_pages()) {
2255+
mysql_mutex_lock(&table->autoinc_mutex);
22472256
index->set_freed();
22482257
UT_LIST_ADD_LAST(table->freed_indexes, index);
2258+
mysql_mutex_unlock(&table->autoinc_mutex);
22492259
return;
22502260
}
22512261
#endif /* BTR_CUR_HASH_ADAPT */

storage/innobase/include/dict0mem.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,8 @@ struct dict_table_t {
17131713
UT_LIST_BASE_NODE_T(dict_index_t) indexes;
17141714
#ifdef BTR_CUR_HASH_ADAPT
17151715
/** List of detached indexes that are waiting to be freed along with
1716-
the last adaptive hash index entry */
1716+
the last adaptive hash index entry.
1717+
Protected by autoinc_mutex (sic!) */
17171718
UT_LIST_BASE_NODE_T(dict_index_t) freed_indexes;
17181719
#endif /* BTR_CUR_HASH_ADAPT */
17191720

@@ -1880,7 +1881,7 @@ struct dict_table_t {
18801881
from a select. */
18811882
lock_t* autoinc_lock;
18821883

1883-
/** Mutex protecting the autoincrement counter. */
1884+
/** Mutex protecting the autoinc counter and freed_indexes. */
18841885
mysql_mutex_t autoinc_mutex;
18851886

18861887
/** Autoinc counter value to give to the next inserted row. */

0 commit comments

Comments
 (0)