diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:39:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:39:13 +0000 |
commit | 86fbb58c3ac0865482819c10a3e81f2eea001c36 (patch) | |
tree | 28c9e526ea739c6f9b89e36115e1e2698bddf981 /storage/innobase/dict | |
parent | Releasing progress-linux version 1:10.11.6-2~progress7.99u1. (diff) | |
download | mariadb-86fbb58c3ac0865482819c10a3e81f2eea001c36.tar.xz mariadb-86fbb58c3ac0865482819c10a3e81f2eea001c36.zip |
Merging upstream version 1:10.11.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r-- | storage/innobase/dict/dict0boot.cc | 5 | ||||
-rw-r--r-- | storage/innobase/dict/dict0crea.cc | 3 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 22 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.cc | 82 | ||||
-rw-r--r-- | storage/innobase/dict/dict0stats.cc | 11 | ||||
-rw-r--r-- | storage/innobase/dict/dict0stats_bg.cc | 52 |
6 files changed, 96 insertions, 79 deletions
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 5516bce9..cb60d813 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -42,7 +42,10 @@ static constexpr page_id_t hdr_page_id{DICT_HDR_SPACE, DICT_HDR_PAGE_NO}; static buf_block_t *dict_hdr_get(mtr_t *mtr) { /* We assume that the DICT_HDR page is always readable and available. */ - return buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, nullptr, BUF_GET, mtr); + buf_block_t *b= + buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, nullptr, BUF_GET, mtr); + buf_page_make_young_if_needed(&b->page); + return b; } /**********************************************************************//** diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index cce5f2f2..dd858287 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -353,9 +353,6 @@ dict_build_table_def_step( /* Always set this bit for all new created tables */ DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME); - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - DICT_TF2_FLAG_UNSET(table, - DICT_TF2_FTS_AUX_HEX_NAME);); if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_FILE_PER_TABLE)) { /* This table will need a new tablespace. */ diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 5bc7ab6e..5d3cab17 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2809,8 +2809,7 @@ dict_foreign_find_index( for (dict_index_t* index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { - if (types_idx != index - && !index->to_be_dropped + if (!index->to_be_dropped && !dict_index_is_online_ddl(index) && dict_foreign_qualify_index( table, col_names, columns, n_cols, @@ -3530,6 +3529,7 @@ dict_foreign_parse_drop_constraints( const char* ptr1; const char* id; CHARSET_INFO* cs; + bool if_exists = false; ut_a(trx->mysql_thd); @@ -3583,6 +3583,7 @@ loop: ptr1 = dict_accept(cs, ptr1, "EXISTS", &success); if (success) { ptr = ptr1; + if_exists = true; } } @@ -3593,14 +3594,14 @@ loop: goto syntax_error; } - ut_a(*n < 1000); - (*constraints_to_drop)[*n] = id; - (*n)++; - if (std::find_if(table->foreign_set.begin(), - table->foreign_set.end(), - dict_foreign_matches_id(id)) - == table->foreign_set.end()) { + table->foreign_set.end(), + dict_foreign_matches_id(id)) + == table->foreign_set.end()) { + + if (if_exists) { + goto loop; + } if (!srv_read_only_mode) { FILE* ef = dict_foreign_err_file; @@ -3622,6 +3623,9 @@ loop: return(DB_CANNOT_DROP_CONSTRAINT); } + ut_a(*n < 1000); + (*constraints_to_drop)[*n] = id; + (*n)++; goto loop; syntax_error: diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index f769839d..e7735586 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -33,8 +33,8 @@ Created 4/24/1996 Heikki Tuuri #include "dict0boot.h" #include "dict0crea.h" #include "dict0dict.h" -#include "dict0mem.h" #include "dict0stats.h" +#include "ibuf0ibuf.h" #include "fsp0file.h" #include "fts0priv.h" #include "mach0data.h" @@ -865,18 +865,30 @@ err_exit: return READ_OK; } -/** Check each tablespace found in the data dictionary. -Then look at each table defined in SYS_TABLES that has a space_id > 0 -to find all the file-per-table tablespaces. +/** @return SELECT MAX(space) FROM sys_tables */ +static uint32_t dict_find_max_space_id(btr_pcur_t *pcur, mtr_t *mtr) +{ + uint32_t max_space_id= 0; -In a crash recovery we already have some tablespace objects created from -processing the REDO log. We will compare the -space_id information in the data dictionary to what we find in the -tablespace file. In addition, more validation will be done if recovery -was needed and force_recovery is not set. + for (const rec_t *rec= dict_startscan_system(pcur, mtr, dict_sys.sys_tables); + rec; rec= dict_getnext_system_low(pcur, mtr)) + if (!dict_sys_tables_rec_check(rec)) + { + ulint len; + const byte *field= + rec_get_nth_field_old(rec, DICT_FLD__SYS_TABLES__SPACE, &len); + ut_ad(len == 4); + max_space_id= std::max(max_space_id, mach_read_from_4(field)); + } + + return max_space_id; +} -We also scan the biggest space id, and store it to fil_system. */ -void dict_check_tablespaces_and_store_max_id() +/** Check MAX(SPACE) FROM SYS_TABLES and store it in fil_system. +Open each data file if an encryption plugin has been loaded. + +@param spaces set of tablespace files to open */ +void dict_check_tablespaces_and_store_max_id(const std::set<uint32_t> *spaces) { uint32_t max_space_id = 0; btr_pcur_t pcur; @@ -888,6 +900,12 @@ void dict_check_tablespaces_and_store_max_id() dict_sys.lock(SRW_LOCK_CALL); + if (!spaces && ibuf.empty + && !encryption_key_id_exists(FIL_DEFAULT_ENCRYPTION_KEY)) { + max_space_id = dict_find_max_space_id(&pcur, &mtr); + goto done; + } + for (const rec_t *rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_tables); rec; rec = dict_getnext_system_low(&pcur, &mtr)) { @@ -919,14 +937,6 @@ void dict_check_tablespaces_and_store_max_id() continue; } - if (flags2 & DICT_TF2_DISCARDED) { - sql_print_information("InnoDB: Ignoring tablespace" - " for %.*s because " - "the DISCARD flag is set", - static_cast<int>(len), field); - continue; - } - /* For tables or partitions using .ibd files, the flag DICT_TF2_USE_FILE_PER_TABLE was not set in MIX_LEN before MySQL 5.6.5. The flag should not have been @@ -939,6 +949,19 @@ void dict_check_tablespaces_and_store_max_id() continue; } + if (spaces && spaces->find(uint32_t(space_id)) + == spaces->end()) { + continue; + } + + if (flags2 & DICT_TF2_DISCARDED) { + sql_print_information("InnoDB: Ignoring tablespace" + " for %.*s because " + "the DISCARD flag is set", + static_cast<int>(len), field); + continue; + } + const span<const char> name{field, len}; char* filepath = fil_make_filepath(nullptr, name, @@ -971,6 +994,7 @@ void dict_check_tablespaces_and_store_max_id() ut_free(filepath); } +done: mtr.commit(); fil_set_max_space_id_if_bigger(max_space_id); @@ -2246,22 +2270,10 @@ dict_load_tablespace( /* The tablespace may already be open. */ table->space = fil_space_for_table_exists_in_mem(table->space_id, table->flags); - if (table->space) { + if (table->space || table->file_unreadable) { return; } - if (ignore_err >= DICT_ERR_IGNORE_TABLESPACE) { - table->file_unreadable = true; - return; - } - - if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) { - ib::error() << "Failed to find tablespace for table " - << table->name << " in the cache. Attempting" - " to load the tablespace with space id " - << table->space_id; - } - /* Use the remote filepath if needed. This parameter is optional in the call to fil_ibd_open(). If not supplied, it will be built from the table->name. */ @@ -2284,6 +2296,12 @@ dict_load_tablespace( if (!table->space) { /* We failed to find a sensible tablespace file */ table->file_unreadable = true; + + if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) { + sql_print_error("InnoDB: Failed to load tablespace " + ULINTPF " for table %s", + table->space_id, table->name); + } } ut_free(filepath); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 40969335..f11187b9 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -752,16 +752,9 @@ dict_stats_empty_index( } } -/*********************************************************************//** -Write all zeros (or 1 where it makes sense) into a table and its indexes' -statistics members. The resulting stats correspond to an empty table. */ -static -void -dict_stats_empty_table( -/*===================*/ - dict_table_t* table, /*!< in/out: table */ +void dict_stats_empty_table( + dict_table_t* table, bool empty_defrag_stats) - /*!< in: whether to empty defrag stats */ { /* Initialize table/index level stats is now protected by table level lock_mutex.*/ diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index a66aac22..b0c34dc6 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -69,6 +69,8 @@ static recalc_pool_t recalc_pool; /** Whether the global data structures have been initialized */ static bool stats_initialised; +static THD *dict_stats_thd; + /*****************************************************************//** Free the resources occupied by the recalc pool, called once during thread de-initialization. */ @@ -90,6 +92,9 @@ static void dict_stats_recalc_pool_deinit() defrag_pool_t defrag_empty_pool; recalc_pool.swap(recalc_empty_pool); defrag_pool.swap(defrag_empty_pool); + + if (dict_stats_thd) + destroy_background_thd(dict_stats_thd); } /*****************************************************************//** @@ -361,52 +366,50 @@ done: { ut_ad(i->state == recalc::IN_PROGRESS); recalc_pool.erase(i); - const bool reschedule= !update_now && recalc_pool.empty(); if (err == DB_SUCCESS_LOCKED_REC) recalc_pool.emplace_back(recalc{table_id, recalc::IDLE}); mysql_mutex_unlock(&recalc_pool_mutex); - if (reschedule) - dict_stats_schedule(MIN_RECALC_INTERVAL * 1000); } return update_now; } -static tpool::timer* dict_stats_timer; -static std::mutex dict_stats_mutex; +/** Check if the recalc pool is empty. */ +static bool is_recalc_pool_empty() +{ + mysql_mutex_lock(&recalc_pool_mutex); + bool empty= recalc_pool.empty(); + mysql_mutex_unlock(&recalc_pool_mutex); + return empty; +} +static tpool::timer* dict_stats_timer; static void dict_stats_func(void*) { - THD *thd= innobase_create_background_thd("InnoDB statistics"); - set_current_thd(thd); - while (dict_stats_process_entry_from_recalc_pool(thd)) {} - dict_defrag_process_entries_from_defrag_pool(thd); + if (!dict_stats_thd) + dict_stats_thd= innobase_create_background_thd("InnoDB statistics"); + set_current_thd(dict_stats_thd); + + while (dict_stats_process_entry_from_recalc_pool(dict_stats_thd)) {} + dict_defrag_process_entries_from_defrag_pool(dict_stats_thd); + + innobase_reset_background_thd(dict_stats_thd); set_current_thd(nullptr); - destroy_background_thd(thd); + if (!is_recalc_pool_empty()) + dict_stats_schedule(MIN_RECALC_INTERVAL * 1000); } void dict_stats_start() { - std::lock_guard<std::mutex> lk(dict_stats_mutex); - if (!dict_stats_timer) - dict_stats_timer= srv_thread_pool->create_timer(dict_stats_func); + DBUG_ASSERT(!dict_stats_timer); + dict_stats_timer= srv_thread_pool->create_timer(dict_stats_func); } static void dict_stats_schedule(int ms) { - std::unique_lock<std::mutex> lk(dict_stats_mutex, std::defer_lock); - /* - Use try_lock() to avoid deadlock in dict_stats_shutdown(), which - uses dict_stats_mutex too. If there is simultaneous timer reschedule, - the first one will win, which is fine. - */ - if (!lk.try_lock()) - { - return; - } - if (dict_stats_timer) + if(dict_stats_timer) dict_stats_timer->set_time(ms,0); } @@ -418,7 +421,6 @@ void dict_stats_schedule_now() /** Shut down the dict_stats_thread. */ void dict_stats_shutdown() { - std::lock_guard<std::mutex> lk(dict_stats_mutex); delete dict_stats_timer; dict_stats_timer= 0; } |