From cedfe8eca49506c6b4d2d6868f1014c72caaab36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Jul 2025 12:24:25 +0300 Subject: [PATCH] MDEV-37250 buf_pool_t::shrink() assertion failure buf_pool_t::shrink(): When relocating a dirty page of the temporary tablespace, reset the oldest_modification() on the discarded block, like we do for persistent pages in buf_flush_relocate_on_flush_list(). buf_pool_t::resize(): Add debug assertions to catch this error earlier. This bug does not seem to affect non-debug builds. Reviewed by: Thirunarayanan Balathandayuthapani --- ...innodb_buffer_pool_shrink_temporary.result | 17 ++++++++++++++++ .../t/innodb_buffer_pool_shrink_temporary.opt | 1 + .../innodb_buffer_pool_shrink_temporary.test | 20 +++++++++++++++++++ storage/innobase/buf/buf0buf.cc | 8 +++++++- 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/innodb/r/innodb_buffer_pool_shrink_temporary.result create mode 100644 mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.opt create mode 100644 mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.test diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_shrink_temporary.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_shrink_temporary.result new file mode 100644 index 0000000000000..bfaf8df7a2e95 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_shrink_temporary.result @@ -0,0 +1,17 @@ +call mtr.add_suppression("innodb_buffer_pool_size change aborted"); +SET @b=REPEAT('0',1048576); +CREATE TEMPORARY TABLE t (c MEDIUMTEXT) ENGINE=InnoDB; +INSERT INTO t VALUES +(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b); +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +SET GLOBAL innodb_buffer_pool_size=6291456; +SET GLOBAL innodb_buffer_pool_size=16777216; +CHECKSUM TABLE t; +Table Checksum +test.t 4050893687 +DROP TEMPORARY TABLE t; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.opt b/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.opt new file mode 100644 index 0000000000000..d8ba7cf7b0ff8 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.opt @@ -0,0 +1 @@ +--innodb-buffer-pool-size=16m diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.test new file mode 100644 index 0000000000000..cf2ea4ad17539 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_shrink_temporary.test @@ -0,0 +1,20 @@ +--source include/have_innodb.inc +call mtr.add_suppression("innodb_buffer_pool_size change aborted"); +SET @b=REPEAT('0',1048576); +CREATE TEMPORARY TABLE t (c MEDIUMTEXT) ENGINE=InnoDB; +INSERT INTO t VALUES +(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b),(@b); +--error 0,ER_WRONG_USAGE +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +--error 0,ER_WRONG_USAGE +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +--error 0,ER_WRONG_USAGE +SET STATEMENT max_statement_time=0.000001 FOR +SET GLOBAL innodb_buffer_pool_size=6291456; +--error 0,ER_WRONG_USAGE +SET GLOBAL innodb_buffer_pool_size=6291456; +SET GLOBAL innodb_buffer_pool_size=16777216; +CHECKSUM TABLE t; +DROP TEMPORARY TABLE t; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 614e095f53a00..4b245bd14dee6 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1760,6 +1760,11 @@ ATTRIBUTE_COLD buf_pool_t::shrink_status buf_pool_t::shrink(size_t size) buf_flush_relocate_on_flush_list(b, &block->page); mysql_mutex_unlock(&flush_list_mutex); } + else + { + ut_d(if (auto om= b->oldest_modification()) ut_ad(om == 2)); + b->oldest_modification_.store(0, std::memory_order_relaxed); + } } /* relocate LRU list */ @@ -2091,10 +2096,11 @@ ATTRIBUTE_COLD void buf_pool_t::resize(size_t size, THD *thd) noexcept while (buf_page_t *b= UT_LIST_GET_FIRST(withdrawn)) { + ut_ad(!b->oldest_modification()); + ut_ad(b->state() == buf_page_t::NOT_USED); UT_LIST_REMOVE(withdrawn, b); UT_LIST_ADD_LAST(free, b); ut_d(b->in_free_list= true); - ut_ad(b->state() == buf_page_t::NOT_USED); b->lock.init(); }