mirror of
https://github.com/MariaDB/server.git
synced 2025-11-09 23:36:13 +01:00
In the parent commit, dict_sys.latch could theoretically have been
replaced with a mutex. But, we can do better and merge dict_sys.mutex
into dict_sys.latch. Generally, every occurrence of dict_sys.mutex_lock()
will be replaced with dict_sys.lock().
The PERFORMANCE_SCHEMA instrumentation for dict_sys_mutex
will be removed along with dict_sys.mutex. The dict_sys.latch
will remain instrumented as dict_operation_lock.
Some use of dict_sys.lock() will be replaced with dict_sys.freeze(),
which we will reintroduce for the new shared mode. Most notably,
concurrent table lookups are possible as long as the tables are present
in the dict_sys cache. In particular, this will allow more concurrency
among InnoDB purge workers.
Because dict_sys.mutex will no longer 'throttle' the threads that purge
InnoDB transaction history, a performance degradation may be observed
unless innodb_purge_threads=1.
The table cache eviction policy will become FIFO-like,
similar to what happened to fil_system.LRU
in commit 45ed9dd957.
The name of the list dict_sys.table_LRU will become somewhat misleading;
that list contains tables that may be evicted, even though the
eviction policy no longer is least-recently-used but first-in-first-out.
(Note: Tables can never be evicted as long as locks exist on them or
the tables are in use by some thread.)
As demonstrated by the test perfschema.sxlock_func, there
will be less contention on dict_sys.latch, because some previous
use of exclusive latches will be replaced with shared latches.
fts_parse_sql_no_dict_lock(): Replaced with pars_sql().
fts_get_table_name_prefix(): Merged to fts_optimize_create().
dict_stats_update_transient_for_index(): Deduplicated some code.
ha_innobase::info_low(), dict_stats_stop_bg(): Use a combination
of dict_sys.latch and table->stats_mutex_lock() to cover the
changes of BG_STAT_SHOULD_QUIT, because the flag is being read
in dict_stats_update_persistent() while not holding dict_sys.latch.
row_discard_tablespace_for_mysql(): Protect stats_bg_flag by
exclusive dict_sys.latch, like most other code does.
row_quiesce_table_has_fts_index(): Remove unnecessary mutex
acquisition. FLUSH TABLES...FOR EXPORT is protected by MDL.
row_import::set_root_by_heuristic(): Remove unnecessary mutex
acquisition. ALTER TABLE...IMPORT TABLESPACE is protected by MDL.
row_ins_sec_index_entry_low(): Replace a call
to dict_set_corrupted_index_cache_only(). Reads of index->type
were not really protected by dict_sys.mutex, and writes
(flagging an index corrupted) should be extremely rare.
dict_stats_process_entry_from_defrag_pool(): Only freeze the dictionary,
do not lock it exclusively.
dict_stats_wait_bg_to_stop_using_table(), DICT_BG_YIELD: Remove trx.
We can simply invoke dict_sys.unlock() and dict_sys.lock() directly.
dict_acquire_mdl_shared()<trylock=false>: Assert that dict_sys.latch is
only held in shared more, not exclusive mode. Only acquire it in
exclusive mode if the table needs to be loaded to the cache.
dict_sys_t::acquire(): Remove. Relocating elements in dict_sys.table_LRU
would require holding an exclusive latch, which we want to avoid
for performance reasons.
dict_sys_t::allow_eviction(): Add the table first to dict_sys.table_LRU,
to compensate for the removal of dict_sys_t::acquire(). This function
is only invoked by INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS.
dict_table_open_on_id(), dict_table_open_on_name(): If dict_locked=false,
try to acquire dict_sys.latch in shared mode. Only acquire the latch in
exclusive mode if the table is not found in the cache.
Reviewed by: Thirunarayanan Balathandayuthapani
219 lines
8.8 KiB
C++
219 lines
8.8 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2017, 2021, 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, Fifth Floor, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/dict0load.h
|
|
Loads to the memory cache database object definitions
|
|
from dictionary tables
|
|
|
|
Created 4/24/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef dict0load_h
|
|
#define dict0load_h
|
|
|
|
#include "dict0types.h"
|
|
#include "trx0types.h"
|
|
#include "ut0byte.h"
|
|
#include "mem0mem.h"
|
|
#include "btr0types.h"
|
|
|
|
#include <deque>
|
|
|
|
/** A stack of table names related through foreign key constraints */
|
|
typedef std::deque<const char*, ut_allocator<const char*> > dict_names_t;
|
|
|
|
/** Check each tablespace found in the data dictionary.
|
|
Then look at each table defined in SYS_TABLES that has a space_id > 0
|
|
to find all the file-per-table tablespaces.
|
|
|
|
In a crash recovery we already have some tablespace objects created from
|
|
processing the REDO log. We will compare the
|
|
space_id information in the data dictionary to what we find in the
|
|
tablespace file. In addition, more validation will be done if recovery
|
|
was needed and force_recovery is not set.
|
|
|
|
We also scan the biggest space id, and store it to fil_system. */
|
|
void dict_check_tablespaces_and_store_max_id();
|
|
|
|
/** Make sure the data_file_name is saved in dict_table_t if needed.
|
|
@param[in,out] table Table object
|
|
@param[in] dict_locked dict_sys.frozen() */
|
|
void dict_get_and_save_data_dir_path(dict_table_t* table, bool dict_locked);
|
|
|
|
/***********************************************************************//**
|
|
Loads a table object based on the table id.
|
|
@return table; NULL if table does not exist */
|
|
dict_table_t*
|
|
dict_load_table_on_id(
|
|
/*==================*/
|
|
table_id_t table_id, /*!< in: table id */
|
|
dict_err_ignore_t ignore_err); /*!< in: errors to ignore
|
|
when loading the table */
|
|
/********************************************************************//**
|
|
This function is called when the database is booted.
|
|
Loads system table index definitions except for the clustered index which
|
|
is added to the dictionary cache at booting before calling this function. */
|
|
void
|
|
dict_load_sys_table(
|
|
/*================*/
|
|
dict_table_t* table); /*!< in: system table */
|
|
/***********************************************************************//**
|
|
Loads foreign key constraints where the table is either the foreign key
|
|
holder or where the table is referenced by a foreign key. Adds these
|
|
constraints to the data dictionary.
|
|
|
|
The foreign key constraint is loaded only if the referenced table is also
|
|
in the dictionary cache. If the referenced table is not in dictionary
|
|
cache, then it is added to the output parameter (fk_tables).
|
|
|
|
@return DB_SUCCESS or error code */
|
|
dberr_t
|
|
dict_load_foreigns(
|
|
/*===============*/
|
|
const char* table_name, /*!< in: table name */
|
|
const char** col_names, /*!< in: column names, or NULL
|
|
to use table->col_names */
|
|
bool check_recursive,/*!< in: Whether to check
|
|
recursive load of tables
|
|
chained by FK */
|
|
bool check_charsets, /*!< in: whether to check
|
|
charset compatibility */
|
|
dict_err_ignore_t ignore_err, /*!< in: error to be ignored */
|
|
dict_names_t& fk_tables) /*!< out: stack of table names
|
|
which must be loaded
|
|
subsequently to load all the
|
|
foreign key constraints. */
|
|
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
|
|
|
|
/********************************************************************//**
|
|
This function opens a system table, and return the first record.
|
|
@return first record of the system table */
|
|
const rec_t*
|
|
dict_startscan_system(
|
|
/*==================*/
|
|
btr_pcur_t* pcur, /*!< out: persistent cursor to
|
|
the record */
|
|
mtr_t* mtr, /*!< in: the mini-transaction */
|
|
dict_table_t* table); /*!< in: system table */
|
|
/********************************************************************//**
|
|
This function get the next system table record as we scan the table.
|
|
@return the record if found, NULL if end of scan. */
|
|
const rec_t*
|
|
dict_getnext_system(
|
|
/*================*/
|
|
btr_pcur_t* pcur, /*!< in/out: persistent cursor
|
|
to the record */
|
|
mtr_t* mtr); /*!< in: the mini-transaction */
|
|
|
|
/** Load a table definition from a SYS_TABLES record to dict_table_t.
|
|
Do not load any columns or indexes.
|
|
@param[in] name Table name
|
|
@param[in] rec SYS_TABLES record
|
|
@param[out,own] table table, or nullptr
|
|
@return error message
|
|
@retval nullptr on success */
|
|
const char *dict_load_table_low(const span<const char> &name,
|
|
const rec_t *rec, dict_table_t **table)
|
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
|
|
|
/********************************************************************//**
|
|
This function parses a SYS_INDEXES record and populate a dict_index_t
|
|
structure with the information from the record. For detail information
|
|
about SYS_INDEXES fields, please refer to dict_boot() function.
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_indexes_rec(
|
|
/*=========================*/
|
|
mem_heap_t* heap, /*!< in/out: heap memory */
|
|
const rec_t* rec, /*!< in: current SYS_INDEXES rec */
|
|
dict_index_t* index, /*!< out: dict_index_t to be
|
|
filled */
|
|
table_id_t* table_id); /*!< out: table id */
|
|
/********************************************************************//**
|
|
This function parses a SYS_COLUMNS record and populate a dict_column_t
|
|
structure with the information from the record.
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_columns_rec(
|
|
/*=========================*/
|
|
mem_heap_t* heap, /*!< in/out: heap memory */
|
|
const rec_t* rec, /*!< in: current SYS_COLUMNS rec */
|
|
dict_col_t* column, /*!< out: dict_col_t to be filled */
|
|
table_id_t* table_id, /*!< out: table id */
|
|
const char** col_name, /*!< out: column name */
|
|
ulint* nth_v_col); /*!< out: if virtual col, this is
|
|
records its sequence number */
|
|
|
|
/** This function parses a SYS_VIRTUAL record and extract virtual column
|
|
information
|
|
@param[in,out] heap heap memory
|
|
@param[in] rec current SYS_COLUMNS rec
|
|
@param[in,out] table_id table id
|
|
@param[in,out] pos virtual column position
|
|
@param[in,out] base_pos base column position
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_virtual_rec(
|
|
const rec_t* rec,
|
|
table_id_t* table_id,
|
|
ulint* pos,
|
|
ulint* base_pos);
|
|
/********************************************************************//**
|
|
This function parses a SYS_FIELDS record and populate a dict_field_t
|
|
structure with the information from the record.
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_fields_rec(
|
|
/*========================*/
|
|
mem_heap_t* heap, /*!< in/out: heap memory */
|
|
const rec_t* rec, /*!< in: current SYS_FIELDS rec */
|
|
dict_field_t* sys_field, /*!< out: dict_field_t to be
|
|
filled */
|
|
ulint* pos, /*!< out: Field position */
|
|
index_id_t* index_id, /*!< out: current index id */
|
|
index_id_t last_id); /*!< in: previous index id */
|
|
/********************************************************************//**
|
|
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
|
|
structure with the information from the record. For detail information
|
|
about SYS_FOREIGN fields, please refer to dict_load_foreign() function
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_foreign_rec(
|
|
/*=========================*/
|
|
mem_heap_t* heap, /*!< in/out: heap memory */
|
|
const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
|
|
dict_foreign_t* foreign); /*!< out: dict_foreign_t to be
|
|
filled */
|
|
/********************************************************************//**
|
|
This function parses a SYS_FOREIGN_COLS record and extract necessary
|
|
information from the record and return to caller.
|
|
@return error message, or NULL on success */
|
|
const char*
|
|
dict_process_sys_foreign_col_rec(
|
|
/*=============================*/
|
|
mem_heap_t* heap, /*!< in/out: heap memory */
|
|
const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
|
|
const char** name, /*!< out: foreign key constraint name */
|
|
const char** for_col_name, /*!< out: referencing column name */
|
|
const char** ref_col_name, /*!< out: referenced column name
|
|
in referenced table */
|
|
ulint* pos); /*!< out: column position */
|
|
|
|
#endif
|