diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result index 5db74a7163630..28282c71fd361 100644 --- a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result @@ -14,6 +14,15 @@ create table t1 (id int primary key, val int not null) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; SET STATEMENT foreign_key_checks=0, unique_checks=0 FOR INSERT INTO t1 SELECT seq*4,seq*4 FROM seq_1_to_262144; +SELECT @@GLOBAL.innodb_adaptive_hash_index; +@@GLOBAL.innodb_adaptive_hash_index +1 +SET STATEMENT max_statement_time=1e-9 FOR +SET GLOBAL innodb_buffer_pool_size = 7340032; +SELECT @@GLOBAL.innodb_adaptive_hash_index; +@@GLOBAL.innodb_adaptive_hash_index +1 +FOUND 1 /innodb_buffer_pool_size=7m.*resized from|innodb_buffer_pool_size change aborted/ in mysqld.1.err set global innodb_buffer_pool_size = 7340032; select count(val) from t1; count(val) diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_temporary.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_temporary.result index b34da91f2550d..08ecf2310ff27 100644 --- a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_temporary.result +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_temporary.result @@ -2,6 +2,16 @@ SET @save_limit=@@GLOBAL.innodb_limit_optimistic_insert_debug; SET @save_size=@@GLOBAL.innodb_buffer_pool_size; SET GLOBAL innodb_limit_optimistic_insert_debug=2; SET GLOBAL innodb_buffer_pool_size=16777216; +call mtr.add_suppression("innodb_buffer_pool_size change aborted"); +SET @old_innodb_adaptive_hash_index = @@innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index = ON; +SET STATEMENT debug_dbug='+d,buf_shrink_fail' FOR +SET GLOBAL innodb_buffer_pool_size=8388608; +ERROR HY000: innodb_buffer_pool_size change aborted +SELECT @@GLOBAL.innodb_adaptive_hash_index,@@GLOBAL.innodb_buffer_pool_size; +@@GLOBAL.innodb_adaptive_hash_index @@GLOBAL.innodb_buffer_pool_size +1 16777216 +SET GLOBAL innodb_adaptive_hash_index = @old_innodb_adaptive_hash_index; CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 SELECT seq FROM seq_1_to_200; SET GLOBAL innodb_max_purge_lag_wait=0; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test index 612a0c1be6432..43ad79a506ec0 100644 --- a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_sequence.inc +--source include/not_embedded.inc # there are no messages in mysqld.1.err --echo # --echo # MDEV-29445: Reorganize buffer pool (and remove chunks) @@ -37,6 +38,17 @@ INSERT INTO t1 SELECT seq*4,seq*4 FROM seq_1_to_262144; SET GLOBAL innodb_read_only_compressed=@save_innodb_read_only_compressed; --enable_query_log +SELECT @@GLOBAL.innodb_adaptive_hash_index; +--error 0,ER_WRONG_USAGE +SET STATEMENT max_statement_time=1e-9 FOR +SET GLOBAL innodb_buffer_pool_size = 7340032; +SELECT @@GLOBAL.innodb_adaptive_hash_index; + +--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN= InnoDB: Trying to shrink innodb_buffer_pool_size=7m +--let SEARCH_PATTERN= innodb_buffer_pool_size=7m.*resized from|innodb_buffer_pool_size change aborted +--source include/search_pattern_in_file.inc + # Attempt to shrink the buffer pool. This may occasionally fail. --error 0,ER_WRONG_USAGE set global innodb_buffer_pool_size = 7340032; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_temporary.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_temporary.test index 59afed2452159..35db56747e497 100644 --- a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_temporary.test +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_temporary.test @@ -8,6 +8,16 @@ SET @save_size=@@GLOBAL.innodb_buffer_pool_size; SET GLOBAL innodb_limit_optimistic_insert_debug=2; SET GLOBAL innodb_buffer_pool_size=16777216; +call mtr.add_suppression("innodb_buffer_pool_size change aborted"); + +SET @old_innodb_adaptive_hash_index = @@innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index = ON; +--error ER_WRONG_USAGE +SET STATEMENT debug_dbug='+d,buf_shrink_fail' FOR +SET GLOBAL innodb_buffer_pool_size=8388608; +SELECT @@GLOBAL.innodb_adaptive_hash_index,@@GLOBAL.innodb_buffer_pool_size; +SET GLOBAL innodb_adaptive_hash_index = @old_innodb_adaptive_hash_index; + CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 SELECT seq FROM seq_1_to_200; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 3fce60922b53a..21e763423ac7c 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1614,6 +1614,7 @@ ATTRIBUTE_COLD buf_pool_t::shrink_status buf_pool_t::shrink(size_t size) noexcept { mysql_mutex_assert_owner(&mutex); + DBUG_EXECUTE_IF("buf_shrink_fail", return SHRINK_ABORT;); buf_load_abort(); if (!n_blocks_to_withdraw) @@ -2014,25 +2015,12 @@ ATTRIBUTE_COLD void buf_pool_t::resize(size_t size, THD *thd) noexcept if (ahi_disabled) btr_search.enable(true); #endif - mysql_mutex_lock(&LOCK_global_system_variables); - bool resized= n_blocks_removed < 0; - if (n_blocks_removed > 0) - { - mysql_mutex_lock(&mutex); - resized= size_in_bytes == old_size; - if (resized) - { - size_in_bytes_requested= size; - size_in_bytes= size; - } - mysql_mutex_unlock(&mutex); - } - - if (resized) + if (n_blocks_removed) sql_print_information("InnoDB: innodb_buffer_pool_size=%zum (%zu pages)" " resized from %zum (%zu pages)", size >> 20, n_blocks_new, old_size >> 20, old_blocks); + mysql_mutex_lock(&LOCK_global_system_variables); } else { @@ -2090,11 +2078,28 @@ ATTRIBUTE_COLD void buf_pool_t::resize(size_t size, THD *thd) noexcept ut_d(b->in_free_list= true); ut_ad(b->state() == buf_page_t::NOT_USED); b->lock.init(); +#ifdef BTR_CUR_HASH_ADAPT + /* Clear the AHI fields, because buf_block_init_low() expects + these to be zeroed. These were not cleared when we relocated + the block to withdrawn. Had we successfully shrunk the buffer pool, + all this virtual memory would have been zeroed or made unaccessible, + and on a subsequent buffer pool extension it would be zero again. */ + buf_block_t *block= reinterpret_cast(b); + block->n_hash_helps= 0; +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + block->n_pointers= 0; +# endif + block->index= nullptr; +#endif } mysql_mutex_unlock(&mutex); my_printf_error(ER_WRONG_USAGE, "innodb_buffer_pool_size change aborted", MYF(ME_ERROR_LOG)); +#ifdef BTR_CUR_HASH_ADAPT + if (ahi_disabled) + btr_search.enable(true); +#endif mysql_mutex_lock(&LOCK_global_system_variables); }