mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 14:32:34 +01:00
7dc6066dea
dict_stats_exec_sql(): Expect the caller to always provide a transaction. Remove some redundant assertions. The caller must hold dict_sys->mutex, but holding dict_operation_lock is only necessary for accessing data dictionary tables, which we are not accessing. dict_stats_save_index_stat(): Acquire dict_sys->mutex for invoking dict_stats_exec_sql(). dict_stats_save(), dict_stats_update_for_index(), dict_stats_update(), dict_stats_drop_index(), dict_stats_delete_from_table_stats(), dict_stats_delete_from_index_stats(), dict_stats_drop_table(), dict_stats_rename_in_table_stats(), dict_stats_rename_in_index_stats(), dict_stats_rename_table(): Use a single caller-provided transaction that is started and committed or rolled back by the caller. dict_stats_process_entry_from_recalc_pool(): Let the caller provide a transaction object. ha_innobase::open(): Pass a transaction to dict_stats_init(). ha_innobase::create(), ha_innobase::discard_or_import_tablespace(): Pass a transaction to dict_stats_update(). ha_innobase::rename_table(): Pass a transaction to dict_stats_rename_table(). We do not use the same transaction as the one that updated the data dictionary tables, because we already released the dict_operation_lock. (FIXME: there is a race condition; a lock wait on SYS_* tables could occur in another DDL transaction until the data dictionary transaction is committed.) ha_innobase::info_low(): Pass a transaction to dict_stats_update() when calculating persistent statistics. alter_stats_norebuild(), alter_stats_rebuild(): Update the persistent statistics as well. In this way, a single transaction will be used for updating the statistics of a whole table, even for partitioned tables. ha_innobase::commit_inplace_alter_table(): Drop statistics for all partitions when adding or dropping virtual columns, so that the statistics will be recalculated on the next handler::open(). This is a refactored version of Oracle Bug#22469660 fix. RecLock::add_to_waitq(), lock_table_enqueue_waiting(): Do not allow a lock wait to occur for updating statistics in a data dictionary transaction, such as DROP TABLE. Instead, return the previously unused error code DB_QUE_THR_SUSPENDED. row_merge_lock_table(), row_mysql_lock_table(): Remove dead code for handling DB_QUE_THR_SUSPENDED. row_drop_table_for_mysql(), row_truncate_table_for_mysql(): Drop the statistics as part of the data dictionary transaction. After TRUNCATE TABLE, the statistics will be recalculated on subsequent ha_innobase::open(), similar to how the logic after the above-mentioned Oracle Bug#22469660 fix in ha_innobase::commit_inplace_alter_table() works. btr_defragment_thread(): Use a single transaction object for updating defragmentation statistics. dict_stats_save_defrag_stats(), dict_stats_save_defrag_stats(), dict_stats_process_entry_from_defrag_pool(), dict_defrag_process_entries_from_defrag_pool(), dict_stats_save_defrag_summary(), dict_stats_save_defrag_stats(): Add a parameter for the transaction. dict_stats_empty_table(): Make public. This will be called by row_truncate_table_for_mysql() after dropping persistent statistics, to clear the memory-based statistics as well.
240 lines
8.5 KiB
C
240 lines
8.5 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2017, 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
|
|
Foundation; version 2 of the License.
|
|
|
|
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 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/dict0stats.h
|
|
Code used for calculating and manipulating table statistics.
|
|
|
|
Created Jan 06, 2010 Vasil Dimov
|
|
*******************************************************/
|
|
|
|
#ifndef dict0stats_h
|
|
#define dict0stats_h
|
|
|
|
#include "univ.i"
|
|
|
|
#include "dict0types.h"
|
|
#include "trx0types.h"
|
|
|
|
enum dict_stats_upd_option_t {
|
|
DICT_STATS_RECALC_PERSISTENT,/* (re) calculate the
|
|
statistics using a precise and slow
|
|
algo and save them to the persistent
|
|
storage, if the persistent storage is
|
|
not present then emit a warning and
|
|
fall back to transient stats */
|
|
DICT_STATS_RECALC_TRANSIENT,/* (re) calculate the statistics
|
|
using an imprecise quick algo
|
|
without saving the results
|
|
persistently */
|
|
DICT_STATS_EMPTY_TABLE, /* Write all zeros (or 1 where it makes sense)
|
|
into a table and its indexes' statistics
|
|
members. The resulting stats correspond to an
|
|
empty table. If the table is using persistent
|
|
statistics, then they are saved on disk. */
|
|
DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY /* fetch the stats
|
|
from the persistent storage if the in-memory
|
|
structures have not been initialized yet,
|
|
otherwise do nothing */
|
|
};
|
|
|
|
/*********************************************************************//**
|
|
Set the persistent statistics flag for a given table. This is set only
|
|
in the in-memory table object and is not saved on disk. It will be read
|
|
from the .frm file upon first open from MySQL after a server restart. */
|
|
UNIV_INLINE
|
|
void
|
|
dict_stats_set_persistent(
|
|
/*======================*/
|
|
dict_table_t* table, /*!< in/out: table */
|
|
ibool ps_on, /*!< in: persistent stats explicitly enabled */
|
|
ibool ps_off) /*!< in: persistent stats explicitly disabled */
|
|
MY_ATTRIBUTE((nonnull));
|
|
|
|
/** @return whether persistent statistics is enabled for a given table */
|
|
UNIV_INLINE
|
|
bool
|
|
dict_stats_is_persistent_enabled(const dict_table_t* table)
|
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
|
|
|
/*********************************************************************//**
|
|
Set the auto recalc flag for a given table (only honored for a persistent
|
|
stats enabled table). The flag is set only in the in-memory table object
|
|
and is not saved in InnoDB files. It will be read from the .frm file upon
|
|
first open from MySQL after a server restart. */
|
|
UNIV_INLINE
|
|
void
|
|
dict_stats_auto_recalc_set(
|
|
/*=======================*/
|
|
dict_table_t* table, /*!< in/out: table */
|
|
ibool auto_recalc_on, /*!< in: explicitly enabled */
|
|
ibool auto_recalc_off); /*!< in: explicitly disabled */
|
|
|
|
/** @return whether auto recalc is enabled for a given table*/
|
|
UNIV_INLINE
|
|
bool
|
|
dict_stats_auto_recalc_is_enabled(const dict_table_t* table)
|
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
|
|
|
/** Initialize table statistics for the first time when opening a table.
|
|
@param[in,out] table freshly opened table
|
|
@param[in,out] trx transaction */
|
|
UNIV_INLINE
|
|
void
|
|
dict_stats_init(dict_table_t* table, trx_t* trx);
|
|
|
|
/*********************************************************************//**
|
|
Deinitialize table's stats after the last close of the table. This is
|
|
used to detect "FLUSH TABLE" and refresh the stats upon next open. */
|
|
UNIV_INLINE
|
|
void
|
|
dict_stats_deinit(
|
|
/*==============*/
|
|
dict_table_t* table) /*!< in/out: table */
|
|
MY_ATTRIBUTE((nonnull));
|
|
|
|
/** Update the table modification counter and if necessary,
|
|
schedule new estimates for table and index statistics to be calculated.
|
|
@param[in,out] table persistent or temporary table */
|
|
void
|
|
dict_stats_update_if_needed(dict_table_t* table)
|
|
MY_ATTRIBUTE((nonnull));
|
|
|
|
/** Calculate new estimates for table and index statistics.
|
|
@param[in,out] table table
|
|
@param[in] stats_upd_option how to update statistics
|
|
@param[in,out] trx transaction
|
|
@return DB_* error code or DB_SUCCESS */
|
|
dberr_t
|
|
dict_stats_update(
|
|
dict_table_t* table,
|
|
dict_stats_upd_option_t stats_upd_option,
|
|
trx_t* trx);
|
|
|
|
/** Remove the persistent statistics for an index.
|
|
@param[in] db_and_table schema and table name, e.g., 'db/table'
|
|
@param[in] iname index name
|
|
@param[out] errstr error message (when not returning DB_SUCCESS)
|
|
@param[in] errstr_sz sizeof errstr
|
|
@param[in,out] trx transaction
|
|
@return DB_SUCCESS or error code */
|
|
dberr_t
|
|
dict_stats_drop_index(
|
|
const char* db_and_table,
|
|
const char* iname,
|
|
char* errstr,
|
|
size_t errstr_sz,
|
|
trx_t* trx);
|
|
|
|
/** Remove the persistent statistics for a table and all of its indexes.
|
|
@param[in] db_and_table schema and table name, e.g., 'db/table'
|
|
@param[out] errstr error message (when not returning DB_SUCCESS)
|
|
@param[in] errstr_sz sizeof errstr
|
|
@param[in,out] trx transaction
|
|
@return DB_SUCCESS or error code */
|
|
dberr_t
|
|
dict_stats_drop_table(
|
|
const char* db_and_table,
|
|
char* errstr,
|
|
size_t errstr_sz,
|
|
trx_t* trx);
|
|
|
|
/** Calculate index statistics.
|
|
@param[in,out] index index tree
|
|
@param[in,out] trx transaction (for persistent statistics)
|
|
@return DB_SUCCESS or error code */
|
|
UNIV_INTERN
|
|
dberr_t
|
|
dict_stats_update_for_index(dict_index_t* index, trx_t* trx)
|
|
MY_ATTRIBUTE((nonnull));
|
|
|
|
/** Rename a table in the InnoDB persistent statistics storage.
|
|
@param[in] old_name old schema and table name, e.g., 'db/table'
|
|
@param[in] new_name new schema and table name, e.g., 'db/table'
|
|
@param[out] errstr error message (when not returning DB_SUCCESS)
|
|
@param[in] errstr_sz sizeof errstr
|
|
@param[in,out] trx transaction
|
|
@return DB_SUCCESS or error code */
|
|
dberr_t
|
|
dict_stats_rename_table(
|
|
const char* old_name,
|
|
const char* new_name,
|
|
char* errstr,
|
|
size_t errstr_sz,
|
|
trx_t* trx);
|
|
/*********************************************************************//**
|
|
Renames an index in InnoDB persistent stats storage.
|
|
This function creates its own transaction and commits it.
|
|
@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
|
|
if the persistent stats do not exist. */
|
|
dberr_t
|
|
dict_stats_rename_index(
|
|
/*====================*/
|
|
const dict_table_t* table, /*!< in: table whose index
|
|
is renamed */
|
|
const char* old_index_name, /*!< in: old index name */
|
|
const char* new_index_name) /*!< in: new index name */
|
|
__attribute__((warn_unused_result));
|
|
|
|
/** Reset the table and index statsistics, corresponding to an empty table.
|
|
@param[in,out] table table whose statistics are to be reset
|
|
@param[in] empty_defrag_stats whether to empty the defrag statistics
|
|
*/
|
|
void
|
|
dict_stats_empty_table(dict_table_t* table, bool empty_defrag_stats = true);
|
|
|
|
/** Save an individual index's statistic into the persistent statistics
|
|
storage.
|
|
@param[in] index index to be updated
|
|
@param[in] last_update timestamp of the stat
|
|
@param[in] stat_name name of the stat
|
|
@param[in] stat_value value of the stat
|
|
@param[in] sample_size n pages sampled or NULL
|
|
@param[in] stat_description description of the stat
|
|
@param[in,out] trx dictionary transaction
|
|
@return DB_SUCCESS or error code */
|
|
dberr_t
|
|
dict_stats_save_index_stat(
|
|
dict_index_t* index,
|
|
lint last_update,
|
|
const char* stat_name,
|
|
ib_uint64_t stat_value,
|
|
ib_uint64_t* sample_size,
|
|
const char* stat_description,
|
|
trx_t* trx)
|
|
MY_ATTRIBUTE((nonnull(1,3,7), warn_unused_result));
|
|
|
|
/** Report an error if updating table statistics failed because
|
|
.ibd file is missing, table decryption failed or table is corrupted.
|
|
@param[in,out] table Table
|
|
@param[in] defragment true if statistics is for defragment
|
|
@retval DB_DECRYPTION_FAILED if decryption of the table failed
|
|
@retval DB_TABLESPACE_DELETED if .ibd file is missing
|
|
@retval DB_CORRUPTION if table is marked as corrupted */
|
|
dberr_t
|
|
dict_stats_report_error(dict_table_t* table, bool defragment = false)
|
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
|
|
|
#include "dict0stats.ic"
|
|
|
|
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS
|
|
void test_dict_stats_all();
|
|
#endif /* UNIV_ENABLE_UNIT_TEST_DICT_STATS */
|
|
|
|
#endif /* dict0stats_h */
|