Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2020-10-29 13:38:38 +02:00
commit 7b2bb67113
177 changed files with 20544 additions and 2947 deletions

View file

@ -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));
@ -592,7 +592,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 */

View file

@ -614,8 +614,24 @@ btr_estimate_n_rows_in_range(
const dtuple_t* tuple2,
page_cur_mode_t mode2);
/*******************************************************************//**
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
@ -623,12 +639,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

View file

@ -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, ... */
@ -528,9 +526,8 @@ struct btr_pcur_t{
btr_pcur_t() :
btr_cur(), latch_mode(0), 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)
{

View file

@ -206,8 +206,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

View file

@ -0,0 +1,77 @@
/*****************************************************************************
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:
Block_hint():m_block(NULL),m_page_id(0,0) {}
/** 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= NULL; }
/** 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;
/** If m_block is non-null, the m_block->page.id at time it was stored. */
page_id_t m_page_id;
/** 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

View file

@ -100,10 +100,6 @@ extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools
extern volatile bool buf_pool_withdrawing; /*!< true when withdrawing buffer
pool pages might cause page relocation */
extern volatile ulint buf_withdraw_clock; /*!< the clock is incremented
every time a pointer to a page may
become obsolete */
# ifdef UNIV_DEBUG
extern my_bool buf_disable_resize_buffer_pool_debug; /*!< if TRUE, resizing
buffer pool is not allowed. */
@ -1394,14 +1390,6 @@ buf_get_nth_chunk_block(
ulint n, /*!< in: nth chunk in the buffer pool */
ulint* chunk_size); /*!< in: chunk size */
/** Verify the possibility that a stored page is not in buffer pool.
@param[in] withdraw_clock withdraw clock when stored the page
@retval true if the page might be relocated */
UNIV_INLINE
bool
buf_pool_is_obsolete(
ulint withdraw_clock);
/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit,
if needed.
@param[in] size size in bytes
@ -2284,6 +2272,12 @@ struct buf_pool_t{
return NULL;
}
} io_buf;
/** Determine if a pointer belongs to a buf_block_t.
It can be a pointer to the buf_block_t itself or a member of it.
@param ptr a pointer that will not be dereferenced
@return whether the ptr belongs to a buf_block_t struct */
inline bool is_block_field(const void *ptr) const;
};
/** Print the given buf_pool_t object.

View file

@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2014, 2019, MariaDB Corporation.
Copyright (c) 2014, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -54,6 +54,25 @@ struct buf_chunk_t{
}
};
bool buf_pool_t::is_block_field(const void *ptr) const
{
const buf_chunk_t* chunk= chunks;
const buf_chunk_t *const echunk= chunk + ut_min(n_chunks,
n_chunks_new);
/* TODO: protect chunks with a mutex (the older pointer will
currently remain during resize()) */
while (chunk < echunk)
{
if (ptr >= reinterpret_cast<const void*>(chunk->blocks) &&
ptr < reinterpret_cast<const void*>(
chunk->blocks + chunk->size))
return true;
chunk++;
}
return false;
}
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@ -989,8 +1008,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
@ -999,6 +1016,8 @@ buf_block_buf_fix_dec(
rw_lock_s_unlock(block->debug_latch);
}
#endif /* UNIV_DEBUG */
block->unfix();
}
/** Returns the buffer pool instance given a page id.
@ -1372,18 +1391,6 @@ buf_page_get_frame(
}
}
/** Verify the possibility that a stored page is not in buffer pool.
@param[in] withdraw_clock withdraw clock when stored the page
@retval true if the page might be relocated */
UNIV_INLINE
bool
buf_pool_is_obsolete(
ulint withdraw_clock)
{
return(UNIV_UNLIKELY(buf_pool_withdrawing
|| buf_withdraw_clock != withdraw_clock));
}
/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit,
if needed.
@param[in] size size in bytes

View file

@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 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 as published by the Free Software
@ -1265,7 +1265,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

View file

@ -938,7 +938,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);

View file

@ -297,20 +297,23 @@ 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.
/** 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, /*!< in: table name */
fil_space_t* space, /*!< in: tablespace */
ulint n_cols, /*!< in: total number of columns
including virtual and non-virtual
columns */
ulint n_v_cols, /*!< in: number of virtual columns */
ulint flags, /*!< in: table flags */
ulint flags2); /*!< in: table flags2 */
const char* name,
fil_space_t* space,
ulint n_cols,
ulint n_v_cols,
ulint flags,
ulint flags2);
/****************************************************************//**
Free a table memory object. */
void
@ -1118,7 +1121,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
@ -2102,20 +2105,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;
/** 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. */

View file

@ -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);
}

View file

@ -170,10 +170,10 @@ mtr_t::release_block_at_savepoint(
ut_a(slot->object == block);
reinterpret_cast<buf_block_t*>(block)->unfix();
buf_page_release_latch(block, slot->type);
reinterpret_cast<buf_block_t*>(block)->unfix();
slot->object = NULL;
}

View file

@ -122,7 +122,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;
extern mysql_pfs_key_t hash_table_locks_key;
#endif /* UNIV_PFS_RWLOCK */

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation.
Copyright (c) 2017, 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 as published by the Free Software

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation.
Copyright (c) 2017, 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 as published by the Free Software
@ -360,8 +360,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; }