diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-10-30 11:15:30 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-10-30 11:15:30 +0200 |
commit | 898521e2dd8a4a6706cba01b6ef0a7cea4114fd0 (patch) | |
tree | 4ef9a6ddc4298574bb75db673c2412f83c107c5b /storage/innobase/dict | |
parent | 571bcf9aaaf59b84e24bbfb809738dea25495d78 (diff) | |
parent | 199863d72b7cccaa4c75641c50c45a83b568ab8c (diff) | |
download | mariadb-git-898521e2dd8a4a6706cba01b6ef0a7cea4114fd0.tar.gz |
Merge 10.4 into 10.5
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 6 | ||||
-rw-r--r-- | storage/innobase/dict/dict0mem.cc | 38 | ||||
-rw-r--r-- | storage/innobase/dict/dict0stats.cc | 210 |
3 files changed, 150 insertions, 104 deletions
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index a4a660be584..ca4081e90e9 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1992,6 +1992,12 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep) #ifdef BTR_CUR_HASH_ADAPT if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) { + if (table->fts) { + fts_optimize_remove_table(table); + fts_free(table); + table->fts = NULL; + } + table->vc_templ = NULL; table->id = 0; return; diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index c27ea57e68d..96f2d7b6e3b 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -124,25 +124,17 @@ bool dict_col_t::same_encoding(uint16_t a, uint16_t b) return false; } -/** Creates a table memory object. -@param[in] name table name -@param[in] space tablespace -@param[in] n_cols total number of columns including virtual and - non-virtual columns -@param[in] n_v_cols number of virtual columns -@param[in] flags table flags -@param[in] flags2 table flags2 -@param[in] init_stats_latch whether to init the stats latch +/** Create a table memory object. +@param name table name +@param space tablespace +@param n_cols total number of columns (both virtual and non-virtual) +@param n_v_cols number of virtual columns +@param flags table flags +@param flags2 table flags2 @return own: table object */ -dict_table_t* -dict_mem_table_create( - const char* name, - fil_space_t* space, - ulint n_cols, - ulint n_v_cols, - ulint flags, - ulint flags2, - bool init_stats_latch) +dict_table_t *dict_mem_table_create(const char *name, fil_space_t *space, + ulint n_cols, ulint n_v_cols, ulint flags, + ulint flags2) { dict_table_t* table; mem_heap_t* heap; @@ -210,12 +202,6 @@ dict_mem_table_create( new(&table->foreign_set) dict_foreign_set(); new(&table->referenced_set) dict_foreign_set(); - if (init_stats_latch) { - rw_lock_create(dict_table_stats_key, &table->stats_latch, - SYNC_INDEX_TREE); - table->stats_latch_inited = true; - } - return(table); } @@ -258,10 +244,6 @@ dict_mem_table_free( UT_DELETE(table->s_cols); - if (table->stats_latch_inited) { - rw_lock_free(&table->stats_latch); - } - mem_heap_free(table->heap); } diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 03330664264..07d5230b3f7 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -483,8 +483,6 @@ dict_stats_table_clone_create( ut_d(t->magic_n = DICT_TABLE_MAGIC_N); - rw_lock_create(dict_table_stats_key, &t->stats_latch, SYNC_INDEX_TREE); - return(t); } @@ -497,7 +495,6 @@ dict_stats_table_clone_free( /*========================*/ dict_table_t* t) /*!< in: dummy table object to free */ { - rw_lock_free(&t->stats_latch); mem_heap_free(t->heap); } @@ -514,7 +511,7 @@ dict_stats_empty_index( { ut_ad(!(index->type & DICT_FTS)); ut_ad(!dict_index_is_ibuf(index)); - ut_ad(rw_lock_own(&index->table->stats_latch, RW_LOCK_X)); + ut_ad(mutex_own(&dict_sys.mutex)); ulint n_uniq = index->n_uniq; @@ -544,10 +541,9 @@ dict_stats_empty_table( bool empty_defrag_stats) /*!< in: whether to empty defrag stats */ { - /* Zero the stats members */ - - rw_lock_x_lock(&table->stats_latch); + mutex_enter(&dict_sys.mutex); + /* Zero the stats members */ table->stat_n_rows = 0; table->stat_clustered_index_size = 1; /* 1 page for each index, not counting the clustered */ @@ -571,8 +567,7 @@ dict_stats_empty_table( } table->stat_initialized = TRUE; - - rw_lock_x_unlock(&table->stats_latch); + mutex_exit(&dict_sys.mutex); } /*********************************************************************//** @@ -671,6 +666,8 @@ dict_stats_copy( to have the same statistics as if the table was empty */ { + ut_ad(mutex_own(&dict_sys.mutex)); + dst->stats_last_recalc = src->stats_last_recalc; dst->stat_n_rows = src->stat_n_rows; dst->stat_clustered_index_size = src->stat_clustered_index_size; @@ -788,8 +785,6 @@ dict_stats_snapshot_create( { mutex_enter(&dict_sys.mutex); - rw_lock_s_lock(&table->stats_latch); - dict_stats_assert_initialized(table); dict_table_t* t; @@ -803,8 +798,6 @@ dict_stats_snapshot_create( t->stats_sample_pages = table->stats_sample_pages; t->stats_bg_flag = table->stats_bg_flag; - rw_lock_s_unlock(&table->stats_latch); - mutex_exit(&dict_sys.mutex); return(t); @@ -844,10 +837,14 @@ dict_stats_update_transient_for_index( Initialize some bogus index cardinality statistics, so that the data can be queried in various means, also via secondary indexes. */ + mutex_enter(&dict_sys.mutex); dict_stats_empty_index(index, false); + mutex_exit(&dict_sys.mutex); #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG } else if (ibuf_debug && !dict_index_is_clust(index)) { + mutex_enter(&dict_sys.mutex); dict_stats_empty_index(index, false); + mutex_exit(&dict_sys.mutex); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ } else { mtr_t mtr; @@ -868,7 +865,9 @@ dict_stats_update_transient_for_index( switch (size) { case ULINT_UNDEFINED: + mutex_enter(&dict_sys.mutex); dict_stats_empty_index(index, false); + mutex_exit(&dict_sys.mutex); return; case 0: /* The root node of the tree is a leaf */ @@ -880,11 +879,23 @@ dict_stats_update_transient_for_index( /* Do not continue if table decryption has failed or table is already marked as corrupted. */ if (index->is_readable()) { - /* We don't handle the return value since it - will be false only when some thread is - dropping the table and we don't have to empty - the statistics of the to be dropped index */ - btr_estimate_number_of_different_key_vals(index); + std::vector<index_field_stats_t> stats + = btr_estimate_number_of_different_key_vals( + index); + + if (!stats.empty()) { + ut_ad(!mutex_own(&dict_sys.mutex)); + mutex_enter(&dict_sys.mutex); + for (size_t i = 0; i < stats.size(); ++i) { + index->stat_n_diff_key_vals[i] + = stats[i].n_diff_key_vals; + index->stat_n_sample_sizes[i] + = stats[i].n_sample_sizes; + index->stat_n_non_null_key_vals[i] + = stats[i].n_non_null_key_vals; + } + mutex_exit(&dict_sys.mutex); + } } } } @@ -901,6 +912,8 @@ dict_stats_update_transient( /*========================*/ dict_table_t* table) /*!< in/out: table */ { + ut_ad(!mutex_own(&dict_sys.mutex)); + dict_index_t* index; ulint sum_of_index_sizes = 0; @@ -926,27 +939,25 @@ dict_stats_update_transient( ut_ad(!dict_index_is_ibuf(index)); - if (index->type & DICT_FTS || dict_index_is_spatial(index)) { + if (index->type & (DICT_FTS | DICT_SPATIAL)) { continue; } - dict_stats_empty_index(index, false); - - if (dict_stats_should_ignore_index(index)) { + if (dict_stats_should_ignore_index(index) + || !index->is_readable()) { + mutex_enter(&dict_sys.mutex); + dict_stats_empty_index(index, false); + mutex_exit(&dict_sys.mutex); continue; } - /* Do not continue if table decryption has failed or - table is already marked as corrupted. */ - if (!index->is_readable()) { - break; - } - dict_stats_update_transient_for_index(index); sum_of_index_sizes += index->stat_index_size; } + mutex_enter(&dict_sys.mutex); + index = dict_table_get_first_index(table); table->stat_n_rows = index->stat_n_diff_key_vals[ @@ -962,6 +973,8 @@ dict_stats_update_transient( table->stat_modified_counter = 0; table->stat_initialized = TRUE; + + mutex_exit(&dict_sys.mutex); } /* @{ Pseudo code about the relation between the following functions @@ -1807,16 +1820,31 @@ dict_stats_analyze_index_for_n_prefix( btr_pcur_close(&pcur); } +/** statistics for an index */ +struct index_stats_t +{ + std::vector<index_field_stats_t> stats; + ulint index_size; + ulint n_leaf_pages; + + index_stats_t(ulint n_uniq) : index_size(1), n_leaf_pages(1) + { + stats.reserve(n_uniq); + for (ulint i= 0; i < n_uniq; ++i) + stats.push_back(index_field_stats_t(0, 1, 0)); + } +}; + /** Set dict_index_t::stat_n_diff_key_vals[] and stat_n_sample_sizes[]. @param[in] n_diff_data input data to use to derive the results -@param[in,out] index index whose stat_n_diff_key_vals[] to set */ +@param[in,out] index_stats index stats to set */ UNIV_INLINE void dict_stats_index_set_n_diff( const n_diff_data_t* n_diff_data, - dict_index_t* index) + index_stats_t& index_stats) { - for (ulint n_prefix = dict_index_get_n_unique(index); + for (ulint n_prefix = index_stats.stats.size(); n_prefix >= 1; n_prefix--) { /* n_diff_all_analyzed_pages can be 0 here if @@ -1847,14 +1875,14 @@ dict_stats_index_set_n_diff( that the total number of ordinary leaf pages is T * D / (D + E). */ n_ordinary_leaf_pages - = index->stat_n_leaf_pages + = index_stats.n_leaf_pages * data->n_leaf_pages_to_analyze / (data->n_leaf_pages_to_analyze + data->n_external_pages_sum); } /* See REF01 for an explanation of the algorithm */ - index->stat_n_diff_key_vals[n_prefix - 1] + index_stats.stats[n_prefix - 1].n_diff_key_vals = n_ordinary_leaf_pages * data->n_diff_on_level @@ -1863,7 +1891,7 @@ dict_stats_index_set_n_diff( * data->n_diff_all_analyzed_pages / data->n_leaf_pages_to_analyze; - index->stat_n_sample_sizes[n_prefix - 1] + index_stats.stats[n_prefix - 1].n_sample_sizes = data->n_leaf_pages_to_analyze; DEBUG_PRINTF(" %s(): n_diff=" UINT64PF @@ -1872,9 +1900,9 @@ dict_stats_index_set_n_diff( " * " UINT64PF " / " UINT64PF " * " UINT64PF " / " UINT64PF ")\n", __func__, - index->stat_n_diff_key_vals[n_prefix - 1], + index_stats.stats[n_prefix - 1].n_diff_key_vals, n_prefix, - index->stat_n_leaf_pages, + index_stats.n_leaf_pages, data->n_diff_on_level, data->n_recs_on_level, data->n_diff_all_analyzed_pages, @@ -1882,15 +1910,12 @@ dict_stats_index_set_n_diff( } } -/*********************************************************************//** -Calculates new statistics for a given index and saves them to the index +/** Calculates new statistics for a given index and saves them to the index members stat_n_diff_key_vals[], stat_n_sample_sizes[], stat_index_size and -stat_n_leaf_pages. This function could be slow. */ -static -void -dict_stats_analyze_index( -/*=====================*/ - dict_index_t* index) /*!< in/out: index to analyze */ +stat_n_leaf_pages. This function can be slow. +@param[in] index index to analyze +@return index stats */ +static index_stats_t dict_stats_analyze_index(dict_index_t* index) { ulint root_level; ulint level; @@ -1901,26 +1926,28 @@ dict_stats_analyze_index( ib_uint64_t total_pages; mtr_t mtr; ulint size; + index_stats_t result(index->n_uniq); DBUG_ENTER("dict_stats_analyze_index"); DBUG_PRINT("info", ("index: %s, online status: %d", index->name(), dict_index_get_online_status(index))); + ut_ad(!mutex_own(&dict_sys.mutex)); // because this function is slow + ut_ad(index->table->get_ref_count()); + /* Disable update statistic for Rtree */ if (dict_index_is_spatial(index)) { - DBUG_VOID_RETURN; + DBUG_RETURN(result); } DEBUG_PRINTF(" %s(index=%s)\n", __func__, index->name()); - dict_stats_empty_index(index, false); - mtr.start(); mtr_s_lock_index(index, &mtr); size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr); if (size != ULINT_UNDEFINED) { - index->stat_index_size = size; + result.index_size = size; size = btr_get_size(index, BTR_N_LEAF_PAGES, &mtr); } @@ -1930,13 +1957,13 @@ dict_stats_analyze_index( switch (size) { case ULINT_UNDEFINED: dict_stats_assert_initialized_index(index); - DBUG_VOID_RETURN; + DBUG_RETURN(result); case 0: /* The root node of the tree is a leaf */ size = 1; } - index->stat_n_leaf_pages = size; + result.n_leaf_pages = size; mtr.start(); mtr_sx_lock_index(index, &mtr); @@ -1975,14 +2002,18 @@ dict_stats_analyze_index( NULL /* boundaries not needed */, &mtr); + mtr.commit(); + + mutex_enter(&dict_sys.mutex); for (ulint i = 0; i < n_uniq; i++) { - index->stat_n_sample_sizes[i] = total_pages; + result.stats[i].n_diff_key_vals = index->stat_n_diff_key_vals[i]; + result.stats[i].n_sample_sizes = total_pages; + result.stats[i].n_non_null_key_vals = index->stat_n_non_null_key_vals[i]; } + result.n_leaf_pages = index->stat_n_leaf_pages; + mutex_exit(&dict_sys.mutex); - mtr.commit(); - - dict_stats_assert_initialized_index(index); - DBUG_VOID_RETURN; + DBUG_RETURN(result); } /* For each level that is being scanned in the btree, this contains the @@ -2174,13 +2205,12 @@ found_level: /* n_prefix == 0 means that the above loop did not end up prematurely due to tree being changed and so n_diff_data[] is set up. */ if (n_prefix == 0) { - dict_stats_index_set_n_diff(n_diff_data, index); + dict_stats_index_set_n_diff(n_diff_data, result); } UT_DELETE_ARRAY(n_diff_data); - dict_stats_assert_initialized_index(index); - DBUG_VOID_RETURN; + DBUG_RETURN(result); } /*********************************************************************//** @@ -2198,7 +2228,7 @@ dict_stats_update_persistent( DEBUG_PRINTF("%s(table=%s)\n", __func__, table->name); - rw_lock_x_lock(&table->stats_latch); + DEBUG_SYNC_C("dict_stats_update_persistent"); /* analyze the clustered index first */ @@ -2209,15 +2239,26 @@ dict_stats_update_persistent( || (index->type | DICT_UNIQUE) != (DICT_CLUSTERED | DICT_UNIQUE)) { /* Table definition is corrupt */ - rw_lock_x_unlock(&table->stats_latch); dict_stats_empty_table(table, true); return(DB_CORRUPTION); } ut_ad(!dict_index_is_ibuf(index)); + mutex_enter(&dict_sys.mutex); + dict_stats_empty_index(index, false); + mutex_exit(&dict_sys.mutex); - dict_stats_analyze_index(index); + index_stats_t stats = dict_stats_analyze_index(index); + + mutex_enter(&dict_sys.mutex); + index->stat_index_size = stats.index_size; + index->stat_n_leaf_pages = stats.n_leaf_pages; + for (size_t i = 0; i < stats.stats.size(); ++i) { + index->stat_n_diff_key_vals[i] = stats.stats[i].n_diff_key_vals; + index->stat_n_sample_sizes[i] = stats.stats[i].n_sample_sizes; + index->stat_n_non_null_key_vals[i] = stats.stats[i].n_non_null_key_vals; + } ulint n_unique = dict_index_get_n_unique(index); @@ -2235,7 +2276,7 @@ dict_stats_update_persistent( ut_ad(!dict_index_is_ibuf(index)); - if (index->type & DICT_FTS || dict_index_is_spatial(index)) { + if (index->type & (DICT_FTS | DICT_SPATIAL)) { continue; } @@ -2246,7 +2287,20 @@ dict_stats_update_persistent( } if (!(table->stats_bg_flag & BG_STAT_SHOULD_QUIT)) { - dict_stats_analyze_index(index); + mutex_exit(&dict_sys.mutex); + stats = dict_stats_analyze_index(index); + mutex_enter(&dict_sys.mutex); + + index->stat_index_size = stats.index_size; + index->stat_n_leaf_pages = stats.n_leaf_pages; + for (size_t i = 0; i < stats.stats.size(); ++i) { + index->stat_n_diff_key_vals[i] + = stats.stats[i].n_diff_key_vals; + index->stat_n_sample_sizes[i] + = stats.stats[i].n_sample_sizes; + index->stat_n_non_null_key_vals[i] + = stats.stats[i].n_non_null_key_vals; + } } table->stat_sum_of_other_index_sizes @@ -2261,7 +2315,7 @@ dict_stats_update_persistent( dict_stats_assert_initialized(table); - rw_lock_x_unlock(&table->stats_latch); + mutex_exit(&dict_sys.mutex); return(DB_SUCCESS); } @@ -3078,11 +3132,22 @@ dict_stats_update_for_index( if (dict_stats_is_persistent_enabled(index->table)) { if (dict_stats_persistent_storage_check(false)) { - rw_lock_x_lock(&index->table->stats_latch); - dict_stats_analyze_index(index); + index_stats_t stats = dict_stats_analyze_index(index); + mutex_enter(&dict_sys.mutex); + index->stat_index_size = stats.index_size; + index->stat_n_leaf_pages = stats.n_leaf_pages; + for (size_t i = 0; i < stats.stats.size(); ++i) { + index->stat_n_diff_key_vals[i] + = stats.stats[i].n_diff_key_vals; + index->stat_n_sample_sizes[i] + = stats.stats[i].n_sample_sizes; + index->stat_n_non_null_key_vals[i] + = stats.stats[i].n_non_null_key_vals; + } index->table->stat_sum_of_other_index_sizes += index->stat_index_size; - rw_lock_x_unlock(&index->table->stats_latch); + mutex_exit(&dict_sys.mutex); + dict_stats_save(index->table, &index->id); DBUG_VOID_RETURN; } @@ -3103,9 +3168,7 @@ dict_stats_update_for_index( } } - rw_lock_x_lock(&index->table->stats_latch); dict_stats_update_transient_for_index(index); - rw_lock_x_unlock(&index->table->stats_latch); DBUG_VOID_RETURN; } @@ -3259,7 +3322,7 @@ dict_stats_update( switch (err) { case DB_SUCCESS: - rw_lock_x_lock(&table->stats_latch); + mutex_enter(&dict_sys.mutex); /* Pass reset_ignored_indexes=true as parameter to dict_stats_copy. This will cause statictics @@ -3268,7 +3331,7 @@ dict_stats_update( dict_stats_assert_initialized(table); - rw_lock_x_unlock(&table->stats_latch); + mutex_exit(&dict_sys.mutex); dict_stats_table_clone_free(t); @@ -3322,13 +3385,8 @@ dict_stats_update( } transient: - - rw_lock_x_lock(&table->stats_latch); - dict_stats_update_transient(table); - rw_lock_x_unlock(&table->stats_latch); - return(DB_SUCCESS); } |