From 464055fe655d70e7191f4bd9f5709bc64b26b942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com> Date: Tue, 1 Oct 2024 18:35:39 +0300 Subject: [PATCH] MDEV-34078 Memory leak in InnoDB purge with 32-column PRIMARY KEY row_purge_reset_trx_id(): Reserve large enough offsets for accomodating the maximum width PRIMARY KEY followed by DB_TRX_ID,DB_ROLL_PTR. Reviewed by: Thirunarayanan Balathandayuthapani --- mysql-test/suite/innodb/r/purge.result | 23 ++++++++++++++++++++ mysql-test/suite/innodb/t/purge.test | 29 +++++++++++++++++++++++++- storage/innobase/row/row0purge.cc | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/purge.result b/mysql-test/suite/innodb/r/purge.result index a71d0afdcbe..5eedbc4ad9d 100644 --- a/mysql-test/suite/innodb/r/purge.result +++ b/mysql-test/suite/innodb/r/purge.result @@ -116,6 +116,29 @@ t12963823 CREATE TABLE `t12963823` ( KEY `ndx_o` (`o`(500)), KEY `ndx_p` (`p`(500)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +BEGIN NOT ATOMIC +DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(c', +GROUP_CONCAT(seq SEPARATOR +' INT DEFAULT 0, c'), +' INT DEFAULT 0, PRIMARY KEY(c', +GROUP_CONCAT(seq SEPARATOR ', c'), +')) ENGINE=InnoDB;') FROM seq_1_to_33); +EXECUTE IMMEDIATE c; +END; +$$ +ERROR 42000: Too many key parts specified; max 32 parts allowed +BEGIN NOT ATOMIC +DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(c', +GROUP_CONCAT(seq SEPARATOR +' INT DEFAULT 0, c'), +' INT DEFAULT 0, PRIMARY KEY(c', +GROUP_CONCAT(seq SEPARATOR ', c'), +')) ENGINE=InnoDB;') FROM seq_1_to_32); +EXECUTE IMMEDIATE c; +END; +$$ +INSERT INTO t1() VALUES(); InnoDB 0 transactions not purged +DROP TABLE t1; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/purge.test b/mysql-test/suite/innodb/t/purge.test index 63312e50fd8..3caa3f065aa 100644 --- a/mysql-test/suite/innodb/t/purge.test +++ b/mysql-test/suite/innodb/t/purge.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_innodb_16k.inc +--source include/have_sequence.inc SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; @@ -110,8 +111,34 @@ CREATE INDEX ndx_n ON t12963823 (n(500)); CREATE INDEX ndx_o ON t12963823 (o(500)); CREATE INDEX ndx_p ON t12963823 (p(500)); SHOW CREATE TABLE t12963823; -# We need to activate the purge thread before DROP TABLE. +DELIMITER $$; +--error ER_TOO_MANY_KEY_PARTS +BEGIN NOT ATOMIC + DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(c', + GROUP_CONCAT(seq SEPARATOR + ' INT DEFAULT 0, c'), + ' INT DEFAULT 0, PRIMARY KEY(c', + GROUP_CONCAT(seq SEPARATOR ', c'), + ')) ENGINE=InnoDB;') FROM seq_1_to_33); + EXECUTE IMMEDIATE c; +END; +$$ +BEGIN NOT ATOMIC + DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(c', + GROUP_CONCAT(seq SEPARATOR + ' INT DEFAULT 0, c'), + ' INT DEFAULT 0, PRIMARY KEY(c', + GROUP_CONCAT(seq SEPARATOR ', c'), + ')) ENGINE=InnoDB;') FROM seq_1_to_32); + EXECUTE IMMEDIATE c; +END; +$$ +DELIMITER ;$$ +INSERT INTO t1() VALUES(); + +# We need to activate the purge thread before DROP TABLE. -- source include/wait_all_purged.inc +DROP TABLE t1; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 6942f5b7af8..f9b30b6a0a9 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -678,7 +678,7 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr) mem_heap_t* heap = NULL; /* Reserve enough offsets for the PRIMARY KEY and 2 columns so that we can access DB_TRX_ID, DB_ROLL_PTR. */ - rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; + rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 3]; rec_offs_init(offsets_); rec_offs* offsets = rec_get_offsets( rec, index, offsets_, index->n_core_fields, -- 2.30.9