summaryrefslogtreecommitdiffstats
path: root/storage/innobase/dict
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0boot.cc5
-rw-r--r--storage/innobase/dict/dict0crea.cc3
-rw-r--r--storage/innobase/dict/dict0dict.cc22
-rw-r--r--storage/innobase/dict/dict0load.cc82
-rw-r--r--storage/innobase/dict/dict0stats.cc11
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc52
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;
}