From f73ffd1150064fb03be417126f1257b4612989a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 11 Jul 2025 15:20:06 +0300 Subject: [PATCH] MDEV-37183 Scrubbing empty record breaks recovery page_delete_rec_list_end(): Do not attempt to scrub the data of an empty record. The test case would reproduce a debug assertion failure in branches where commit 358921ce32203a9a8dd277a5ba7ac177c9e79e53 (MDEV-26938) is present. MariaDB Server 10.6 only supports ascending indexes, and in those, the empty string would always be sorted first, never last in a page. Nevertheless, we fix the bug also in 10.6, in case it would be reproducible in a slightly different scenario. Reviewed by: Thirunarayanan Balathandayuthapani --- mysql-test/suite/innodb/r/scrub_debug.result | 16 ++++++++++++++++ mysql-test/suite/innodb/t/scrub_debug.test | 15 +++++++++++++++ storage/innobase/page/page0page.cc | 5 +++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/scrub_debug.result b/mysql-test/suite/innodb/r/scrub_debug.result index 7b0a9fd501c..7da2e0c51b0 100644 --- a/mysql-test/suite/innodb/r/scrub_debug.result +++ b/mysql-test/suite/innodb/r/scrub_debug.result @@ -15,5 +15,21 @@ FLUSH TABLE t1 FOR EXPORT; NOT FOUND /repairman/ in t1.ibd UNLOCK TABLES; DROP TABLE t1; +# +# MDEV-37183 innodb_immediate_scrub_data_uncompressed=ON may break +# crash recovery +# +SET GLOBAL innodb_limit_optimistic_insert_debug=0; +CREATE TABLE t(a VARCHAR(1) PRIMARY KEY,INDEX(a DESC)) ENGINE=InnoDB; +INSERT INTO t VALUES('2'),('1'),(''),('6'),('4'),('3'); +SET GLOBAL innodb_limit_optimistic_insert_debug=3; +INSERT INTO t VALUES('8'); +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +SELECT COUNT(*) FROM t; +COUNT(*) +7 +DROP TABLE t; SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; diff --git a/mysql-test/suite/innodb/t/scrub_debug.test b/mysql-test/suite/innodb/t/scrub_debug.test index 8cebfca6106..b1603e961fd 100644 --- a/mysql-test/suite/innodb/t/scrub_debug.test +++ b/mysql-test/suite/innodb/t/scrub_debug.test @@ -24,5 +24,20 @@ FLUSH TABLE t1 FOR EXPORT; -- source include/search_pattern_in_file.inc UNLOCK TABLES; DROP TABLE t1; + +--echo # +--echo # MDEV-37183 innodb_immediate_scrub_data_uncompressed=ON may break +--echo # crash recovery +--echo # +SET GLOBAL innodb_limit_optimistic_insert_debug=0; +# Note: MariaDB 10.6 fails to reproduce the crash; it maps DESC to ASC. +CREATE TABLE t(a VARCHAR(1) PRIMARY KEY,INDEX(a DESC)) ENGINE=InnoDB; +INSERT INTO t VALUES('2'),('1'),(''),('6'),('4'),('3'); +SET GLOBAL innodb_limit_optimistic_insert_debug=3; +INSERT INTO t VALUES('8'); +CHECK TABLE t; +SELECT COUNT(*) FROM t; +DROP TABLE t; + SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index e78ea8b75d4..ae9031f3ba1 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -977,8 +977,9 @@ page_delete_rec_list_end( size+= s; n_recs++; - if (scrub) - mtr->memset(block, rec2 - page, rec_offs_data_size(offsets), 0); + if (UNIV_LIKELY(!scrub)); + else if (size_t size= rec_offs_data_size(offsets)) + mtr->memset(block, rec2 - page, size, 0); rec2= page_rec_get_next(rec2); }