From 1ed09cfdcbb66807d2e3804884545b405f0f7ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 28 Feb 2025 08:55:16 +0200 Subject: [PATCH] MDEV-35000 preparation: Clean up dict_table_t::stat innodb_stats_transient_sample_pages, innodb_stats_persistent_sample_pages: Change the type to UNSIGNED, because the number of pages in a table is limited to 32 bits by the InnoDB file format. btr_get_size_and_reserved(), fseg_get_n_frag_pages(), fseg_n_reserved_pages_low(), fseg_n_reserved_pages(): Return uint32_t. The file format limits page numbers to 32 bits. dict_table_t::stat: An Atomic_relaxed that combines a number of metadata fields. innodb_copy_stat_flags(): Copy the statistics flags from TABLE_SHARE or HA_CREATE_INFO. dict_table_t::stats_initialized(), dict_table_t::stats_is_persistent(): Accessors to dict_table_t::stat. Reviewed by: Thirunarayanan Balathandayuthapani --- .../suite/sys_vars/r/sysvars_innodb.result | 8 +- storage/innobase/dict/dict0defrag_bg.cc | 24 ++-- storage/innobase/dict/dict0dict.cc | 5 +- storage/innobase/dict/dict0stats.cc | 88 ++++++------ storage/innobase/dict/dict0stats_bg.cc | 14 +- storage/innobase/fsp/fsp0fsp.cc | 33 ++--- storage/innobase/handler/ha_innodb.cc | 123 ++++++++--------- storage/innobase/handler/handler0alter.cc | 5 +- storage/innobase/handler/i_s.cc | 4 +- storage/innobase/ibuf/ibuf0ibuf.cc | 29 ++-- storage/innobase/include/dict0dict.h | 2 +- storage/innobase/include/dict0mem.h | 94 +++++++------ storage/innobase/include/dict0stats.h | 38 ------ storage/innobase/include/dict0stats.inl | 125 +----------------- storage/innobase/include/fsp0fsp.h | 6 +- storage/innobase/include/ibuf0ibuf.h | 10 +- storage/innobase/include/srv0srv.h | 4 +- storage/innobase/row/row0mysql.cc | 2 +- storage/innobase/row/row0purge.cc | 2 +- storage/innobase/row/row0uins.cc | 2 +- storage/innobase/row/row0umod.cc | 2 +- storage/innobase/srv/srv0srv.cc | 4 +- 22 files changed, 226 insertions(+), 398 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 2d8e1573db8..a82eab33313 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1571,10 +1571,10 @@ VARIABLE_NAME INNODB_STATS_PERSISTENT_SAMPLE_PAGES SESSION_VALUE NULL DEFAULT_VALUE 20 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of leaf index pages to sample when calculating persistent statistics (by ANALYZE, default 20) NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO @@ -1595,10 +1595,10 @@ VARIABLE_NAME INNODB_STATS_TRANSIENT_SAMPLE_PAGES SESSION_VALUE NULL DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of leaf index pages to sample when calculating transient statistics (if persistent statistics are not used, default 8) NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc index bec6da8e6af..81b8dbf077d 100644 --- a/storage/innobase/dict/dict0defrag_bg.cc +++ b/storage/innobase/dict/dict0defrag_bg.cc @@ -284,18 +284,18 @@ release_and_exit: /**************************************************************//** Gets the number of reserved and used pages in a B-tree. -@return number of pages reserved, or ULINT_UNDEFINED if the index -is unavailable */ +@return number of pages reserved +@retval 0 if the index is unavailable */ static -ulint +uint32_t btr_get_size_and_reserved( dict_index_t* index, /*!< in: index */ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ - ulint* used, /*!< out: number of pages used (<= reserved) */ + uint32_t* used, /*!< out: number of pages used (<= reserved) */ mtr_t* mtr) /*!< in/out: mini-transaction where index is s-latched */ { - ulint dummy; + uint32_t dummy; ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); ut_a(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE); @@ -304,19 +304,19 @@ btr_get_size_and_reserved( || dict_index_is_online_ddl(index) || !index->is_committed() || !index->table->space) { - return(ULINT_UNDEFINED); + return 0; } dberr_t err; buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr, &err); *used = 0; if (!root) { - return ULINT_UNDEFINED; + return 0; } mtr->x_lock_space(index->table->space); - ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF + auto n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF + root->page.frame, used, mtr); if (flag == BTR_TOTAL_SIZE) { n += fseg_n_reserved_pages(*root, @@ -343,14 +343,14 @@ dict_stats_save_defrag_stats( const time_t now= time(nullptr); mtr_t mtr; - ulint n_leaf_pages; + uint32_t n_leaf_pages; mtr.start(); mtr_sx_lock_index(index, &mtr); - ulint n_leaf_reserved= btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES, - &n_leaf_pages, &mtr); + uint32_t n_leaf_reserved= btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES, + &n_leaf_pages, &mtr); mtr.commit(); - if (n_leaf_reserved == ULINT_UNDEFINED) + if (!n_leaf_reserved) return DB_SUCCESS; THD *thd= current_thd; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 2e6a6d896e1..38e95282f26 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -198,8 +198,7 @@ dict_tables_have_same_db( /** Decrement the count of open handles */ void dict_table_close(dict_table_t *table) { - if (table->get_ref_count() == 1 && - dict_stats_is_persistent_enabled(table) && + if (table->get_ref_count() == 1 && table->stats_is_persistent() && strchr(table->name.m_name, '/')) { /* It looks like we are closing the last handle. The user could @@ -238,7 +237,7 @@ dict_table_close( dict_table_close(table); else { - if (table->release() && dict_stats_is_persistent_enabled(table) && + if (table->release() && table->stats_is_persistent() && strchr(table->name.m_name, '/')) { /* Force persistent stats re-read upon next open of the table so diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 34c2306feb5..b9bb3645dd5 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -599,7 +599,7 @@ void dict_stats_empty_table( table->stat_clustered_index_size = 1; /* 1 page for each index, not counting the clustered */ table->stat_sum_of_other_index_sizes - = UT_LIST_GET_LEN(table->indexes) - 1; + = uint32_t(UT_LIST_GET_LEN(table->indexes) - 1); table->stat_modified_counter = 0; dict_index_t* index; @@ -617,7 +617,7 @@ void dict_stats_empty_table( dict_stats_empty_index(index, empty_defrag_stats); } - table->stat_initialized = TRUE; + table->stat = table->stat | dict_table_t::STATS_INITIALIZED; table->stats_mutex_unlock(); } @@ -658,16 +658,10 @@ dict_stats_assert_initialized( /*==========================*/ const dict_table_t* table) /*!< in: table */ { - ut_a(table->stat_initialized); - MEM_CHECK_DEFINED(&table->stats_last_recalc, sizeof table->stats_last_recalc); - MEM_CHECK_DEFINED(&table->stat_persistent, - sizeof table->stat_persistent); - - MEM_CHECK_DEFINED(&table->stats_auto_recalc, - sizeof table->stats_auto_recalc); + MEM_CHECK_DEFINED(&table->stat, sizeof table->stat); MEM_CHECK_DEFINED(&table->stats_sample_pages, sizeof table->stats_sample_pages); @@ -844,8 +838,8 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index, ulint n_cols; ib_uint64_t* n_diff; ib_uint64_t* n_not_null; - ibool stats_null_not_equal; - uintmax_t n_sample_pages=1; /* number of pages to sample */ + bool stats_null_not_equal; + uint32_t n_sample_pages=1; /* number of pages to sample */ ulint not_empty_flag = 0; ulint total_external_size = 0; uintmax_t add_on; @@ -883,11 +877,11 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index, case SRV_STATS_NULLS_UNEQUAL: /* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL case, we will treat NULLs as unequal value */ - stats_null_not_equal = TRUE; + stats_null_not_equal = true; break; case SRV_STATS_NULLS_EQUAL: - stats_null_not_equal = FALSE; + stats_null_not_equal = false; break; default: @@ -938,19 +932,21 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index, so taking all case2 paths is I, our expression is: n_pages = S < I? min(I,L) : I - */ - if (index->stat_index_size > 1) { - n_sample_pages = (srv_stats_transient_sample_pages < index->stat_index_size) - ? ut_min(index->stat_index_size, - static_cast( - log2(double(index->stat_index_size)) - * double(srv_stats_transient_sample_pages))) - : index->stat_index_size; + */ + if (uint32_t I = index->stat_index_size) { + const uint32_t S{srv_stats_transient_sample_pages}; + n_sample_pages = S < I + ? std::min(I, + uint32_t(log2(double(I)) + * double(S))) + : I; } } /* Sanity check */ - ut_ad(n_sample_pages > 0 && n_sample_pages <= (index->stat_index_size <= 1 ? 1 : index->stat_index_size)); + ut_ad(n_sample_pages); + ut_ad(n_sample_pages <= (index->stat_index_size <= 1 + ? 1 : index->stat_index_size)); /* We sample some pages in the index to get an estimate */ btr_cur_t cursor; @@ -1169,7 +1165,7 @@ invalid: mtr.x_lock_space(index->table->space); - ulint dummy, size; + uint32_t dummy, size; index->stat_index_size = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF @@ -1226,7 +1222,7 @@ dict_stats_update_transient( ut_ad(!table->stats_mutex_is_owner()); dict_index_t* index; - ulint sum_of_index_sizes = 0; + uint32_t sum_of_index_sizes = 0; dberr_t err = DB_SUCCESS; /* Find out the sizes of the indexes and how many different values @@ -1285,7 +1281,7 @@ empty_table: table->stat_modified_counter = 0; - table->stat_initialized = TRUE; + table->stat = table->stat | dict_table_t::STATS_INITIALIZED; table->stats_mutex_unlock(); @@ -2225,8 +2221,8 @@ dict_stats_analyze_index_for_n_prefix( struct index_stats_t { std::vector stats; - ulint index_size; - ulint n_leaf_pages; + uint32_t index_size; + uint32_t n_leaf_pages; index_stats_t(ulint n_uniq) : index_size(1), n_leaf_pages(1) { @@ -2365,7 +2361,7 @@ empty_index: uint16_t root_level = btr_page_get_level(root->page.frame); mtr.x_lock_space(index->table->space); - ulint dummy, size; + uint32_t dummy, size; result.index_size = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF + root->page.frame, &size, &mtr) @@ -2742,7 +2738,7 @@ dict_stats_update_persistent( table->stat_modified_counter = 0; - table->stat_initialized = TRUE; + table->stat = table->stat | dict_table_t::STATS_INITIALIZED; dict_stats_assert_initialized(table); @@ -3164,8 +3160,7 @@ dict_stats_fetch_table_stats_step( ut_a(len == 8); table->stat_clustered_index_size - = std::max( - (ulint) mach_read_from_8(data), 1); + = std::max(mach_read_from_4(data + 4), 1U); break; } @@ -3174,18 +3169,9 @@ dict_stats_fetch_table_stats_step( ut_a(dtype_get_mtype(type) == DATA_INT); ut_a(len == 8); - ulint stat_other_idx_size - = (ulint) mach_read_from_8(data); - if (!stat_other_idx_size - && UT_LIST_GET_LEN(table->indexes) > 1) { - stat_other_idx_size - = UT_LIST_GET_LEN(table->indexes) - 1; - } - table->stat_sum_of_other_index_sizes - = std::max( - (ulint) mach_read_from_8(data), - UT_LIST_GET_LEN(table->indexes) - 1); - + table->stat_sum_of_other_index_sizes = std::max( + mach_read_from_4(data + 4), + uint32_t(UT_LIST_GET_LEN(table->indexes) - 1)); break; } default: @@ -3370,14 +3356,12 @@ dict_stats_fetch_index_stats_step( if (stat_name_len == 4 /* strlen("size") */ && strncasecmp("size", stat_name, stat_name_len) == 0) { - index->stat_index_size - = std::max((ulint) stat_value, 1); + index->stat_index_size = std::max(uint32_t(stat_value), 1U); arg->stats_were_modified = true; } else if (stat_name_len == 12 /* strlen("n_leaf_pages") */ && strncasecmp("n_leaf_pages", stat_name, stat_name_len) == 0) { - index->stat_n_leaf_pages - = std::max((ulint) stat_value, 1); + index->stat_n_leaf_pages = std::max(uint32_t(stat_value), 1U); arg->stats_were_modified = true; } else if (stat_name_len == 12 /* strlen("n_page_split") */ && strncasecmp("n_page_split", stat_name, stat_name_len) @@ -3648,7 +3632,9 @@ dict_stats_update_for_index( { DBUG_ENTER("dict_stats_update_for_index"); - if (dict_stats_is_persistent_enabled(index->table)) { + ut_ad(index->table->stat_initialized()); + + if (index->table->stats_is_persistent()) { if (dict_stats_persistent_storage_check(false)) { index_stats_t stats = dict_stats_analyze_index(index); @@ -3789,7 +3775,7 @@ dict_stats_update( /* If table is using persistent stats, then save the stats on disk */ - if (dict_stats_is_persistent_enabled(table)) { + if (table->stats_is_persistent()) { if (dict_stats_persistent_storage_check(false)) { @@ -3806,7 +3792,7 @@ dict_stats_update( /* fetch requested, either fetch from persistent statistics storage or use the old method */ - if (table->stat_initialized) { + if (table->stat_initialized()) { return(DB_SUCCESS); } @@ -3850,7 +3836,7 @@ dict_stats_update( goto transient; } #endif - if (dict_stats_auto_recalc_is_enabled(table)) { + if (table->stats_is_auto_recalc()) { return(dict_stats_update( table, DICT_STATS_RECALC_PERSISTENT)); diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index b0c34dc6d30..e44e97e2b8e 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -135,7 +135,9 @@ schedule new estimates for table and index statistics to be calculated. void dict_stats_update_if_needed_func(dict_table_t *table) #endif { - if (UNIV_UNLIKELY(!table->stat_initialized)) { + uint32_t stat{table->stat}; + + if (UNIV_UNLIKELY(!table->stat_initialized(stat))) { /* The table may have been evicted from dict_sys and reloaded internally by InnoDB for FOREIGN KEY processing, but not reloaded by the SQL layer. @@ -154,13 +156,9 @@ void dict_stats_update_if_needed_func(dict_table_t *table) ulonglong counter = table->stat_modified_counter++; ulonglong n_rows = dict_table_get_n_rows(table); - if (dict_stats_is_persistent_enabled(table)) { - if (table->name.is_temporary()) { - return; - } - if (counter > n_rows / 10 /* 10% */ - && dict_stats_auto_recalc_is_enabled(table)) { - + if (table->stats_is_persistent(stat)) { + if (table->stats_is_auto_recalc(stat) + && counter > n_rows / 10 && !table->name.is_temporary()) { #ifdef WITH_WSREP /* Do not add table to background statistic calculation if this thread is not a diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 677e9b68662..0fb03a0cd41 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1644,12 +1644,11 @@ fseg_find_last_used_frag_page_slot( /** Calculate reserved fragment page slots. @param inode file segment index @return number of fragment pages */ -static ulint fseg_get_n_frag_pages(const fseg_inode_t *inode) +static uint32_t fseg_get_n_frag_pages(const fseg_inode_t *inode) noexcept { - ulint i; - ulint count = 0; + uint32_t count = 0; - for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { + for (ulint i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i)) { count++; } @@ -1794,21 +1793,24 @@ Calculates the number of pages reserved by a segment, and how many pages are currently used. @return number of reserved pages */ static -ulint +uint32_t fseg_n_reserved_pages_low( /*======================*/ const fseg_inode_t* inode, /*!< in: segment inode */ - ulint* used) /*!< out: number of pages used (not + uint32_t* used) /*!< out: number of pages used (not more than reserved) */ + noexcept { + const uint32_t extent_size = FSP_EXTENT_SIZE; + *used = mach_read_from_4(inode + FSEG_NOT_FULL_N_USED) - + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL) + + extent_size * flst_get_len(inode + FSEG_FULL) + fseg_get_n_frag_pages(inode); return fseg_get_n_frag_pages(inode) - + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FREE) - + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_NOT_FULL) - + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL); + + extent_size * flst_get_len(inode + FSEG_FREE) + + extent_size * flst_get_len(inode + FSEG_NOT_FULL) + + extent_size * flst_get_len(inode + FSEG_FULL); } /** Calculate the number of pages reserved by a segment, @@ -1818,9 +1820,9 @@ and how many pages are currently used. @param[out] used number of pages that are used (not more than reserved) @param[in,out] mtr mini-transaction @return number of reserved pages */ -ulint fseg_n_reserved_pages(const buf_block_t &block, - const fseg_header_t *header, ulint *used, - mtr_t *mtr) +uint32_t fseg_n_reserved_pages(const buf_block_t &block, + const fseg_header_t *header, uint32_t *used, + mtr_t *mtr) noexcept { ut_ad(page_align(header) == block.page.frame); buf_block_t *iblock; @@ -1845,7 +1847,7 @@ static dberr_t fseg_fill_free_list(const fseg_inode_t *inode, buf_block_t *iblock, fil_space_t *space, uint32_t hint, mtr_t *mtr) { - ulint used; + uint32_t used; ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_d(space->modify_check(*mtr)); @@ -1996,8 +1998,7 @@ fseg_alloc_free_page_low( dberr_t* err) { ib_id_t seg_id; - ulint used; - ulint reserved; + uint32_t used, reserved; xdes_t* descr; /*!< extent of the hinted page */ uint32_t ret_page; /*!< the allocated page offset, FIL_NULL if could not be allocated */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7e9439a760c..faec1410236 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1622,7 +1622,7 @@ inline void ha_innobase::reload_statistics() if (table->is_readable()) dict_stats_init(table); else - table->stat_initialized= 1; + table->stat.fetch_or(dict_table_t::STATS_INITIALIZED); } } @@ -2978,6 +2978,44 @@ static int innobase_rollback_by_xid(handlerton*, XID *xid) noexcept return XAER_NOTA; } +/** Initialize the InnoDB persistent statistics attributes. +@param table InnoDB table +@param table_options MariaDB table options +@param sar the value of STATS_AUTO_RECALC +@param initialized whether the InnoDB statistics were already initialized +@return whether table->stats_sample_pages needs to be initialized */ +static bool innodb_copy_stat_flags(dict_table_t *table, + ulong table_options, + enum_stats_auto_recalc sar, + bool initialized) noexcept +{ + if (table->is_temporary() || table->no_rollback()) + { + table->stat= dict_table_t::STATS_INITIALIZED | + dict_table_t::STATS_PERSISTENT_OFF | dict_table_t::STATS_AUTO_RECALC_OFF; + table->stats_sample_pages= 1; + return false; + } + + static_assert(HA_OPTION_STATS_PERSISTENT == + dict_table_t::STATS_PERSISTENT_ON << 11, ""); + static_assert(HA_OPTION_NO_STATS_PERSISTENT == + dict_table_t::STATS_PERSISTENT_OFF << 11, ""); + uint32_t stat= + (table_options & + (HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) >> 11; + static_assert(uint32_t{HA_STATS_AUTO_RECALC_ON} << 3 == + dict_table_t::STATS_AUTO_RECALC_ON, ""); + static_assert(uint32_t{HA_STATS_AUTO_RECALC_OFF} << 3 == + dict_table_t::STATS_AUTO_RECALC_OFF, ""); + static_assert(true == dict_table_t::STATS_INITIALIZED, ""); + stat|= (sar & (HA_STATS_AUTO_RECALC_ON | HA_STATS_AUTO_RECALC_OFF)) << 3 | + initialized; + + table->stat= stat; + return true; +} + /*********************************************************************//** Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object. Those flags are stored in .frm file and end up in the MySQL table object, @@ -2990,29 +3028,9 @@ innobase_copy_frm_flags_from_create_info( dict_table_t* innodb_table, /*!< in/out: InnoDB table */ const HA_CREATE_INFO* create_info) /*!< in: create info */ { - ibool ps_on; - ibool ps_off; - - if (innodb_table->is_temporary() - || innodb_table->no_rollback()) { - /* Temp tables do not use persistent stats. */ - ps_on = FALSE; - ps_off = TRUE; - } else { - ps_on = create_info->table_options - & HA_OPTION_STATS_PERSISTENT; - ps_off = create_info->table_options - & HA_OPTION_NO_STATS_PERSISTENT; - } - - dict_stats_set_persistent(innodb_table, ps_on, ps_off); - - dict_stats_auto_recalc_set( - innodb_table, - create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, - create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); - - innodb_table->stats_sample_pages = create_info->stats_sample_pages; + if (innodb_copy_stat_flags(innodb_table, create_info->table_options, + create_info->stats_auto_recalc, false)) + innodb_table->stats_sample_pages= create_info->stats_sample_pages; } /*********************************************************************//** @@ -3026,28 +3044,10 @@ innobase_copy_frm_flags_from_table_share( dict_table_t* innodb_table, /*!< in/out: InnoDB table */ const TABLE_SHARE* table_share) /*!< in: table share */ { - ibool ps_on; - ibool ps_off; - - if (innodb_table->is_temporary()) { - /* Temp tables do not use persistent stats */ - ps_on = FALSE; - ps_off = TRUE; - } else { - ps_on = table_share->db_create_options - & HA_OPTION_STATS_PERSISTENT; - ps_off = table_share->db_create_options - & HA_OPTION_NO_STATS_PERSISTENT; - } - - dict_stats_set_persistent(innodb_table, ps_on, ps_off); - - dict_stats_auto_recalc_set( - innodb_table, - table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, - table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); - - innodb_table->stats_sample_pages = table_share->stats_sample_pages; + if (innodb_copy_stat_flags(innodb_table, table_share->db_create_options, + table_share->stats_auto_recalc, + innodb_table->stat_initialized())) + innodb_table->stats_sample_pages= table_share->stats_sample_pages; } /*********************************************************************//** @@ -13387,6 +13387,8 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE); } + ut_ad(m_prebuilt->table->stat_initialized()); + if (m_prebuilt->table->space == fil_system.sys_space) { ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, @@ -13460,7 +13462,7 @@ ha_innobase::discard_or_import_tablespace( err, m_prebuilt->table->flags, NULL)); } - if (dict_stats_is_persistent_enabled(m_prebuilt->table)) { + if (m_prebuilt->table->stats_is_persistent()) { dberr_t ret; /* Adjust the persistent statistics. */ @@ -13645,7 +13647,7 @@ int ha_innobase::delete_table(const char *name) /* This looks like the rollback of ALTER TABLE...ADD PARTITION that was caused by MDL timeout. We could have written undo log for inserting the data into the new partitions. */ - if (table->stat_persistent != DICT_STATS_PERSISTENT_OFF) + if (!(table->stat & dict_table_t::STATS_PERSISTENT_OFF)) { /* We do not really know if we are holding MDL_EXCLUSIVE. Even though this code is handling the case that we are not holding @@ -13660,7 +13662,7 @@ int ha_innobase::delete_table(const char *name) DEBUG_SYNC(thd, "before_delete_table_stats"); - if (err == DB_SUCCESS && dict_stats_is_persistent_enabled(table) && + if (err == DB_SUCCESS && table->stats_is_persistent() && !table->is_stats_table()) { table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, @@ -14033,7 +14035,7 @@ int ha_innobase::truncate() std::this_thread::sleep_for(std::chrono::milliseconds(50)); } - if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) && + if (error == DB_SUCCESS && ib_table->stats_is_persistent() && !ib_table->is_stats_table()) { table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, @@ -14529,7 +14531,7 @@ ha_innobase::scan_time() ulint stat_clustered_index_size; - ut_a(m_prebuilt->table->stat_initialized); + ut_ad(m_prebuilt->table->stat_initialized()); stat_clustered_index_size = m_prebuilt->table->stat_clustered_index_size; @@ -14656,7 +14658,7 @@ innodb_rec_per_key( rec_per_key_t rec_per_key; ib_uint64_t n_diff; - ut_a(index->table->stat_initialized); + ut_ad(index->table->stat_initialized()); ut_ad(i < dict_index_get_n_unique(index)); ut_ad(!dict_index_is_spatial(index)); @@ -14806,7 +14808,7 @@ ha_innobase::info_low( m_prebuilt->trx->op_info = "updating table statistics"; - if (dict_stats_is_persistent_enabled(ib_table)) { + if (ib_table->stats_is_persistent()) { if (is_analyze) { if (!srv_read_only_mode) { dict_stats_recalc_pool_del( @@ -14844,7 +14846,7 @@ ha_innobase::info_low( ulint stat_clustered_index_size; ulint stat_sum_of_other_index_sizes; - ut_a(ib_table->stat_initialized); + ut_ad(ib_table->stat_initialized()); #if !defined NO_ELISION && !defined SUX_LOCK_GENERIC if (xbegin()) { @@ -14998,7 +15000,7 @@ ha_innobase::info_low( auto _ = make_scope_exit([ib_table]() { ib_table->stats_shared_unlock(); }); - ut_a(ib_table->stat_initialized); + ut_ad(ib_table->stat_initialized()); for (uint i = 0; i < table->s->keys; i++) { ulong j; @@ -15925,8 +15927,7 @@ ha_innobase::extra( /* During copy alter operation, InnoDB updates the stats only for non-persistent tables. */ - if (!dict_stats_is_persistent_enabled( - m_prebuilt->table)) { + if (!m_prebuilt->table->stats_is_persistent()) { dict_stats_update_if_needed( m_prebuilt->table, *trx); } @@ -19156,12 +19157,12 @@ static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata, " SHOW TABLE STATUS for tables that use transient statistics (off by default)", NULL, NULL, FALSE); -static MYSQL_SYSVAR_ULONGLONG(stats_transient_sample_pages, +static MYSQL_SYSVAR_UINT(stats_transient_sample_pages, srv_stats_transient_sample_pages, PLUGIN_VAR_RQCMDARG, "The number of leaf index pages to sample when calculating transient" " statistics (if persistent statistics are not used, default 8)", - NULL, NULL, 8, 1, ~0ULL, 0); + NULL, NULL, 8, 1, ~0U, 0); static MYSQL_SYSVAR_BOOL(stats_persistent, srv_stats_persistent, PLUGIN_VAR_OPCMDARG, @@ -19177,12 +19178,12 @@ static MYSQL_SYSVAR_BOOL(stats_auto_recalc, srv_stats_auto_recalc, " new statistics)", NULL, NULL, TRUE); -static MYSQL_SYSVAR_ULONGLONG(stats_persistent_sample_pages, +static MYSQL_SYSVAR_UINT(stats_persistent_sample_pages, srv_stats_persistent_sample_pages, PLUGIN_VAR_RQCMDARG, "The number of leaf index pages to sample when calculating persistent" " statistics (by ANALYZE, default 20)", - NULL, NULL, 20, 1, ~0ULL, 0); + NULL, NULL, 20, 1, ~0U, 0); static MYSQL_SYSVAR_ULONGLONG(stats_modified_counter, srv_stats_modified_counter, PLUGIN_VAR_RQCMDARG, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 798c90133d3..b808c74b262 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -11180,7 +11180,7 @@ alter_stats_norebuild( DBUG_ENTER("alter_stats_norebuild"); DBUG_ASSERT(!ctx->need_rebuild()); - if (!dict_stats_is_persistent_enabled(ctx->new_table)) { + if (!ctx->new_table->stats_is_persistent()) { DBUG_VOID_RETURN; } @@ -11214,8 +11214,7 @@ alter_stats_rebuild( { DBUG_ENTER("alter_stats_rebuild"); - if (!table->space - || !dict_stats_is_persistent_enabled(table)) { + if (!table->space || !table->stats_is_persistent()) { DBUG_VOID_RETURN; } diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 0f00a0d39f9..6f0987f153e 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -4777,9 +4777,9 @@ i_s_dict_fill_sys_tablestats(THD* thd, dict_table_t *table, OK(field_store_string(fields[SYS_TABLESTATS_NAME], table->name.m_name)); - OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized, true)); + OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized(), true)); - if (table->stat_initialized) + if (table->stat_initialized()) { OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows, true)); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index d90527c0107..b594b86d1ea 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -375,7 +375,7 @@ ibuf_size_update( ibuf.free_list_len = flst_get_len(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST); - ibuf.height = 1 + btr_page_get_level(root); + ibuf.height = uint8_t(1 + btr_page_get_level(root)); /* the '1 +' is the ibuf header page */ ibuf.size = ibuf.seg_size - (1 + ibuf.free_list_len); @@ -443,18 +443,11 @@ err_exit: goto err_exit; } - /* At startup we intialize ibuf to have a maximum of - CHANGE_BUFFER_DEFAULT_SIZE in terms of percentage of the - buffer pool size. Once ibuf struct is initialized this - value is updated with the user supplied size by calling - ibuf_max_size_update(). */ - ibuf.max_size = ((buf_pool_get_curr_size() >> srv_page_size_shift) - * CHANGE_BUFFER_DEFAULT_SIZE) / 100; - mysql_mutex_init(ibuf_mutex_key, &ibuf_mutex, nullptr); mysql_mutex_init(ibuf_pessimistic_insert_mutex_key, &ibuf_pessimistic_insert_mutex, nullptr); + ibuf_max_size_update(CHANGE_BUFFER_DEFAULT_SIZE); mysql_mutex_lock(&ibuf_mutex); ibuf_size_update(root); mysql_mutex_unlock(&ibuf_mutex); @@ -506,10 +499,12 @@ ibuf_max_size_update( percentage of the buffer pool size */ { if (UNIV_UNLIKELY(!ibuf.index)) return; - ulint new_size = ((buf_pool_get_curr_size() >> srv_page_size_shift) - * new_val) / 100; + ulint new_size = std::min( + (buf_pool_get_curr_size() >> srv_page_size_shift) * new_val + / 100, uint32_t(~0U)); + mysql_mutex_lock(&ibuf_mutex); - ibuf.max_size = new_size; + ibuf.max_size = uint32_t(new_size); mysql_mutex_unlock(&ibuf_mutex); } @@ -4483,17 +4478,17 @@ ibuf_print( return; } - const ulint size= ibuf.size; - const ulint free_list_len= ibuf.free_list_len; - const ulint seg_size= ibuf.seg_size; + const uint32_t size= ibuf.size; + const uint32_t free_list_len= ibuf.free_list_len; + const uint32_t seg_size= ibuf.seg_size; mysql_mutex_unlock(&ibuf_mutex); fprintf(file, "-------------\n" "INSERT BUFFER\n" "-------------\n" - "size " ULINTPF ", free list len " ULINTPF "," - " seg size " ULINTPF ", " ULINTPF " merges\n", + "size %" PRIu32 ", free list len %" PRIu32 "," + " seg size %" PRIu32 ", " ULINTPF " merges\n", size, free_list_len, seg_size, ulint{ibuf.n_merges}); ibuf_print_ops("merged operations:\n", ibuf.n_merged_ops, file); ibuf_print_ops("discarded operations:\n", ibuf.n_discarded_ops, file); diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 97568c61997..842b9fec9cd 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -674,7 +674,7 @@ TPOOL_SUPPRESS_TSAN @return estimated number of rows */ inline uint64_t dict_table_get_n_rows(const dict_table_t *table) { - ut_ad(table->stat_initialized); + ut_ad(table->stat_initialized()); return table->stat_n_rows; } diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index ffc26510679..bec735537fc 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1106,10 +1106,10 @@ struct dict_index_t { is indexed from 0 to n_uniq-1); This is used when innodb_stats_method is "nulls_ignored". */ - ulint stat_index_size; + uint32_t stat_index_size; /*!< approximate index size in database pages */ - ulint stat_n_leaf_pages; + uint32_t stat_n_leaf_pages; /*!< approximate number of leaf pages in the index tree */ bool stats_error_printed; @@ -2358,63 +2358,32 @@ public: /** Statistics for query optimization. Mostly protected by dict_sys.latch and stats_mutex_lock(). @{ */ - /** TRUE if statistics have been calculated the first time after - database startup or table creation. */ - unsigned stat_initialized:1; - /** Timestamp of last recalc of the stats. */ time_t stats_last_recalc; - /** The two bits below are set in the 'stat_persistent' member. They - have the following meaning: - 1. _ON=0, _OFF=0, no explicit persistent stats setting for this table, - the value of the global srv_stats_persistent is used to determine - whether the table has persistent stats enabled or not - 2. _ON=0, _OFF=1, persistent stats are explicitly disabled for this - table, regardless of the value of the global srv_stats_persistent - 3. _ON=1, _OFF=0, persistent stats are explicitly enabled for this - table, regardless of the value of the global srv_stats_persistent - 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */ - #define DICT_STATS_PERSISTENT_ON (1 << 1) - #define DICT_STATS_PERSISTENT_OFF (1 << 2) + static constexpr uint32_t STATS_INITIALIZED= 1U; + static constexpr uint32_t STATS_PERSISTENT_ON= 1U << 1; + static constexpr uint32_t STATS_PERSISTENT_OFF= 1U << 2; + static constexpr uint32_t STATS_AUTO_RECALC_ON= 1U << 3; + static constexpr uint32_t STATS_AUTO_RECALC_OFF= 1U << 4; - /** Indicates whether the table uses persistent stats or not. See - DICT_STATS_PERSISTENT_ON and DICT_STATS_PERSISTENT_OFF. */ - ib_uint32_t stat_persistent; + /** flags for index cardinality statistics */ + Atomic_relaxed stat; + /** Approximate clustered index size in database pages. */ + uint32_t stat_clustered_index_size; + /** Approximate size of other indexes in database pages. */ + uint32_t stat_sum_of_other_index_sizes; - /** The two bits below are set in the 'stats_auto_recalc' member. They - have the following meaning: - 1. _ON=0, _OFF=0, no explicit auto recalc setting for this table, the - value of the global srv_stats_persistent_auto_recalc is used to - determine whether the table has auto recalc enabled or not - 2. _ON=0, _OFF=1, auto recalc is explicitly disabled for this table, - regardless of the value of the global srv_stats_persistent_auto_recalc - 3. _ON=1, _OFF=0, auto recalc is explicitly enabled for this table, - regardless of the value of the global srv_stats_persistent_auto_recalc - 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */ - #define DICT_STATS_AUTO_RECALC_ON (1 << 1) - #define DICT_STATS_AUTO_RECALC_OFF (1 << 2) - /** Indicates whether the table uses automatic recalc for persistent - stats or not. See DICT_STATS_AUTO_RECALC_ON and - DICT_STATS_AUTO_RECALC_OFF. */ - ib_uint32_t stats_auto_recalc; - - /** The number of pages to sample for this table during persistent - stats estimation. If this is 0, then the value of the global - srv_stats_persistent_sample_pages will be used instead. */ - ulint stats_sample_pages; + /** The number of pages to sample for this table during persistent + stats estimation. If this is 0, then the value of the global + srv_stats_persistent_sample_pages will be used instead. */ + uint32_t stats_sample_pages; /** Approximate number of rows in the table. We periodically calculate new estimates. */ ib_uint64_t stat_n_rows; - /** Approximate clustered index size in database pages. */ - ulint stat_clustered_index_size; - - /** Approximate size of other indexes in database pages. */ - ulint stat_sum_of_other_index_sizes; - /** How many rows are modified since last stats recalc. When a row is inserted, updated, or deleted, we add 1 to this number; we calculate new estimates for the table and the indexes if the table has changed @@ -2551,6 +2520,35 @@ public: /** @return the index for that starts with a specific column */ dict_index_t *get_index(const dict_col_t &col) const; + /** @return whether the statistics are initialized */ + static bool stat_initialized(uint32_t stat) noexcept + { return stat & STATS_INITIALIZED; } + + /** @return whether STATS_PERSISTENT is enabled */ + static bool stats_is_persistent(uint32_t stat) noexcept + { + ut_ad(~(stat & (STATS_PERSISTENT_ON | STATS_PERSISTENT_OFF))); + if (stat & STATS_PERSISTENT_ON) return true; + return !(stat & STATS_PERSISTENT_OFF) && srv_stats_persistent; + } + /** @return whether STATS_AUTO_RECALC is enabled */ + static bool stats_is_auto_recalc(uint32_t stat) noexcept + { + ut_ad(stat_initialized(stat)); + ut_ad(~(stat & (STATS_AUTO_RECALC_ON | STATS_AUTO_RECALC_OFF))); + if (stat & STATS_AUTO_RECALC_ON) return true; + return !(stat & STATS_AUTO_RECALC_OFF) && srv_stats_auto_recalc; + } + + /** @return whether the statistics are initialized */ + bool stat_initialized() const noexcept { return stat_initialized(stat); } + /** @return whether STATS_PERSISTENT is enabled */ + bool stats_is_persistent() const noexcept + { return stats_is_persistent(stat); } + /** @return whether STATS_AUTO_RECALC is enabled */ + bool stats_is_auto_recalc() const noexcept + { return stats_is_auto_recalc(stat); } + /** Create metadata. @param name table name @param space tablespace diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index 3b006daf53c..e1d9893dd0a 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -52,44 +52,6 @@ enum dict_stats_upd_option_t { 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's stats for the first time when opening a table. */ UNIV_INLINE diff --git a/storage/innobase/include/dict0stats.inl b/storage/innobase/include/dict0stats.inl index dd516275156..fa5b4cccf19 100644 --- a/storage/innobase/include/dict0stats.inl +++ b/storage/innobase/include/dict0stats.inl @@ -25,120 +25,6 @@ Created Jan 23, 2012 Vasil Dimov *******************************************************/ #include "dict0dict.h" -#include "srv0srv.h" - -/*********************************************************************//** -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 */ -{ - /* Not allowed to have both flags set, but a CREATE or ALTER - statement that contains "STATS_PERSISTENT=0 STATS_PERSISTENT=1" would - end up having both set. In this case we clear the OFF flag. */ - if (ps_on && ps_off) { - ps_off = FALSE; - } - - ib_uint32_t stat_persistent = 0; - - if (ps_on) { - stat_persistent |= DICT_STATS_PERSISTENT_ON; - } - - if (ps_off) { - stat_persistent |= DICT_STATS_PERSISTENT_OFF; - } - - /* we rely on this assignment to be atomic */ - table->stat_persistent = stat_persistent; -} - -/** @return whether persistent statistics is enabled for a given table */ -UNIV_INLINE -bool -dict_stats_is_persistent_enabled(const dict_table_t* table) -{ - /* Because of the nature of this check (non-locking) it is possible - that a table becomes: - * PS-disabled immediately after this function has returned TRUE or - * PS-enabled immediately after this function has returned FALSE. - This means that it is possible that we do: - + dict_stats_update(DICT_STATS_RECALC_PERSISTENT) on a table that has - just been PS-disabled or - + 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 - hold dict_sys.latch or stats_mutex_lock() like for accessing the - other ::stat_ members which would be too big performance penalty, - especially when this function is called from - dict_stats_update_if_needed(). */ - - /* we rely on this read to be atomic */ - ib_uint32_t stat_persistent = table->stat_persistent; - - if (stat_persistent & DICT_STATS_PERSISTENT_ON) { - ut_ad(!(stat_persistent & DICT_STATS_PERSISTENT_OFF)); - return(true); - } else if (stat_persistent & DICT_STATS_PERSISTENT_OFF) { - return(false); - } else { - return(srv_stats_persistent); - } -} - -/*********************************************************************//** -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 */ -{ - ut_ad(!auto_recalc_on || !auto_recalc_off); - - ib_uint32_t stats_auto_recalc = 0; - - if (auto_recalc_on) { - stats_auto_recalc |= DICT_STATS_AUTO_RECALC_ON; - } - - if (auto_recalc_off) { - stats_auto_recalc |= DICT_STATS_AUTO_RECALC_OFF; - } - - /* we rely on this assignment to be atomic */ - table->stats_auto_recalc = stats_auto_recalc; -} - -/** @return whether auto recalc is enabled for a given table*/ -UNIV_INLINE -bool -dict_stats_auto_recalc_is_enabled(const dict_table_t* table) -{ - /* we rely on this read to be atomic */ - ib_uint32_t stats_auto_recalc = table->stats_auto_recalc; - - if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_ON) { - ut_ad(!(stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF)); - return(true); - } else if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF) { - return(false); - } else { - return(srv_stats_auto_recalc); - } -} /*********************************************************************//** Initialize table's stats for the first time when opening a table. */ @@ -150,13 +36,15 @@ dict_stats_init( { ut_ad(!table->stats_mutex_is_owner()); - if (table->stat_initialized) { + uint32_t stat = table->stat; + + if (stat & dict_table_t::STATS_INITIALIZED) { return; } dict_stats_upd_option_t opt; - if (dict_stats_is_persistent_enabled(table)) { + if (table->stats_is_persistent(stat)) { opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY; } else { opt = DICT_STATS_RECALC_TRANSIENT; @@ -178,7 +66,7 @@ dict_stats_deinit( ut_ad(table->get_ref_count() == 0); #ifdef HAVE_valgrind - if (!table->stat_initialized) { + if (!table->stat_initialized()) { return; } @@ -215,5 +103,6 @@ dict_stats_deinit( sizeof(index->stat_n_leaf_pages)); } #endif /* HAVE_valgrind */ - table->stat_initialized = FALSE; + + table->stat = table->stat & ~dict_table_t::STATS_INITIALIZED; } diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 4b8dd20a224..fe8d5980ac4 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -355,9 +355,9 @@ and how many pages are currently used. @param[out] used number of pages that are used (not more than reserved) @param[in,out] mtr mini-transaction @return number of reserved pages */ -ulint fseg_n_reserved_pages(const buf_block_t &block, - const fseg_header_t *header, ulint *used, - mtr_t *mtr) +uint32_t fseg_n_reserved_pages(const buf_block_t &block, + const fseg_header_t *header, uint32_t *used, + mtr_t *mtr) noexcept MY_ATTRIBUTE((nonnull)); /**********************************************************************//** Allocates a single free page from a segment. This function implements diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index c246b2ef513..b00532f9a02 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -62,11 +62,11 @@ extern ulong innodb_change_buffering; /** Insert buffer struct */ struct ibuf_t{ - Atomic_relaxed size; /*!< current size of the ibuf index + Atomic_relaxed size; /*!< current size of the ibuf index tree, in pages */ - Atomic_relaxed max_size; /*!< recommended maximum size of the + Atomic_relaxed max_size;/*!< recommended maximum size of the ibuf index tree, in pages */ - ulint seg_size; /*!< allocated pages of the file + uint32_t seg_size; /*!< allocated pages of the file segment containing ibuf header and tree */ bool empty; /*!< Protected by the page @@ -75,8 +75,8 @@ struct ibuf_t{ (FSP_IBUF_TREE_ROOT_PAGE_NO). true if and only if the insert buffer tree is empty. */ - ulint free_list_len; /*!< length of the free list */ - ulint height; /*!< tree height */ + uint8_t height; /*!< tree height */ + uint32_t free_list_len; /*!< length of the free list */ dict_index_t* index; /*!< insert buffer index */ /** number of pages merged */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index bca858ca409..374b15f0d66 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -294,9 +294,9 @@ extern uint srv_fast_shutdown; extern ibool srv_innodb_status; -extern unsigned long long srv_stats_transient_sample_pages; +extern uint32_t srv_stats_transient_sample_pages; extern my_bool srv_stats_persistent; -extern unsigned long long srv_stats_persistent_sample_pages; +extern uint32_t srv_stats_persistent_sample_pages; extern my_bool srv_stats_auto_recalc; extern my_bool srv_stats_include_delete_marked; extern unsigned long long srv_stats_modified_counter; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4c8468dbc41..8b20d70fb15 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1599,7 +1599,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) ut_a(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); ut_a(prebuilt->magic_n2 == ROW_PREBUILT_ALLOCATED); ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); - ut_ad(table->stat_initialized); + ut_ad(table->stat_initialized()); if (!table->is_readable()) { return row_mysql_get_table_error(trx, table); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 442dd4f6e1d..547936e34c1 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1564,7 +1564,7 @@ row_purge_record_func( case TRX_UNDO_DEL_MARK_REC: purged = row_purge_del_mark(node); if (purged) { - if (node->table->stat_initialized + if (node->table->stat_initialized() && srv_stats_include_delete_marked) { dict_stats_update_if_needed( node->table, *thr->graph->trx); diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 23255cc98f9..b02cbec56ea 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -614,7 +614,7 @@ row_undo_ins( err = row_undo_ins_remove_clust_rec(node); } - if (err == DB_SUCCESS && node->table->stat_initialized) { + if (err == DB_SUCCESS && node->table->stat_initialized()) { /* Not protected by dict_sys.latch or table->stats_mutex_lock() for performance reasons, we would rather get garbage diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index d8a3b29b630..a1bc1df3dd2 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1388,7 +1388,7 @@ rollback_clust: bool update_statistics = !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); - if (err == DB_SUCCESS && node->table->stat_initialized) { + if (err == DB_SUCCESS && node->table->stat_initialized()) { switch (node->rec_type) { case TRX_UNDO_UPD_EXIST_REC: break; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index b3bdfef9c66..f73a95d5226 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -291,13 +291,13 @@ this many index pages, there are 2 ways to calculate statistics: in the innodb database. * quick transient stats, that are used if persistent stats for the given table/index are not found in the innodb database */ -unsigned long long srv_stats_transient_sample_pages; +uint32_t srv_stats_transient_sample_pages; /** innodb_stats_persistent */ my_bool srv_stats_persistent; /** innodb_stats_include_delete_marked */ my_bool srv_stats_include_delete_marked; /** innodb_stats_persistent_sample_pages */ -unsigned long long srv_stats_persistent_sample_pages; +uint32_t srv_stats_persistent_sample_pages; /** innodb_stats_auto_recalc */ my_bool srv_stats_auto_recalc;