diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 67b5b856e0fb9fc8dcf77b3e838aa805cffe3ef8..f12e253d797234512ec9d627687a16dfb7896ba6 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -105,7 +105,6 @@ SET(INNOBASE_SOURCES include/data0types.h include/db0err.h include/dict0boot.h - include/dict0boot.ic include/dict0crea.h include/dict0crea.ic include/dict0defrag_bg.h diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index bd2cf4ffdd8f80470fcb5f95f4dc61621c657e1d..f4f94e2ace9150c6c5baa969a03ef0d8b8cf7cdd 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -93,27 +93,16 @@ dict_hdr_get_new_id( mtr.commit(); } -/**********************************************************************//** -Writes the current value of the row id counter to the dictionary header file -page. */ -void -dict_hdr_flush_row_id(void) -/*=======================*/ +/** Update dict_sys.row_id in the dictionary header file page. */ +void dict_hdr_flush_row_id(row_id_t id) { - row_id_t id; - mtr_t mtr; - - ut_ad(mutex_own(&dict_sys.mutex)); - - id = dict_sys.row_id; - - mtr.start(); - - buf_block_t* d = dict_hdr_get(&mtr); - - mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame, id); - - mtr.commit(); + mtr_t mtr; + mtr.start(); + buf_block_t* d= dict_hdr_get(&mtr); + byte *row_id= DICT_HDR + DICT_HDR_ROW_ID + d->frame; + if (mach_read_from_8(row_id) < id) + mtr.write<8>(*d, row_id, id); + mtr.commit(); } /*****************************************************************//** @@ -270,9 +259,7 @@ dict_boot(void) ..._MARGIN, it will immediately be updated to the disk-based header. */ - dict_sys.row_id = DICT_HDR_ROW_ID_WRITE_MARGIN - + ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID), - DICT_HDR_ROW_ID_WRITE_MARGIN); + dict_sys.recover_row_id(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID)); if (ulint max_space_id = mach_read_from_4(dict_hdr + DICT_HDR_MAX_SPACE_ID)) { max_space_id--; diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 857342b18bdb598be511e04c12a983424b0c9bf4..fb9d5b810e28fd33b1c27df4461998c5e647a1d8 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -46,27 +46,39 @@ dict_hdr_get_new_id( (not assigned if NULL) */ ulint* space_id); /*!< out: space id (not assigned if NULL) */ -/**********************************************************************//** -Writes the current value of the row id counter to the dictionary header file -page. */ -void -dict_hdr_flush_row_id(void); -/*=======================*/ -/**********************************************************************//** -Returns a new row id. -@return the new id */ -UNIV_INLINE -row_id_t -dict_sys_get_new_row_id(void); -/*=========================*/ +/** Update dict_sys.row_id in the dictionary header file page. */ +void dict_hdr_flush_row_id(row_id_t id); +/** @return A new value for GEN_CLUST_INDEX(DB_ROW_ID) */ +inline row_id_t dict_sys_t::get_new_row_id() +{ + row_id_t id= row_id.fetch_add(1); + if (!(id % ROW_ID_WRITE_MARGIN)) + dict_hdr_flush_row_id(id); + return id; +} + +/** Ensure that row_id is not smaller than id, on IMPORT TABLESPACE */ +inline void dict_sys_t::update_row_id(row_id_t id) +{ + row_id_t sys_id= row_id; + while (id >= sys_id) + { + if (!row_id.compare_exchange_strong(sys_id, id)) + continue; + if (!(id % ROW_ID_WRITE_MARGIN)) + dict_hdr_flush_row_id(id); + break; + } +} + /**********************************************************************//** Writes a row id to a record or other 6-byte stored form. */ -UNIV_INLINE -void -dict_sys_write_row_id( -/*==================*/ - byte* field, /*!< in: record field */ - row_id_t row_id);/*!< in: row id */ +inline void dict_sys_write_row_id(byte *field, row_id_t row_id) +{ + static_assert(DATA_ROW_ID_LEN == 6, "compatibility"); + mach_write_to_6(field, row_id); +} + /*****************************************************************//** Initializes the data dictionary memory structures when the database is started. This function is also called when the data dictionary is created. @@ -87,12 +99,7 @@ dict_create(void) /*********************************************************************//** Check if a table id belongs to system table. @return true if the table id belongs to a system table. */ -UNIV_INLINE -bool -dict_is_sys_table( -/*==============*/ - table_id_t id) /*!< in: table id to check */ - MY_ATTRIBUTE((warn_unused_result)); +inline bool dict_is_sys_table(table_id_t id) { return id < DICT_HDR_FIRST_ID; } /* Space id and page no where the dictionary header resides */ #define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */ @@ -289,11 +296,4 @@ length of thos fields. */ #define DICT_FLD_LEN_SPACE 4 #define DICT_FLD_LEN_FLAGS 4 -/* When a row id which is zero modulo this number (which must be a power of -two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is -updated */ -#define DICT_HDR_ROW_ID_WRITE_MARGIN 256 - -#include "dict0boot.ic" - #endif diff --git a/storage/innobase/include/dict0boot.ic b/storage/innobase/include/dict0boot.ic deleted file mode 100644 index d920bddecee9541114aaff32d443747f7d76a9a0..0000000000000000000000000000000000000000 --- a/storage/innobase/include/dict0boot.ic +++ /dev/null @@ -1,78 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2013, 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 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/dict0boot.ic -Data dictionary creation and booting - -Created 4/18/1996 Heikki Tuuri -*******************************************************/ - -/**********************************************************************//** -Returns a new row id. -@return the new id */ -UNIV_INLINE -row_id_t -dict_sys_get_new_row_id(void) -/*=========================*/ -{ - row_id_t id; - - mutex_enter(&dict_sys.mutex); - - id = dict_sys.row_id; - - if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) { - - dict_hdr_flush_row_id(); - } - - dict_sys.row_id++; - - mutex_exit(&dict_sys.mutex); - - return(id); -} - -/**********************************************************************//** -Writes a row id to a record or other 6-byte stored form. */ -UNIV_INLINE -void -dict_sys_write_row_id( -/*==================*/ - byte* field, /*!< in: record field */ - row_id_t row_id) /*!< in: row id */ -{ - compile_time_assert(DATA_ROW_ID_LEN == 6); - mach_write_to_6(field, row_id); -} - -/*********************************************************************//** -Check if a table id belongs to system table. -@return true if the table id belongs to a system table. */ -UNIV_INLINE -bool -dict_is_sys_table( -/*==============*/ - table_id_t id) /*!< in: table id to check */ -{ - return(id < DICT_HDR_FIRST_ID); -} - - diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 2d347feb7d62ea3743ff8e95c2b805755c21a21b..a6b01ab6c430ffecc91c685499a6aaa640ac8b7a 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1416,12 +1416,6 @@ class dict_sys_t and DROP TABLE, as well as reading the dictionary data for a table from system tables */ - row_id_t row_id; /*!< the next row id to assign; - NOTE that at a checkpoint this - must be written to the dict system - header and flushed to a file; in - recovery this must be derived from - the log records */ hash_table_t table_hash; /*!< hash table of the tables, based on name */ /** hash table of persistent table IDs */ @@ -1439,14 +1433,31 @@ class dict_sys_t UT_LIST_BASE_NODE_T(dict_table_t) table_non_LRU; /*!< List of tables that can't be evicted from the cache */ + private: bool m_initialised= false; /** the sequence of temporary table IDs */ std::atomic<table_id_t> temp_table_id{DICT_HDR_FIRST_ID}; - - /** hash table of temporary table IDs */ - hash_table_t temp_id_hash; + /** hash table of temporary table IDs */ + hash_table_t temp_id_hash; + /** the next value of DB_ROW_ID, backed by DICT_HDR_ROW_ID + (FIXME: remove this, and move to dict_table_t) */ + Atomic_relaxed<row_id_t> row_id; + /** The synchronization interval of row_id */ + static constexpr size_t ROW_ID_WRITE_MARGIN= 256; public: + /** @return A new value for GEN_CLUST_INDEX(DB_ROW_ID) */ + inline row_id_t get_new_row_id(); + + /** Ensure that row_id is not smaller than id, on IMPORT TABLESPACE */ + inline void update_row_id(row_id_t id); + + /** Recover the global DB_ROW_ID sequence on database startup */ + void recover_row_id(row_id_t id) + { + row_id= ut_uint64_align_up(id, ROW_ID_WRITE_MARGIN) + ROW_ID_WRITE_MARGIN; + } + /** @return a new temporary table ID */ table_id_t get_temporary_table_id() { return temp_table_id.fetch_add(1, std::memory_order_relaxed); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index ad097f4472cab7e6edd42d5e6d716a741772fe5f..4accc5dd9902b7c125421540e4534db280cd37cf 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2396,15 +2396,7 @@ row_import_set_sys_max_row_id( if (row_id) { /* Update the system row id if the imported index row id is greater than the max system row id. */ - - mutex_enter(&dict_sys.mutex); - - if (row_id >= dict_sys.row_id) { - dict_sys.row_id = row_id + 1; - dict_hdr_flush_row_id(); - } - - mutex_exit(&dict_sys.mutex); + dict_sys.update_row_id(row_id); } } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index b3f0a33cedcc865cda9def450753487ec39dd443..b86f4fe34ceacc9fab36f428519f145868632291 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -3501,22 +3501,9 @@ row_ins_alloc_row_id_step( /*======================*/ ins_node_t* node) /*!< in: row insert node */ { - row_id_t row_id; - - ut_ad(node->state == INS_NODE_ALLOC_ROW_ID); - - if (dict_index_is_unique(dict_table_get_first_index(node->table))) { - - /* No row id is stored if the clustered index is unique */ - - return; - } - - /* Fill in row id value to row */ - - row_id = dict_sys_get_new_row_id(); - - dict_sys_write_row_id(node->sys_buf, row_id); + ut_ad(node->state == INS_NODE_ALLOC_ROW_ID); + if (dict_table_get_first_index(node->table)->is_gen_clust()) + dict_sys_write_row_id(node->sys_buf, dict_sys.get_new_row_id()); } /***********************************************************//**