summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2022-11-10 12:09:16 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2022-11-15 12:16:40 +0530
commitdf4c3d96a4aba0e5a9af3bd5158cd2049a978130 (patch)
tree1c146d786244ccaa05d37119a9770e66415b5a58
parent1895c769c2c4170fa4d6f46f0014e98ea6295794 (diff)
downloadmariadb-git-df4c3d96a4aba0e5a9af3bd5158cd2049a978130.tar.gz
MDEV-29977 Memory leak in row_log_table_apply_update
- InnoDB fails to free the persistent cursor for the clustered index when InnoDB replays the update operation on the table that is being rebuilt.
-rw-r--r--mysql-test/suite/innodb/r/innodb-table-online.result20
-rw-r--r--mysql-test/suite/innodb/t/innodb-table-online.test21
-rw-r--r--storage/innobase/row/row0log.cc2
3 files changed, 39 insertions, 4 deletions
diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result
index ea56ea41c87..d54b79b5da7 100644
--- a/mysql-test/suite/innodb/r/innodb-table-online.result
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result
@@ -459,10 +459,26 @@ SET DEBUG_SYNC = 'now WAIT_FOR created';
UPDATE t1 SET f = REPEAT('a', 20000);
SET DEBUG_SYNC = 'now SIGNAL updated';
connection con1;
-disconnect con1;
connection default;
DROP TABLE t1;
-SET DEBUG_SYNC = 'RESET';
+#
+# MDEV-29977 Memory leak in row_log_table_apply_update
+#
+CREATE TABLE t1(f1 longtext, f2 int, KEY(f1(1024)), KEY(f2, f1(20))) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('a', 1);
+connection con1;
+set DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con_default WAIT_FOR con1_signal";
+ALTER TABLE t1 FORCE;
+connection default;
+SET DEBUG_SYNC="now WAIT_FOR con_default";
+UPDATE t1 SET f1 = NULL;
+UPDATE t1 SET f1 = REPEAT('b', 9000);
+SET DEBUG_SYNC="now SIGNAL con1_signal";
+connection con1;
+DROP TABLE t1;
+connection default;
+SET DEBUG_SYNC=RESET;
+disconnect con1;
SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig;
SET GLOBAL innodb_monitor_enable = default;
SET GLOBAL innodb_monitor_disable = default;
diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test
index 997b0a5bf10..a89073db4f7 100644
--- a/mysql-test/suite/innodb/t/innodb-table-online.test
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test
@@ -413,11 +413,28 @@ SET DEBUG_SYNC = 'now SIGNAL updated';
connection con1;
reap;
-disconnect con1;
connection default;
DROP TABLE t1;
-SET DEBUG_SYNC = 'RESET';
+--echo #
+--echo # MDEV-29977 Memory leak in row_log_table_apply_update
+--echo #
+CREATE TABLE t1(f1 longtext, f2 int, KEY(f1(1024)), KEY(f2, f1(20))) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('a', 1);
+connection con1;
+set DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con_default WAIT_FOR con1_signal";
+send ALTER TABLE t1 FORCE;
+connection default;
+SET DEBUG_SYNC="now WAIT_FOR con_default";
+UPDATE t1 SET f1 = NULL;
+UPDATE t1 SET f1 = REPEAT('b', 9000);
+SET DEBUG_SYNC="now SIGNAL con1_signal";
+connection con1;
+reap;
+DROP TABLE t1;
+connection default;
+SET DEBUG_SYNC=RESET;
+disconnect con1;
# Check that all connections opened by test cases in this file are really
# gone so execution of other tests won't be affected by their presence.
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index aa001a84deb..eab53e0c87c 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -2364,6 +2364,8 @@ func_exit_committed:
mtr_start(&mtr);
index->set_modified(mtr);
+ ut_free(pcur.old_rec_buf);
+
if (ROW_FOUND != row_search_index_entry(
index, entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
ut_ad(0);