summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/CMakeLists.txt1
-rw-r--r--storage/innobase/btr/btr0btr.cc4
-rw-r--r--storage/innobase/btr/btr0bulk.cc4
-rw-r--r--storage/innobase/btr/btr0cur.cc84
-rw-r--r--storage/innobase/btr/btr0pcur.cc39
-rw-r--r--storage/innobase/buf/buf0block_hint.cc59
-rw-r--r--storage/innobase/buf/buf0buf.cc10
-rw-r--r--storage/innobase/dict/dict0dict.cc6
-rw-r--r--storage/innobase/dict/dict0mem.cc38
-rw-r--r--storage/innobase/dict/dict0stats.cc207
-rw-r--r--storage/innobase/fts/fts0ast.cc8
-rw-r--r--storage/innobase/fts/fts0que.cc31
-rw-r--r--storage/innobase/gis/gis0sea.cc25
-rw-r--r--storage/innobase/handler/ha_innodb.cc80
-rw-r--r--storage/innobase/handler/handler0alter.cc74
-rw-r--r--storage/innobase/handler/i_s.cc42
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc2
-rw-r--r--storage/innobase/include/btr0btr.h4
-rw-r--r--storage/innobase/include/btr0cur.h31
-rw-r--r--storage/innobase/include/btr0pcur.h11
-rw-r--r--storage/innobase/include/btr0sea.h2
-rw-r--r--storage/innobase/include/buf0block_hint.h76
-rw-r--r--storage/innobase/include/buf0buf.h27
-rw-r--r--storage/innobase/include/buf0buf.ic4
-rw-r--r--storage/innobase/include/dict0dict.h2
-rw-r--r--storage/innobase/include/dict0dict.ic2
-rw-r--r--storage/innobase/include/dict0mem.h38
-rw-r--r--storage/innobase/include/dict0stats.ic7
-rw-r--r--storage/innobase/include/sync0sync.h1
-rw-r--r--storage/innobase/include/trx0undo.h2
-rw-r--r--storage/innobase/row/row0mysql.cc7
-rw-r--r--storage/innobase/row/row0uins.cc2
-rw-r--r--storage/innobase/sync/sync0debug.cc3
-rw-r--r--storage/innobase/sync/sync0sync.cc1
-rw-r--r--storage/innobase/trx/trx0rec.cc3
-rw-r--r--storage/innobase/trx/trx0undo.cc9
36 files changed, 585 insertions, 361 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 10f183790a7..b7e7fb93bf3 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -29,6 +29,7 @@ SET(INNOBASE_SOURCES
btr/btr0pcur.cc
btr/btr0sea.cc
btr/btr0defragment.cc
+ buf/buf0block_hint.cc
buf/buf0buddy.cc
buf/buf0buf.cc
buf/buf0dblwr.cc
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index e7e70f76790..b2de0ad33b2 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -280,7 +280,7 @@ the index.
ulint
btr_height_get(
/*===========*/
- dict_index_t* index, /*!< in: index tree */
+ const dict_index_t* index, /*!< in: index tree */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint height=0;
@@ -582,7 +582,7 @@ Gets the number of pages in a B-tree.
ulint
btr_get_size(
/*=========*/
- dict_index_t* index, /*!< in: index */
+ const dict_index_t* index, /*!< in: index */
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
mtr_t* mtr) /*!< in/out: mini-transaction where index
is s-latched */
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index ee1bc20e1c9..6e8b88172e8 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -849,6 +849,8 @@ PageBulk::latch()
m_mtr.start();
m_index->set_modified(m_mtr);
+ ut_ad(m_block->page.buf_fix_count());
+
/* In case the block is S-latched by page_cleaner. */
if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock,
__FILE__, __LINE__, &m_mtr)) {
@@ -867,6 +869,8 @@ PageBulk::latch()
buf_block_buf_fix_dec(m_block);
+ ut_ad(m_block->page.buf_fix_count());
+
ut_ad(m_cur_rec > m_page && m_cur_rec < m_heap_top);
return (m_err);
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index fdb56e34d7e..846d8ecfd7e 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -770,6 +770,9 @@ btr_cur_optimistic_latch_leaves(
unsigned line,
mtr_t* mtr)
{
+ ut_ad(block->page.buf_fix_count());
+ ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
+
switch (*latch_mode) {
default:
ut_error;
@@ -780,16 +783,10 @@ btr_cur_optimistic_latch_leaves(
modify_clock, file, line, mtr));
case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV:
- if (block->page.state() != BUF_BLOCK_FILE_PAGE) {
- return(false);
- }
- /* pin the block not to be relocated */
- buf_block_buf_fix_inc(block, file, line);
-
rw_lock_s_lock(&block->lock);
if (block->modify_clock != modify_clock) {
rw_lock_s_unlock(&block->lock);
- break;
+ return false;
}
const uint32_t curr_page_no = block->page.id().page_no();
const uint32_t left_page_no = btr_page_get_prev(block->frame);
@@ -816,7 +813,7 @@ btr_cur_optimistic_latch_leaves(
/* release the left block */
btr_leaf_page_release(
cursor->left_block, mode, mtr);
- break;
+ return false;
}
} else {
cursor->left_block = NULL;
@@ -825,15 +822,22 @@ btr_cur_optimistic_latch_leaves(
if (buf_page_optimistic_get(mode, block, modify_clock,
file, line, mtr)) {
if (btr_page_get_prev(block->frame) == left_page_no) {
- buf_block_buf_fix_dec(block);
+ /* block was already buffer-fixed while
+ entering the function and
+ buf_page_optimistic_get() buffer-fixes
+ it again. */
+ ut_ad(2 <= block->page.buf_fix_count());
*latch_mode = mode;
return(true);
} else {
- /* release the block */
+ /* release the block and decrement of
+ buf_fix_count which was incremented
+ in buf_page_optimistic_get() */
btr_leaf_page_release(block, mode, mtr);
}
}
+ ut_ad(block->page.buf_fix_count());
/* release the left block */
if (cursor->left_block != NULL) {
btr_leaf_page_release(cursor->left_block,
@@ -841,8 +845,6 @@ btr_cur_optimistic_latch_leaves(
}
}
- /* unpin the block */
- buf_block_buf_fix_dec(block);
return false;
}
@@ -1397,12 +1399,7 @@ btr_cur_search_to_nth_level_func(
guess = NULL;
#else
info = btr_search_get_info(index);
-
- if (!buf_pool.is_obsolete(info->withdraw_clock)) {
- guess = info->root_guess;
- } else {
- guess = NULL;
- }
+ guess = info->root_guess;
#ifdef BTR_CUR_HASH_ADAPT
@@ -1836,10 +1833,7 @@ retry_page_get:
}
#ifdef BTR_CUR_ADAPT
- if (block != guess) {
- info->root_guess = block;
- info->withdraw_clock = buf_pool.withdraw_clock();
- }
+ info->root_guess = block;
#endif
}
@@ -6561,21 +6555,19 @@ btr_record_not_null_field_in_rec(
}
}
-/*******************************************************************//**
-Estimates the number of different key values in a given index, for
+/** Estimates the number of different key values in a given index, for
each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index).
The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed
0..n_uniq-1) and the number of pages that were sampled is saved in
-index->stat_n_sample_sizes[].
+result.n_sample_sizes[].
If innodb_stats_method is nulls_ignored, we also record the number of
non-null values for each prefix and stored the estimates in
-array index->stat_n_non_null_key_vals.
-@return true if the index is available and we get the estimated numbers,
-false if the index is unavailable. */
-bool
-btr_estimate_number_of_different_key_vals(
-/*======================================*/
- dict_index_t* index) /*!< in: index */
+array result.n_non_null_key_vals.
+@param[in] index index
+@return vector with statistics information
+empty vector if the index is unavailable. */
+std::vector<index_field_stats_t>
+btr_estimate_number_of_different_key_vals(dict_index_t* index)
{
btr_cur_t cursor;
page_t* page;
@@ -6595,11 +6587,11 @@ btr_estimate_number_of_different_key_vals(
rec_offs* offsets_rec = NULL;
rec_offs* offsets_next_rec = NULL;
+ std::vector<index_field_stats_t> result;
+
/* For spatial index, there is no such stats can be
fetched. */
- if (dict_index_is_spatial(index)) {
- return(false);
- }
+ ut_ad(!dict_index_is_spatial(index));
n_cols = dict_index_get_n_unique(index);
@@ -6709,7 +6701,7 @@ btr_estimate_number_of_different_key_vals(
mtr_commit(&mtr);
mem_heap_free(heap);
- return(false);
+ return result;
}
/* Count the number of different key values for each prefix of
@@ -6815,8 +6807,12 @@ exit_loop:
also the pages used for external storage of fields (those pages are
included in index->stat_n_leaf_pages) */
+ result.reserve(n_cols);
+
for (j = 0; j < n_cols; j++) {
- index->stat_n_diff_key_vals[j]
+ index_field_stats_t stat;
+
+ stat.n_diff_key_vals
= BTR_TABLE_STATS_FROM_SAMPLE(
n_diff[j], index, n_sample_pages,
total_external_size, not_empty_flag);
@@ -6837,25 +6833,23 @@ exit_loop:
add_on = n_sample_pages;
}
- index->stat_n_diff_key_vals[j] += add_on;
+ stat.n_diff_key_vals += add_on;
- index->stat_n_sample_sizes[j] = n_sample_pages;
+ stat.n_sample_sizes = n_sample_pages;
- /* Update the stat_n_non_null_key_vals[] with our
- sampled result. stat_n_non_null_key_vals[] is created
- and initialized to zero in dict_index_add_to_cache(),
- along with stat_n_diff_key_vals[] array */
if (n_not_null != NULL) {
- index->stat_n_non_null_key_vals[j] =
+ stat.n_non_null_key_vals =
BTR_TABLE_STATS_FROM_SAMPLE(
n_not_null[j], index, n_sample_pages,
total_external_size, not_empty_flag);
}
+
+ result.push_back(stat);
}
mem_heap_free(heap);
- return(true);
+ return result;
}
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index cc8c11c42e1..ad254976973 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -202,11 +202,10 @@ before_first:
cursor->old_n_fields,
&cursor->old_rec_buf,
&cursor->buf_size);
- cursor->block_when_stored = block;
+ cursor->block_when_stored.store(block);
/* Function try to check if block is S/X latch. */
cursor->modify_clock = buf_block_get_modify_clock(block);
- cursor->withdraw_clock = buf_pool.withdraw_clock();
}
/**************************************************************//**
@@ -236,6 +235,26 @@ btr_pcur_copy_stored_position(
pcur_receive->old_n_fields = pcur_donate->old_n_fields;
}
+/** Structure acts as functor to do the latching of leaf pages.
+It returns true if latching of leaf pages succeeded and false
+otherwise. */
+struct optimistic_latch_leaves
+{
+ btr_pcur_t *const cursor;
+ ulint *latch_mode;
+ mtr_t *const mtr;
+
+ optimistic_latch_leaves(btr_pcur_t *cursor, ulint *latch_mode, mtr_t *mtr)
+ :cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
+
+ bool operator() (buf_block_t *hint) const
+ {
+ return hint && btr_cur_optimistic_latch_leaves(
+ hint, cursor->modify_clock, latch_mode,
+ btr_pcur_get_btr_cur(cursor), __FILE__, __LINE__, mtr);
+ }
+};
+
/**************************************************************//**
Restores the stored position of a persistent cursor bufferfixing the page and
obtaining the specified latches. If the cursor position was saved when the
@@ -298,7 +317,7 @@ btr_pcur_restore_position_func(
cursor->latch_mode =
BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- cursor->block_when_stored = btr_pcur_get_block(cursor);
+ cursor->block_when_stored.clear();
return(FALSE);
}
@@ -313,12 +332,9 @@ btr_pcur_restore_position_func(
case BTR_MODIFY_PREV:
/* Try optimistic restoration. */
- if (!buf_pool.is_obsolete(cursor->withdraw_clock)
- && btr_cur_optimistic_latch_leaves(
- cursor->block_when_stored, cursor->modify_clock,
- &latch_mode, btr_pcur_get_btr_cur(cursor),
- file, line, mtr)) {
-
+ if (cursor->block_when_stored.run_with_hint(
+ optimistic_latch_leaves(cursor, &latch_mode,
+ mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->latch_mode = latch_mode;
@@ -416,11 +432,10 @@ btr_pcur_restore_position_func(
since the cursor can now be on a different page!
But we can retain the value of old_rec */
- cursor->block_when_stored = btr_pcur_get_block(cursor);
+ cursor->block_when_stored.store(btr_pcur_get_block(cursor));
cursor->modify_clock = buf_block_get_modify_clock(
- cursor->block_when_stored);
+ cursor->block_when_stored.block());
cursor->old_stored = true;
- cursor->withdraw_clock = buf_pool.withdraw_clock();
mem_heap_free(heap);
diff --git a/storage/innobase/buf/buf0block_hint.cc b/storage/innobase/buf/buf0block_hint.cc
new file mode 100644
index 00000000000..4d699004476
--- /dev/null
+++ b/storage/innobase/buf/buf0block_hint.cc
@@ -0,0 +1,59 @@
+/*****************************************************************************
+
+Copyright (c) 2020, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2020, MariaDB Corporation.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License, version 2.0, as published by the
+Free Software Foundation.
+
+This program is also distributed with certain software (including but not
+limited to OpenSSL) that is licensed under separate terms, as designated in a
+particular file or component or in included license documentation. The authors
+of MySQL hereby grant you an additional permission to link the program and
+your derivative works with the separately licensed software that they have
+included with MySQL.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
+for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*****************************************************************************/
+
+#include "buf0block_hint.h"
+namespace buf {
+
+void Block_hint::buffer_fix_block_if_still_valid()
+{
+ /* To check if m_block belongs to the current buf_pool, we must
+ prevent freeing memory while we check, and until we buffer-fix the
+ block. For this purpose it is enough to latch any of the many
+ latches taken by buf_pool_t::resize().
+
+ Similar to buf_page_optimistic_get(), we must validate
+ m_block->page.id() after acquiring the hash_lock, because the object
+ may have been freed and not actually attached to buf_pool.page_hash
+ at the moment. (The block could have been reused to store a
+ different page, and that slice of buf_pool.page_hash could be protected
+ by another hash_lock that we are not holding.)
+
+ Finally, assuming that we have correct hash bucket latched, we must
+ validate m_block->state() to ensure that the block is not being freed. */
+ if (m_block)
+ {
+ const ulint fold= m_page_id.fold();
+ page_hash_latch *hash_lock= buf_pool.page_hash.lock<false>(fold);
+ if (buf_pool.is_uncompressed(m_block) && m_page_id == m_block->page.id() &&
+ m_block->page.state() == BUF_BLOCK_FILE_PAGE)
+ m_block->fix();
+ else
+ clear();
+ hash_lock->read_unlock();
+ }
+}
+} // namespace buf
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 2cdd36a8b60..9a180614afd 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1479,8 +1479,6 @@ bool buf_pool_t::create()
NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE;
ut_ad(!resizing);
- ut_ad(!withdrawing);
- ut_ad(!withdraw_clock());
ut_ad(!chunks_old);
chunk_t::map_reg= UT_NEW_NOKEY(chunk_t::map());
@@ -1637,7 +1635,6 @@ inline bool buf_pool_t::realloc(buf_block_t *block)
{
buf_block_t* new_block;
- ut_ad(withdrawing);
mysql_mutex_assert_owner(&mutex);
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
@@ -1909,9 +1906,6 @@ inline bool buf_pool_t::withdraw_blocks()
ib::info() << "withdrawn target: " << UT_LIST_GET_LEN(withdraw)
<< " blocks";
- /* retry is not needed */
- ++withdraw_clock_;
-
return(false);
}
@@ -2105,7 +2099,6 @@ inline void buf_pool_t::resize()
ut_ad(withdraw_target == 0);
withdraw_target = w;
- withdrawing.store(true, std::memory_order_relaxed);
}
buf_resize_status("Withdrawing blocks to be shrunken.");
@@ -2121,7 +2114,6 @@ withdraw_retry:
if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
/* abort to resize for shutdown. */
- withdrawing.store(false, std::memory_order_relaxed);
return;
}
@@ -2162,8 +2154,6 @@ withdraw_retry:
goto withdraw_retry;
}
- withdrawing.store(false, std::memory_order_relaxed);
-
buf_resize_status("Latching whole of buffer pool.");
#ifndef DBUG_OFF
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..2d1cb86e51a 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,7 +2239,6 @@ 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);
@@ -2217,7 +2246,16 @@ dict_stats_update_persistent(
ut_ad(!dict_index_is_ibuf(index));
- 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 +2273,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 +2284,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 +2312,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 +3129,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 +3165,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 +3319,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 +3328,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 +3382,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);
}
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index a2834f5e7e5..bb42f7c9f54 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2020, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -557,8 +557,7 @@ fts_ast_node_check_union(
fts_ast_node_t* node)
{
if (node->type == FTS_AST_LIST
- || node->type == FTS_AST_SUBEXP_LIST
- || node->type == FTS_AST_PARSER_PHRASE_LIST) {
+ || node->type == FTS_AST_SUBEXP_LIST) {
for (node = node->list.head; node; node = node->next) {
if (!fts_ast_node_check_union(node)) {
@@ -566,6 +565,9 @@ fts_ast_node_check_union(
}
}
+ } else if (node->type == FTS_AST_PARSER_PHRASE_LIST) {
+ /* Phrase search for plugin parser */
+ return(false);
} else if (node->type == FTS_AST_OPER
&& (node->oper == FTS_IGNORE
|| node->oper == FTS_EXIST)) {
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index dd74aad4de7..8e2cb838e5a 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -4423,24 +4423,27 @@ fts_phrase_or_proximity_search(
if (k == ib_vector_size(query->match_array[j])) {
end_list = TRUE;
- if (match[j]->doc_id != match[0]->doc_id) {
- /* no match */
- if (query->flags & FTS_PHRASE) {
- ulint s;
+ if (query->flags & FTS_PHRASE) {
+ ulint s;
+ /* Since i is the last doc id in the
+ match_array[j], remove all doc ids > i
+ from the match_array[0]. */
+ fts_match_t* match_temp;
+ for (s = i + 1; s < n_matched; s++) {
+ match_temp = static_cast<
+ fts_match_t*>(ib_vector_get(
+ query->match_array[0], s));
+ match_temp->doc_id = 0;
+ }
+ if (match[j]->doc_id !=
+ match[0]->doc_id) {
+ /* no match */
match[0]->doc_id = 0;
-
- for (s = i + 1; s < n_matched;
- s++) {
- match[0] = static_cast<
- fts_match_t*>(
- ib_vector_get(
- query->match_array[0],
- s));
- match[0]->doc_id = 0;
- }
}
+ }
+ if (match[j]->doc_id != match[0]->doc_id) {
goto func_exit;
}
}
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index 0a0d4242c00..d9a0ae80c33 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -1237,6 +1237,24 @@ rtr_check_discard_page(
lock_mutex_exit();
}
+/** Structure acts as functor to get the optimistic access of the page.
+It returns true if it successfully gets the page. */
+struct optimistic_get
+{
+ btr_pcur_t *const r_cursor;
+ mtr_t *const mtr;
+
+ optimistic_get(btr_pcur_t *r_cursor,mtr_t *mtr)
+ :r_cursor(r_cursor), mtr(mtr) {}
+
+ bool operator()(buf_block_t *hint) const
+ {
+ return hint && buf_page_optimistic_get(
+ RW_X_LATCH, hint, r_cursor->modify_clock, __FILE__,
+ __LINE__, mtr);
+ }
+};
+
/** Restore the stored position of a persistent cursor bufferfixing the page */
static
bool
@@ -1270,11 +1288,8 @@ rtr_cur_restore_position(
ut_ad(latch_mode == BTR_CONT_MODIFY_TREE);
- if (!buf_pool.is_obsolete(r_cursor->withdraw_clock)
- && buf_page_optimistic_get(RW_X_LATCH,
- r_cursor->block_when_stored,
- r_cursor->modify_clock,
- __FILE__, __LINE__, mtr)) {
+ if (r_cursor->block_when_stored.run_with_hint(
+ optimistic_get(r_cursor, mtr))) {
ut_ad(r_cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(r_cursor->rel_pos == BTR_PCUR_ON);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index b636592bb87..c7e65abb0c7 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -223,6 +223,27 @@ enum default_row_format_enum {
DEFAULT_ROW_FORMAT_DYNAMIC = 2,
};
+/** A dummy variable */
+static uint innodb_max_purge_lag_wait;
+
+/** Wait for trx_sys_t::rseg_history_len to be below a limit. */
+static void innodb_max_purge_lag_wait_update(THD *thd, st_mysql_sys_var *,
+ void *, const void *limit)
+{
+ const uint l= *static_cast<const uint*>(limit);
+ if (trx_sys.rseg_history_len <= l)
+ return;
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+ while (trx_sys.rseg_history_len > l)
+ {
+ if (thd_kill_level(thd))
+ break;
+ srv_wake_purge_thread_if_not_active();
+ os_thread_sleep(100000);
+ }
+ mysql_mutex_lock(&LOCK_global_system_variables);
+}
+
static
void set_my_errno(int err)
{
@@ -567,7 +588,6 @@ static PSI_rwlock_info all_innodb_rwlocks[] = {
PSI_RWLOCK_KEY(trx_purge_latch),
PSI_RWLOCK_KEY(index_tree_rw_lock),
PSI_RWLOCK_KEY(index_online_log),
- PSI_RWLOCK_KEY(dict_table_stats)
};
# endif /* UNIV_PFS_RWLOCK */
@@ -14186,6 +14206,8 @@ ha_innobase::info_low(
DEBUG_SYNC_C("ha_innobase_info_low");
+ ut_ad(!mutex_own(&dict_sys.mutex));
+
/* If we are forcing recovery at a high level, we will suppress
statistics calculation on tables, because that may crash the
server if an index is badly corrupted. */
@@ -14222,7 +14244,6 @@ ha_innobase::info_low(
opt = DICT_STATS_RECALC_TRANSIENT;
}
- ut_ad(!mutex_own(&dict_sys.mutex));
ret = dict_stats_update(ib_table, opt);
if (ret != DB_SUCCESS) {
@@ -14238,14 +14259,14 @@ ha_innobase::info_low(
stats.update_time = (ulong) ib_table->update_time;
}
+ DBUG_EXECUTE_IF("dict_sys_mutex_avoid", goto func_exit;);
+
if (flag & HA_STATUS_VARIABLE) {
ulint stat_clustered_index_size;
ulint stat_sum_of_other_index_sizes;
- if (!(flag & HA_STATUS_NO_LOCK)) {
- rw_lock_s_lock(&ib_table->stats_latch);
- }
+ mutex_enter(&dict_sys.mutex);
ut_a(ib_table->stat_initialized);
@@ -14257,9 +14278,7 @@ ha_innobase::info_low(
stat_sum_of_other_index_sizes
= ib_table->stat_sum_of_other_index_sizes;
- if (!(flag & HA_STATUS_NO_LOCK)) {
- rw_lock_s_unlock(&ib_table->stats_latch);
- }
+ mutex_exit(&dict_sys.mutex);
/*
The MySQL optimizer seems to assume in a left join that n_rows
@@ -14360,10 +14379,26 @@ ha_innobase::info_low(
ib_push_frm_error(m_user_thd, ib_table, table, num_innodb_index, true);
}
- if (!(flag & HA_STATUS_NO_LOCK)) {
- rw_lock_s_lock(&ib_table->stats_latch);
+ snprintf(path, sizeof(path), "%s/%s%s",
+ mysql_data_home, table->s->normalized_path.str,
+ reg_ext);
+
+ unpack_filename(path,path);
+
+ /* Note that we do not know the access time of the table,
+ nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
+
+ if (os_file_get_status(
+ path, &stat_info, false,
+ srv_read_only_mode) == DB_SUCCESS) {
+ stats.create_time = (ulong) stat_info.ctime;
}
+ struct Locking {
+ Locking() { mutex_enter(&dict_sys.mutex); }
+ ~Locking() { mutex_exit(&dict_sys.mutex); }
+ } locking;
+
ut_a(ib_table->stat_initialized);
for (uint i = 0; i < table->s->keys; i++) {
@@ -14441,25 +14476,6 @@ ha_innobase::info_low(
key->rec_per_key[j] = rec_per_key_int;
}
}
-
- if (!(flag & HA_STATUS_NO_LOCK)) {
- rw_lock_s_unlock(&ib_table->stats_latch);
- }
-
- snprintf(path, sizeof(path), "%s/%s%s",
- mysql_data_home, table->s->normalized_path.str,
- reg_ext);
-
- unpack_filename(path,path);
-
- /* Note that we do not know the access time of the table,
- nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
-
- if (os_file_get_status(
- path, &stat_info, false,
- srv_read_only_mode) == DB_SUCCESS) {
- stats.create_time = (ulong) stat_info.ctime;
- }
}
if (srv_force_recovery > SRV_FORCE_NO_IBUF_MERGE) {
@@ -19111,6 +19127,11 @@ static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay,
0L, /* Minimum value */
10000000UL, 0); /* Maximum value */
+static MYSQL_SYSVAR_UINT(max_purge_lag_wait, innodb_max_purge_lag_wait,
+ PLUGIN_VAR_RQCMDARG,
+ "Wait until History list length is below the specified limit",
+ NULL, innodb_max_purge_lag_wait_update, UINT_MAX, 0, UINT_MAX, 0);
+
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
@@ -20049,6 +20070,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flushing_avg_loops),
MYSQL_SYSVAR(max_purge_lag),
MYSQL_SYSVAR(max_purge_lag_delay),
+ MYSQL_SYSVAR(max_purge_lag_wait),
MYSQL_SYSVAR(old_blocks_pct),
MYSQL_SYSVAR(old_blocks_time),
MYSQL_SYSVAR(open_files),
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 9343ca7fe45..7d20796b646 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -56,6 +56,8 @@ Smart ALTER TABLE
#include "ha_innodb.h"
#include "ut0stage.h"
#include "span.h"
+#include <thread>
+#include <sstream>
using st_::span;
/** File format constraint for ALTER TABLE */
@@ -556,6 +558,7 @@ inline bool dict_table_t::instant_column(const dict_table_t& table,
mem_heap_alloc(heap, table.n_v_cols * sizeof(*v_cols)));
for (ulint i = table.n_v_cols; i--; ) {
new (&v_cols[i]) dict_v_col_t(table.v_cols[i]);
+ v_cols[i].v_indexes.clear();
}
} else {
ut_ad(table.n_v_cols == 0);
@@ -7363,22 +7366,28 @@ innobase_rename_index_cache(dict_index_t* index, const char* new_name)
/** Rename the index name in cache.
@param[in] ctx alter context
@param[in] ha_alter_info Data used during inplace alter. */
-static void innobase_rename_indexes_cache(
- const ha_innobase_inplace_ctx* ctx,
- const Alter_inplace_info* ha_alter_info)
+static void
+innobase_rename_indexes_cache(const ha_innobase_inplace_ctx *ctx,
+ const Alter_inplace_info *ha_alter_info)
{
- DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
+ DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
- for (const Alter_inplace_info::Rename_key_pair& pair :
- ha_alter_info->rename_keys) {
- dict_index_t* index = dict_table_get_index_on_name(
- ctx->old_table, pair.old_key->name.str);
- ut_ad(index);
+ std::vector<std::pair<dict_index_t *, const char *>> rename_info;
+ rename_info.reserve(ha_alter_info->rename_keys.size());
- innobase_rename_index_cache(index, pair.new_key->name.str);
- }
-}
+ for (const Alter_inplace_info::Rename_key_pair &pair :
+ ha_alter_info->rename_keys)
+ {
+ dict_index_t *index=
+ dict_table_get_index_on_name(ctx->old_table, pair.old_key->name.str);
+ ut_ad(index);
+ rename_info.emplace_back(index, pair.new_key->name.str);
+ }
+
+ for (const auto &pair : rename_info)
+ innobase_rename_index_cache(pair.first, pair.second);
+}
/** Fill the stored column information in s_cols list.
@param[in] altered_table mysql table object
@@ -10535,11 +10544,18 @@ alter_stats_norebuild(
}
}
- for (const Alter_inplace_info::Rename_key_pair& pair :
- ha_alter_info->rename_keys) {
+ for (size_t i = 0; i < ha_alter_info->rename_keys.size(); i++) {
+ const Alter_inplace_info::Rename_key_pair& pair
+ = ha_alter_info->rename_keys[i];
+
+ std::stringstream ss;
+ ss << TEMP_FILE_PREFIX_INNODB << std::this_thread::get_id()
+ << i;
+ auto tmp_name = ss.str();
+
dberr_t err = dict_stats_rename_index(ctx->new_table,
pair.old_key->name.str,
- pair.new_key->name.str);
+ tmp_name.c_str());
if (err != DB_SUCCESS) {
push_warning_printf(
@@ -10551,6 +10567,34 @@ alter_stats_norebuild(
" statistics storage: %s",
ctx->new_table->name.m_name,
pair.old_key->name.str,
+ tmp_name.c_str(),
+ ut_strerr(err));
+ }
+ }
+
+ for (size_t i = 0; i < ha_alter_info->rename_keys.size(); i++) {
+ const Alter_inplace_info::Rename_key_pair& pair
+ = ha_alter_info->rename_keys[i];
+
+ std::stringstream ss;
+ ss << TEMP_FILE_PREFIX_INNODB << std::this_thread::get_id()
+ << i;
+ auto tmp_name = ss.str();
+
+ dberr_t err = dict_stats_rename_index(ctx->new_table,
+ tmp_name.c_str(),
+ pair.new_key->name.str);
+
+ if (err != DB_SUCCESS) {
+ push_warning_printf(
+ thd,
+ Sql_condition::WARN_LEVEL_WARN,
+ ER_ERROR_ON_RENAME,
+ "Error renaming an index of table '%s'"
+ " from '%s' to '%s' in InnoDB persistent"
+ " statistics storage: %s",
+ ctx->new_table->name.m_name,
+ tmp_name.c_str(),
pair.new_key->name.str,
ut_strerr(err));
}
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index b0dc115977e..ecc0905de56 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -5037,33 +5037,39 @@ i_s_dict_fill_sys_tablestats(
OK(field_store_string(fields[SYS_TABLESTATS_NAME],
table->name.m_name));
- rw_lock_s_lock(&table->stats_latch);
-
- OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized, true));
+ {
+ struct Locking
+ {
+ Locking() { mutex_enter(&dict_sys.mutex); }
+ ~Locking() { mutex_exit(&dict_sys.mutex); }
+ } locking;
- if (table->stat_initialized) {
- OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows,
+ OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized,
true));
- OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
- table->stat_clustered_index_size, true));
+ if (table->stat_initialized) {
+ OK(fields[SYS_TABLESTATS_NROW]->store(
+ table->stat_n_rows, true));
- OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
- table->stat_sum_of_other_index_sizes, true));
+ OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
+ table->stat_clustered_index_size, true));
- OK(fields[SYS_TABLESTATS_MODIFIED]->store(
- table->stat_modified_counter, true));
- } else {
- OK(fields[SYS_TABLESTATS_NROW]->store(0, true));
+ OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
+ table->stat_sum_of_other_index_sizes,
+ true));
- OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0, true));
+ OK(fields[SYS_TABLESTATS_MODIFIED]->store(
+ table->stat_modified_counter, true));
+ } else {
+ OK(fields[SYS_TABLESTATS_NROW]->store(0, true));
- OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0, true));
+ OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0, true));
- OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
- }
+ OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0, true));
- rw_lock_s_unlock(&table->stats_latch);
+ OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
+ }
+ }
OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, true));
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 5c9d7955c90..91a450b0711 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -1309,7 +1309,7 @@ ibuf_dummy_index_create(
dict_index_t* index;
table = dict_mem_table_create("IBUF_DUMMY", NULL, n, 0,
- comp ? DICT_TF_COMPACT : 0, 0, false);
+ comp ? DICT_TF_COMPACT : 0, 0);
index = dict_mem_index_create(table, "IBUF_DUMMY", 0, n);
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 317c63c97d8..7fae1ad163b 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -214,7 +214,7 @@ the index.
ulint
btr_height_get(
/*===========*/
- dict_index_t* index, /*!< in: index tree */
+ const dict_index_t* index, /*!< in: index tree */
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((warn_unused_result));
@@ -579,7 +579,7 @@ Gets the number of pages in a B-tree.
ulint
btr_get_size(
/*=========*/
- dict_index_t* index, /*!< in: index */
+ const dict_index_t* index, /*!< in: index */
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
mtr_t* mtr) /*!< in/out: mini-transaction where index
is s-latched */
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 838b49dad47..7136d726db0 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -590,8 +590,24 @@ btr_estimate_n_rows_in_range(
btr_pos_t* range_start,
btr_pos_t* range_end);
-/*******************************************************************//**
-Estimates the number of different key values in a given index, for
+
+/** Statistics for one field of an index. */
+struct index_field_stats_t
+{
+ ib_uint64_t n_diff_key_vals;
+ ib_uint64_t n_sample_sizes;
+ ib_uint64_t n_non_null_key_vals;
+
+ index_field_stats_t(ib_uint64_t n_diff_key_vals= 0,
+ ib_uint64_t n_sample_sizes= 0,
+ ib_uint64_t n_non_null_key_vals= 0)
+ : n_diff_key_vals(n_diff_key_vals), n_sample_sizes(n_sample_sizes),
+ n_non_null_key_vals(n_non_null_key_vals)
+ {
+ }
+};
+
+/** Estimates the number of different key values in a given index, for
each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index).
The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed
0..n_uniq-1) and the number of pages that were sampled is saved in
@@ -599,12 +615,11 @@ index->stat_n_sample_sizes[].
If innodb_stats_method is nulls_ignored, we also record the number of
non-null values for each prefix and stored the estimates in
array index->stat_n_non_null_key_vals.
-@return true if the index is available and we get the estimated numbers,
-false if the index is unavailable. */
-bool
-btr_estimate_number_of_different_key_vals(
-/*======================================*/
- dict_index_t* index); /*!< in: index */
+@param[in] index index
+@return stat vector if the index is available and we get the estimated numbers,
+empty vector if the index is unavailable. */
+std::vector<index_field_stats_t>
+btr_estimate_number_of_different_key_vals(dict_index_t* index);
/** Gets the externally stored size of a record, in units of a database page.
@param[in] rec record
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index bceb35a6969..bc7afbf3b67 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -29,6 +29,7 @@ Created 2/23/1996 Heikki Tuuri
#include "dict0dict.h"
#include "btr0cur.h"
+#include "buf0block_hint.h"
#include "btr0btr.h"
#include "gis0rtree.h"
@@ -502,13 +503,10 @@ struct btr_pcur_t{
whether cursor was on, before, or after the old_rec record */
enum btr_pcur_pos_t rel_pos;
/** buffer block when the position was stored */
- buf_block_t* block_when_stored;
+ buf::Block_hint block_when_stored;
/** the modify clock value of the buffer block when the cursor position
was stored */
ib_uint64_t modify_clock;
- /** the withdraw clock value of the buffer pool when the cursor
- position was stored */
- ulint withdraw_clock;
/** btr_pcur_store_position() and btr_pcur_restore_position() state. */
enum pcur_pos_t pos_state;
/** PAGE_CUR_G, ... */
@@ -529,9 +527,8 @@ struct btr_pcur_t{
btr_cur(), latch_mode(RW_NO_LATCH),
old_stored(false), old_rec(NULL),
old_n_fields(0), rel_pos(btr_pcur_pos_t(0)),
- block_when_stored(NULL),
- modify_clock(0), withdraw_clock(0),
- pos_state(BTR_PCUR_NOT_POSITIONED),
+ block_when_stored(),
+ modify_clock(0), pos_state(BTR_PCUR_NOT_POSITIONED),
search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL),
old_rec_buf(NULL), buf_size(0)
{
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index f09920b1816..f8f2050d3d3 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -192,8 +192,6 @@ struct btr_search_t{
the machine word, i.e., they cannot be turned into bit-fields. */
buf_block_t* root_guess;/*!< the root page frame when it was last time
fetched, or NULL */
- ulint withdraw_clock; /*!< the withdraw clock value of the buffer
- pool when root_guess was stored */
#ifdef BTR_CUR_HASH_ADAPT
ulint hash_analysis; /*!< when this exceeds
BTR_SEARCH_HASH_ANALYSIS, the hash
diff --git a/storage/innobase/include/buf0block_hint.h b/storage/innobase/include/buf0block_hint.h
new file mode 100644
index 00000000000..ee48e7ce6d2
--- /dev/null
+++ b/storage/innobase/include/buf0block_hint.h
@@ -0,0 +1,76 @@
+/*****************************************************************************
+
+Copyright (c) 2020, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2020, MariaDB Corporation.
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License, version 2.0, as published by the
+Free Software Foundation.
+
+This program is also distributed with certain software (including but not
+limited to OpenSSL) that is licensed under separate terms, as designated in a
+particular file or component or in included license documentation. The authors
+of MySQL hereby grant you an additional permission to link the program and
+your derivative works with the separately licensed software that they have
+included with MySQL.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
+for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*****************************************************************************/
+#pragma once
+#include "buf0buf.h"
+
+namespace buf {
+class Block_hint {
+public:
+ /** Stores the pointer to the block, which is currently buffer-fixed.
+ @param block a pointer to a buffer-fixed block to be stored */
+ inline void store(buf_block_t *block)
+ {
+ ut_ad(block->page.buf_fix_count());
+ m_block= block;
+ m_page_id= block->page.id();
+ }
+
+ /** Clears currently stored pointer. */
+ inline void clear() { m_block= nullptr; }
+
+ /** Invoke f on m_block(which may be null)
+ @param f The function to be executed. It will be passed the pointer.
+ If you wish to use the block pointer subsequently,
+ you need to ensure you buffer-fix it before returning from f.
+ @return the return value of f
+ */
+ template <typename F>
+ bool run_with_hint(const F &f)
+ {
+ buffer_fix_block_if_still_valid();
+ /* m_block could be changed during f() call, so we use local
+ variable to remember which block we need to unfix */
+ buf_block_t *block= m_block;
+ bool res= f(block);
+ if (block)
+ buf_block_buf_fix_dec(block);
+ return res;
+ }
+
+ buf_block_t *block() const { return m_block; }
+
+ private:
+ /** The block pointer stored by store(). */
+ buf_block_t *m_block= nullptr;
+ /** If m_block is non-null, the m_block->page.id at time it was stored. */
+ page_id_t m_page_id{0, 0};
+
+ /** A helper function which checks if m_block is not a dangling pointer and
+ still points to block with page with m_page_id and if so, buffer-fixes it,
+ otherwise clear()s it */
+ void buffer_fix_block_if_still_valid();
+};
+} // namespace buf
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index d8e152f1ffa..df52d6b572c 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1467,21 +1467,7 @@ public:
/** @return whether resize() is in progress */
bool resize_in_progress() const
{
- return UNIV_UNLIKELY(resizing.load(std::memory_order_relaxed) ||
- withdrawing.load(std::memory_order_relaxed));
- }
-
- /** @return the withdraw_clock */
- ulint withdraw_clock() const
- { return withdraw_clock_.load(std::memory_order_relaxed); }
-
- /** Verify the possibility that a stored page is not in buffer pool.
- @param withdraw_clock the withdraw clock of the page
- @return whether the page might be relocated */
- bool is_obsolete(ulint withdraw_clock) const
- {
- return UNIV_UNLIKELY(withdrawing.load(std::memory_order_relaxed) ||
- this->withdraw_clock() != withdraw_clock);
+ return UNIV_UNLIKELY(resizing.load(std::memory_order_relaxed));
}
/** @return the current size in blocks */
@@ -1594,9 +1580,7 @@ public:
@return whether block has been created by chunk_t::create() */
bool is_uncompressed(const buf_block_t *block) const
{
- /* The pointer should be aligned. */
- return !(size_t(block) % sizeof *block) &&
- is_block_field(reinterpret_cast<const void*>(block));
+ return is_block_field(reinterpret_cast<const void*>(block));
}
/** Get the page_hash latch for a page */
@@ -2091,13 +2075,6 @@ private:
/** whether resize() is in the critical path */
std::atomic<bool> resizing;
-
- /** whether withdrawing buffer pool pages might cause page relocation */
- std::atomic<bool> withdrawing;
-
- /** a counter that is incremented every time a pointer to a page may
- become obsolete */
- std::atomic<ulint> withdraw_clock_;
};
/** The InnoDB buffer pool */
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 3074489527f..4d8cef4c4b2 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -288,8 +288,6 @@ buf_block_buf_fix_dec(
/*==================*/
buf_block_t* block) /*!< in/out: block to bufferunfix */
{
- block->unfix();
-
#ifdef UNIV_DEBUG
/* No debug latch is acquired if block belongs to system temporary.
Debug latch is not of much help if access to block is single
@@ -298,6 +296,8 @@ buf_block_buf_fix_dec(
rw_lock_s_unlock(block->debug_latch);
}
#endif /* UNIV_DEBUG */
+
+ block->unfix();
}
/********************************************************************//**
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index b5319d51c9a..276252e625c 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1280,7 +1280,7 @@ UNIV_INLINE
rw_lock_t*
dict_index_get_lock(
/*================*/
- dict_index_t* index) /*!< in: index */
+ const dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/********************************************************************//**
Returns free space reserved for future updates of records. This is
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index 4a006471c37..eda639ba7c1 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -914,7 +914,7 @@ UNIV_INLINE
rw_lock_t*
dict_index_get_lock(
/*================*/
- dict_index_t* index) /*!< in: index */
+ const dict_index_t* index) /*!< in: index */
{
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 68eb417e531..1ad2517c8fb 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -298,19 +298,17 @@ parent table will fail, and user has to drop excessive foreign constraint
before proceeds. */
#define FK_MAX_CASCADE_DEL 15
-/** 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= true);
+ ulint flags2);
/****************************************************************/ /**
Free a table memory object. */
void
@@ -1118,7 +1116,7 @@ public:
when InnoDB was started up */
zip_pad_info_t zip_pad;/*!< Information about state of
compression failures and successes */
- rw_lock_t lock; /*!< read-write lock protecting the
+ mutable rw_lock_t lock; /*!< read-write lock protecting the
upper levels of the index tree */
/** Determine if the index has been committed to the
@@ -2137,22 +2135,8 @@ public:
/*!< set of foreign key constraints which refer to this table */
dict_foreign_set referenced_set;
- /** Statistics for query optimization. @{ */
-
- /** This latch protects:
- dict_table_t::stat_initialized,
- dict_table_t::stat_n_rows (*),
- dict_table_t::stat_clustered_index_size,
- dict_table_t::stat_sum_of_other_index_sizes,
- dict_table_t::stat_modified_counter (*),
- dict_table_t::indexes*::stat_n_diff_key_vals[],
- dict_table_t::indexes*::stat_index_size,
- dict_table_t::indexes*::stat_n_leaf_pages.
- (*) Those are not always protected for
- performance reasons. */
- rw_lock_t stats_latch;
-
- bool stats_latch_inited= false;
+ /** Statistics for query optimization. Mostly protected by
+ dict_sys.mutex. @{ */
/** TRUE if statistics have been calculated the first time after
database startup or table creation. */
diff --git a/storage/innobase/include/dict0stats.ic b/storage/innobase/include/dict0stats.ic
index 0b8c57a5eba..4972efe8961 100644
--- a/storage/innobase/include/dict0stats.ic
+++ b/storage/innobase/include/dict0stats.ic
@@ -75,7 +75,7 @@ dict_stats_is_persistent_enabled(const dict_table_t* table)
+ dict_stats_update(DICT_STATS_RECALC_TRANSIENT) on a table that has
just been PS-enabled.
This is acceptable. Avoiding this would mean that we would have to
- protect the ::stat_persistent with dict_table_t::stats_latch like the
+ protect the stat_persistent with dict_sys.mutex like the
other ::stat_ members which would be too big performance penalty,
especially when this function is called from
dict_stats_update_if_needed(). */
@@ -178,10 +178,7 @@ dict_stats_deinit(
ut_a(table->get_ref_count() == 0);
- rw_lock_x_lock(&table->stats_latch);
-
if (!table->stat_initialized) {
- rw_lock_x_unlock(&table->stats_latch);
return;
}
@@ -221,6 +218,4 @@ dict_stats_deinit(
sizeof(index->stat_n_leaf_pages));
}
#endif /* HAVE_valgrind */
-
- rw_lock_x_unlock(&table->stats_latch);
}
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index be8ad78de82..ce19178a5ad 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -108,7 +108,6 @@ extern mysql_pfs_key_t trx_i_s_cache_lock_key;
extern mysql_pfs_key_t trx_purge_latch_key;
extern mysql_pfs_key_t index_tree_rw_lock_key;
extern mysql_pfs_key_t index_online_log_key;
-extern mysql_pfs_key_t dict_table_stats_key;
extern mysql_pfs_key_t trx_sys_rw_lock_key;
#endif /* UNIV_PFS_RWLOCK */
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index 37421930b9b..9325f39a309 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -327,8 +327,6 @@ struct trx_undo_t {
(IB_ID_MAX if the undo log is empty) */
buf_block_t* guess_block; /*!< guess for the buffer block where
the top page might reside */
- ulint withdraw_clock; /*!< the withdraw clock value of the
- buffer pool when guess_block was stored */
/** @return whether the undo log is empty */
bool empty() const { return top_undo_no == IB_ID_MAX; }
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index c9ccb35ea05..33aa578873f 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1522,7 +1522,7 @@ error_exit:
srv_stats.n_rows_inserted.inc(size_t(trx->id));
}
- /* Not protected by dict_table_stats_lock() for performance
+ /* Not protected by dict_sys.mutex for performance
reasons, we would rather get garbage in stat_n_rows (which is
just an estimate anyway) than protecting the following code
with a latch. */
@@ -1892,7 +1892,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
ut_ad(is_delete == (node->is_delete == PLAIN_DELETE));
if (is_delete) {
- /* Not protected by dict_table_stats_lock() for performance
+ /* Not protected by dict_sys.mutex for performance
reasons, we would rather get garbage in stat_n_rows (which is
just an estimate anyway) than protecting the following code
with a latch. */
@@ -2234,8 +2234,7 @@ row_update_cascade_for_mysql(
bool stats;
if (node->is_delete == PLAIN_DELETE) {
- /* Not protected by
- dict_table_stats_lock() for
+ /* Not protected by dict_sys.mutex for
performance reasons, we would rather
get garbage in stat_n_rows (which is
just an estimate anyway) than
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 1529d8050db..114d83c8564 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -567,7 +567,7 @@ row_undo_ins(
}
if (err == DB_SUCCESS && node->table->stat_initialized) {
- /* Not protected by dict_table_stats_lock() for
+ /* Not protected by dict_sys.mutex for
performance reasons, we would rather get garbage
in stat_n_rows (which is just an estimate anyway)
than protecting the following code with a latch. */
diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc
index a41d8a0d4f9..87646867319 100644
--- a/storage/innobase/sync/sync0debug.cc
+++ b/storage/innobase/sync/sync0debug.cc
@@ -1334,9 +1334,6 @@ sync_latch_meta_init()
LATCH_ADD_RWLOCK(INDEX_TREE, SYNC_INDEX_TREE, index_tree_rw_lock_key);
- LATCH_ADD_RWLOCK(DICT_TABLE_STATS, SYNC_INDEX_TREE,
- dict_table_stats_key);
-
/* JAN: TODO: Add PFS instrumentation */
LATCH_ADD_MUTEX(DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK,
PFS_NOT_INSTRUMENTED);
diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc
index dd78aa9ae14..c2957a3fdcb 100644
--- a/storage/innobase/sync/sync0sync.cc
+++ b/storage/innobase/sync/sync0sync.cc
@@ -87,7 +87,6 @@ mysql_pfs_key_t buf_block_lock_key;
mysql_pfs_key_t buf_block_debug_latch_key;
# endif /* UNIV_DEBUG */
mysql_pfs_key_t dict_operation_lock_key;
-mysql_pfs_key_t dict_table_stats_key;
mysql_pfs_key_t index_tree_rw_lock_key;
mysql_pfs_key_t index_online_log_key;
mysql_pfs_key_t fil_space_latch_key;
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index 6b0395cef07..52130b50eb1 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -1912,8 +1912,6 @@ dberr_t trx_undo_report_rename(trx_t* trx, const dict_table_t* table)
if (uint16_t offset = trx_undo_page_report_rename(
trx, table, block, &mtr)) {
- undo->withdraw_clock
- = buf_pool.withdraw_clock();
undo->top_page_no = undo->last_page_no;
undo->top_offset = offset;
undo->top_undo_no = trx->undo_no++;
@@ -2076,7 +2074,6 @@ trx_undo_report_row_operation(
mtr_commit(&mtr);
} else {
/* Success */
- undo->withdraw_clock = buf_pool.withdraw_clock();
mtr_commit(&mtr);
undo->top_page_no = undo_block->page.id().page_no();
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 1f3ce121c28..67e515127d0 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -981,7 +981,6 @@ trx_undo_mem_create(
undo->top_undo_no = IB_ID_MAX;
undo->top_page_no = page_no;
undo->guess_block = NULL;
- undo->withdraw_clock = 0;
ut_ad(undo->empty());
return(undo);
@@ -1157,9 +1156,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr)
if (undo) {
return buf_page_get_gen(
page_id_t(undo->rseg->space->id, undo->last_page_no),
- 0, RW_X_LATCH,
- buf_pool.is_obsolete(undo->withdraw_clock)
- ? NULL : undo->guess_block,
+ 0, RW_X_LATCH, undo->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
}
@@ -1213,9 +1210,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
if (*undo) {
return buf_page_get_gen(
page_id_t(rseg->space->id, (*undo)->last_page_no),
- 0, RW_X_LATCH,
- buf_pool.is_obsolete((*undo)->withdraw_clock)
- ? NULL : (*undo)->guess_block,
+ 0, RW_X_LATCH, (*undo)->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
}