summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-05-14 14:20:16 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-05-14 14:37:13 +0530
commitb82bd425dcc405266fdc02e539134af52a24a697 (patch)
tree7c6a784ec9deb80a5dd9601579fd7922279fd071
parent1447b39475d2900066e0d058cee9b3fa6aec5016 (diff)
downloadmariadb-git-bb-103-thiru.tar.gz
MDEV-25663 Double free of transaction during truncate operationbb-103-thiru
InnoDB truncate table fails to load the fts stopword table into cache. In that case, InnoDB double frees the truncate creation transaction. InnoDB should free the transaction which was created inside ha_innobase::create.
-rw-r--r--mysql-test/suite/innodb/r/truncate_crash.result11
-rw-r--r--mysql-test/suite/innodb/t/truncate_crash.test12
-rw-r--r--storage/innobase/handler/ha_innodb.cc7
3 files changed, 29 insertions, 1 deletions
diff --git a/mysql-test/suite/innodb/r/truncate_crash.result b/mysql-test/suite/innodb/r/truncate_crash.result
index 10ce8e92ab6..e6b92b00671 100644
--- a/mysql-test/suite/innodb/r/truncate_crash.result
+++ b/mysql-test/suite/innodb/r/truncate_crash.result
@@ -1,3 +1,4 @@
+call mtr.add_suppression("InnoDB: \\(\\Too many concurrent transactions\\)\\ writing .*");
FLUSH TABLES;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
@@ -12,3 +13,13 @@ COUNT(*)
0
TRUNCATE TABLE t1;
DROP TABLE t1;
+#
+# MDEV-25663 Double free of transaction during
+# truncate operation
+#
+CREATE TABLE t1 (a INT, b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB;
+SET DEBUG_DBUG='+d,ib_create_table_fail_too_many_trx';
+TRUNCATE table t1;
+ERROR HY000: Got error -1 "Internal error < 0 (Not system error)" from storage engine InnoDB
+SET DEBUG_DBUG='-d,ib_create_table_fail_too_many_trx';
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/truncate_crash.test b/mysql-test/suite/innodb/t/truncate_crash.test
index 5cb39c745dc..475822dab28 100644
--- a/mysql-test/suite/innodb/t/truncate_crash.test
+++ b/mysql-test/suite/innodb/t/truncate_crash.test
@@ -3,6 +3,7 @@
--source include/have_debug_sync.inc
--source include/not_embedded.inc
+call mtr.add_suppression("InnoDB: \\(\\Too many concurrent transactions\\)\\ writing .*");
FLUSH TABLES;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
@@ -21,3 +22,14 @@ disconnect wait;
SELECT COUNT(*) FROM t1;
TRUNCATE TABLE t1;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-25663 Double free of transaction during
+--echo # truncate operation
+--echo #
+CREATE TABLE t1 (a INT, b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB;
+SET DEBUG_DBUG='+d,ib_create_table_fail_too_many_trx';
+--error ER_GET_ERRNO
+TRUNCATE table t1;
+SET DEBUG_DBUG='-d,ib_create_table_fail_too_many_trx';
+DROP TABLE t1;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 2f02fa31c98..89822faf84e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -12830,7 +12830,6 @@ create_table_info_t::create_table_update_dict()
if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) {
dict_table_close(innobase_table, FALSE, FALSE);
srv_active_wake_master_thread();
- m_trx->free();
DBUG_RETURN(-1);
}
@@ -12979,6 +12978,12 @@ ha_innobase::create(
error = info.create_table_update_dict();
+ /* In case of error, free the transaction only if
+ it is newly created transaction in ha_innobase::create() */
+ if (own_trx && error) {
+ info.trx()->free();
+ }
+
/* Tell the InnoDB server that there might be work for
utility threads: */