Commit 0bee3b8d authored by Marko Mäkelä's avatar Marko Mäkelä

Cleanup: Use Atomic_relaxed for dict_sys.row_id

parent edbde4a1
...@@ -105,7 +105,6 @@ SET(INNOBASE_SOURCES ...@@ -105,7 +105,6 @@ SET(INNOBASE_SOURCES
include/data0types.h include/data0types.h
include/db0err.h include/db0err.h
include/dict0boot.h include/dict0boot.h
include/dict0boot.ic
include/dict0crea.h include/dict0crea.h
include/dict0crea.ic include/dict0crea.ic
include/dict0defrag_bg.h include/dict0defrag_bg.h
......
...@@ -93,27 +93,16 @@ dict_hdr_get_new_id( ...@@ -93,27 +93,16 @@ dict_hdr_get_new_id(
mtr.commit(); mtr.commit();
} }
/**********************************************************************//** /** Update dict_sys.row_id in the dictionary header file page. */
Writes the current value of the row id counter to the dictionary header file void dict_hdr_flush_row_id(row_id_t id)
page. */
void
dict_hdr_flush_row_id(void)
/*=======================*/
{ {
row_id_t id; mtr_t mtr;
mtr_t mtr; mtr.start();
buf_block_t* d= dict_hdr_get(&mtr);
ut_ad(mutex_own(&dict_sys.mutex)); byte *row_id= DICT_HDR + DICT_HDR_ROW_ID + d->frame;
if (mach_read_from_8(row_id) < id)
id = dict_sys.row_id; mtr.write<8>(*d, row_id, id);
mtr.commit();
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();
} }
/*****************************************************************//** /*****************************************************************//**
...@@ -270,9 +259,7 @@ dict_boot(void) ...@@ -270,9 +259,7 @@ dict_boot(void)
..._MARGIN, it will immediately be updated to the disk-based ..._MARGIN, it will immediately be updated to the disk-based
header. */ header. */
dict_sys.row_id = DICT_HDR_ROW_ID_WRITE_MARGIN dict_sys.recover_row_id(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID));
+ ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID),
DICT_HDR_ROW_ID_WRITE_MARGIN);
if (ulint max_space_id = mach_read_from_4(dict_hdr if (ulint max_space_id = mach_read_from_4(dict_hdr
+ DICT_HDR_MAX_SPACE_ID)) { + DICT_HDR_MAX_SPACE_ID)) {
max_space_id--; max_space_id--;
......
...@@ -46,27 +46,39 @@ dict_hdr_get_new_id( ...@@ -46,27 +46,39 @@ dict_hdr_get_new_id(
(not assigned if NULL) */ (not assigned if NULL) */
ulint* space_id); /*!< out: space id ulint* space_id); /*!< out: space id
(not assigned if NULL) */ (not assigned if NULL) */
/**********************************************************************//** /** Update dict_sys.row_id in the dictionary header file page. */
Writes the current value of the row id counter to the dictionary header file void dict_hdr_flush_row_id(row_id_t id);
page. */ /** @return A new value for GEN_CLUST_INDEX(DB_ROW_ID) */
void inline row_id_t dict_sys_t::get_new_row_id()
dict_hdr_flush_row_id(void); {
/*=======================*/ row_id_t id= row_id.fetch_add(1);
/**********************************************************************//** if (!(id % ROW_ID_WRITE_MARGIN))
Returns a new row id. dict_hdr_flush_row_id(id);
@return the new id */ return id;
UNIV_INLINE }
row_id_t
dict_sys_get_new_row_id(void); /** 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. */ Writes a row id to a record or other 6-byte stored form. */
UNIV_INLINE inline void dict_sys_write_row_id(byte *field, row_id_t row_id)
void {
dict_sys_write_row_id( static_assert(DATA_ROW_ID_LEN == 6, "compatibility");
/*==================*/ mach_write_to_6(field, row_id);
byte* field, /*!< in: record field */ }
row_id_t row_id);/*!< in: row id */
/*****************************************************************//** /*****************************************************************//**
Initializes the data dictionary memory structures when the database is Initializes the data dictionary memory structures when the database is
started. This function is also called when the data dictionary is created. started. This function is also called when the data dictionary is created.
...@@ -87,12 +99,7 @@ dict_create(void) ...@@ -87,12 +99,7 @@ dict_create(void)
/*********************************************************************//** /*********************************************************************//**
Check if a table id belongs to system table. Check if a table id belongs to system table.
@return true if the table id belongs to a system table. */ @return true if the table id belongs to a system table. */
UNIV_INLINE inline bool dict_is_sys_table(table_id_t id) { return id < DICT_HDR_FIRST_ID; }
bool
dict_is_sys_table(
/*==============*/
table_id_t id) /*!< in: table id to check */
MY_ATTRIBUTE((warn_unused_result));
/* Space id and page no where the dictionary header resides */ /* Space id and page no where the dictionary header resides */
#define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */ #define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
...@@ -289,11 +296,4 @@ length of thos fields. */ ...@@ -289,11 +296,4 @@ length of thos fields. */
#define DICT_FLD_LEN_SPACE 4 #define DICT_FLD_LEN_SPACE 4
#define DICT_FLD_LEN_FLAGS 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 #endif
/*****************************************************************************
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);
}
...@@ -1416,12 +1416,6 @@ class dict_sys_t ...@@ -1416,12 +1416,6 @@ class dict_sys_t
and DROP TABLE, as well as reading and DROP TABLE, as well as reading
the dictionary data for a table from the dictionary data for a table from
system tables */ 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 hash_table_t table_hash; /*!< hash table of the tables, based
on name */ on name */
/** hash table of persistent table IDs */ /** hash table of persistent table IDs */
...@@ -1439,14 +1433,31 @@ class dict_sys_t ...@@ -1439,14 +1433,31 @@ class dict_sys_t
UT_LIST_BASE_NODE_T(dict_table_t) UT_LIST_BASE_NODE_T(dict_table_t)
table_non_LRU; /*!< List of tables that can't be table_non_LRU; /*!< List of tables that can't be
evicted from the cache */ evicted from the cache */
private: private:
bool m_initialised= false; bool m_initialised= false;
/** the sequence of temporary table IDs */ /** the sequence of temporary table IDs */
std::atomic<table_id_t> temp_table_id{DICT_HDR_FIRST_ID}; std::atomic<table_id_t> temp_table_id{DICT_HDR_FIRST_ID};
/** hash table of temporary table IDs */
/** hash table of temporary table IDs */ hash_table_t temp_id_hash;
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: 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 */ /** @return a new temporary table ID */
table_id_t get_temporary_table_id() { table_id_t get_temporary_table_id() {
return temp_table_id.fetch_add(1, std::memory_order_relaxed); return temp_table_id.fetch_add(1, std::memory_order_relaxed);
......
...@@ -2396,15 +2396,7 @@ row_import_set_sys_max_row_id( ...@@ -2396,15 +2396,7 @@ row_import_set_sys_max_row_id(
if (row_id) { if (row_id) {
/* Update the system row id if the imported index row id is /* Update the system row id if the imported index row id is
greater than the max system row id. */ greater than the max system row id. */
dict_sys.update_row_id(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);
} }
} }
......
...@@ -3501,22 +3501,9 @@ row_ins_alloc_row_id_step( ...@@ -3501,22 +3501,9 @@ row_ins_alloc_row_id_step(
/*======================*/ /*======================*/
ins_node_t* node) /*!< in: row insert node */ ins_node_t* node) /*!< in: row insert node */
{ {
row_id_t row_id; ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
if (dict_table_get_first_index(node->table)->is_gen_clust())
ut_ad(node->state == INS_NODE_ALLOC_ROW_ID); dict_sys_write_row_id(node->sys_buf, dict_sys.get_new_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);
} }
/***********************************************************//** /***********************************************************//**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment