diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2021-05-14 14:20:16 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2021-05-14 14:37:13 +0530 |
commit | b82bd425dcc405266fdc02e539134af52a24a697 (patch) | |
tree | 7c6a784ec9deb80a5dd9601579fd7922279fd071 | |
parent | 1447b39475d2900066e0d058cee9b3fa6aec5016 (diff) | |
download | mariadb-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.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/truncate_crash.test | 12 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 7 |
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: */ |