diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2021-12-30 13:13:58 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2022-01-05 20:09:50 +0530 |
commit | e8d1bb045946a1c7b6e53c6b0bf468f9166db893 (patch) | |
tree | fcfe67130cf775c24e67e23820cbb327d56d3db5 | |
parent | 59e8a1265728498e73d186ce17ae9549358e8e95 (diff) | |
download | mariadb-git-bb-10.6-MDEV-27017.tar.gz |
MDEV-27017 Assertion failure 'table->get_ref_count() == 0' on DDL that involves FULLTEXT INDEXbb-10.6-MDEV-27017
purge_sys.stop_FTS() does not wait for purge operation
on FTS tables to finish. InnoDB DDL does purge_sys.stop_FTS()
and lock all fts tables. It eventually fails due to
n_ref_count value.
fts_stop_purge(): Stops the purge thread to process new FTS tables,
check n_ref_count of all fts index auxiliary, common tables.
This should make sure that consecutive fts_lock_tables()
is always successful.
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 60 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 6 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 14 | ||||
-rw-r--r-- | storage/innobase/include/trx0purge.h | 7 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 4 |
5 files changed, 74 insertions, 17 deletions
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 2a3a780228d..b7af3dab2c4 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2021, Oracle and/or its affiliates. -Copyright (c) 2016, 2021, MariaDB Corporation. +Copyright (c) 2016, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -23,9 +23,7 @@ Full Text Search interface ***********************************************************************/ #include "trx0roll.h" -#ifdef UNIV_DEBUG -# include "trx0purge.h" -#endif +#include "trx0purge.h" #include "row0mysql.h" #include "row0upd.h" #include "dict0types.h" @@ -1565,6 +1563,60 @@ dberr_t fts_lock_common_tables(trx_t *trx, const dict_table_t &table) return DB_SUCCESS; } +/** This function make sure that table doesn't +have any other reference count. +@param table_name table name */ +static void fts_table_no_ref_count(const char *table_name) +{ + dict_table_t *table= dict_table_open_on_name( + table_name, false, DICT_ERR_IGNORE_TABLESPACE); + if (!table) + return; + + while (table->get_ref_count() > 1) + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + table->release(); +} + +/** Stop the purge thread and check n_ref_count of all auxiliary +and common table associated with the fts table. +@param table parent FTS table */ +void purge_sys_t::stop_FTS(const dict_table_t &table) +{ + purge_sys.stop_FTS(); + fts_table_t fts_table; + char table_name[MAX_FULL_NAME_LEN]; + + FTS_INIT_FTS_TABLE(&fts_table, nullptr, FTS_COMMON_TABLE, (&table)); + + for (const char **suffix= fts_common_tables; *suffix; suffix++) + { + fts_table.suffix= *suffix; + fts_get_table_name(&fts_table, table_name, false); + fts_table_no_ref_count(table_name); + } + + if (!table.fts) + return; + auto indexes= table.fts->indexes; + if (!indexes) + return; + for (ulint i= 0;i < ib_vector_size(indexes); ++i) + { + const dict_index_t *index= static_cast<const dict_index_t*>( + ib_vector_getp(indexes, i)); + FTS_INIT_INDEX_TABLE(&fts_table, nullptr, FTS_INDEX_TABLE, index); + for (const fts_index_selector_t *s= fts_index_selector; + s->suffix; s++) + { + fts_table.suffix= s->suffix; + fts_get_table_name(&fts_table, table_name, false); + fts_table_no_ref_count(table_name); + } + } +} + /** Lock the internal FTS_ tables for table, before fts_drop_tables(). @param trx transaction @param table table containing FULLTEXT INDEX diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c850de7fec3..db8e910845a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -13457,7 +13457,7 @@ int ha_innobase::delete_table(const char *name) if (fts) { fts_optimize_remove_table(table); - purge_sys.stop_FTS(); + purge_sys.stop_FTS(*table); err= fts_lock_tables(trx, *table); } @@ -13835,7 +13835,7 @@ int ha_innobase::truncate() if (fts) { fts_optimize_remove_table(ib_table); - purge_sys.stop_FTS(); + purge_sys.stop_FTS(*ib_table); error = fts_lock_tables(trx, *ib_table); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 80385c1c3f8..6b3ca805872 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -6271,7 +6271,7 @@ acquire_lock: } if (fts_exist) { - purge_sys.stop_FTS(); + purge_sys.stop_FTS(*ctx->new_table); if (error == DB_SUCCESS) { error = fts_lock_tables(ctx->trx, *ctx->new_table); } @@ -8718,7 +8718,7 @@ inline bool rollback_inplace_alter_table(Alter_inplace_info *ha_alter_info, if (fts_exist) { fts_optimize_remove_table(ctx->new_table); - purge_sys.stop_FTS(); + purge_sys.stop_FTS(*ctx->new_table); } if (ctx->need_rebuild()) { @@ -10876,14 +10876,14 @@ ha_innobase::commit_inplace_alter_table( } } - if (fts_exist) { - purge_sys.stop_FTS(); - } - for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) { auto ctx = static_cast<ha_innobase_inplace_ctx*>(*pctx); dberr_t error = DB_SUCCESS; + if (fts_exist) { + purge_sys.stop_FTS(*ctx->old_table); + } + if (new_clustered && ctx->old_table->fts) { ut_ad(!ctx->old_table->fts->add_wq); fts_optimize_remove_table(ctx->old_table); diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 417c6688e83..dc032cdf73a 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +Copyright (c) 2017, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -283,6 +283,11 @@ public: trx_sys.clone_oldest_view(&view); latch.wr_unlock(); } + + /** Stop the purge thread and check n_ref_count of all auxiliary + and common table associated with the fts table. + @param table parent FTS table */ + void stop_FTS(const dict_table_t &table); }; /** The global data structure coordinating a purge */ diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 746d1a850b2..757ead4f0e9 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2484,7 +2484,7 @@ dberr_t row_discard_tablespace_for_mysql(dict_table_t *table, trx_t *trx) if (fts_exist) { fts_optimize_remove_table(table); - purge_sys.stop_FTS(); + purge_sys.stop_FTS(*table); err= fts_lock_tables(trx, *table); if (err != DB_SUCCESS) { |