diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 12:06:43 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 19:11:30 +0300 |
commit | 1eee3a3fb79e809943ff9e37b022660d155ad486 (patch) | |
tree | c45eb5b1f5f3ce8af2319db374a875d061233665 /mysql-test/suite | |
parent | b9418ed3332358e7209300739435c5e0aeb5ba70 (diff) | |
download | mariadb-git-1eee3a3fb79e809943ff9e37b022660d155ad486.tar.gz |
MDEV-13051 MySQL#86607 InnoDB crash after failed ADD INDEX and table_definition_cache eviction
There are two bugs related to failed ADD INDEX and
the InnoDB table cache eviction.
dict_table_close(): Try dropping failed ADD INDEX when releasing
the last table handle, not when releasing the last-but-one.
dict_table_remove_from_cache_low(): Do not invoke
row_merge_drop_indexes() after freeing all index metadata.
Instead, directly invoke row_merge_drop_indexes_dict() to
remove the metadata from the persistent data dictionary
and to free the index pages.
Diffstat (limited to 'mysql-test/suite')
-rw-r--r-- | mysql-test/suite/innodb/r/table_definition_cache_debug.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/table_definition_cache_debug.test | 66 |
2 files changed, 82 insertions, 0 deletions
diff --git a/mysql-test/suite/innodb/r/table_definition_cache_debug.result b/mysql-test/suite/innodb/r/table_definition_cache_debug.result new file mode 100644 index 00000000000..a72d4baad21 --- /dev/null +++ b/mysql-test/suite/innodb/r/table_definition_cache_debug.result @@ -0,0 +1,16 @@ +SET @save_tdc= @@GLOBAL.table_definition_cache; +SET @save_toc= @@GLOBAL.table_open_cache; +SET GLOBAL table_definition_cache= 400; +SET GLOBAL table_open_cache= 1024; +CREATE TABLE to_be_evicted(a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB; +INSERT INTO to_be_evicted VALUES(1,2),(2,1); +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL scanned WAIT_FOR got_duplicate'; +ALTER TABLE to_be_evicted ADD UNIQUE INDEX(b); +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +BEGIN; +INSERT INTO to_be_evicted VALUES(3, 2); +SET DEBUG_SYNC = 'now SIGNAL got_duplicate'; +ERROR 23000: Duplicate entry '2' for key 'b' +COMMIT; +SET DEBUG_SYNC = RESET; +FLUSH TABLES; diff --git a/mysql-test/suite/innodb/t/table_definition_cache_debug.test b/mysql-test/suite/innodb/t/table_definition_cache_debug.test new file mode 100644 index 00000000000..57d64d6844e --- /dev/null +++ b/mysql-test/suite/innodb/t/table_definition_cache_debug.test @@ -0,0 +1,66 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +SET @save_tdc= @@GLOBAL.table_definition_cache; +SET @save_toc= @@GLOBAL.table_open_cache; + +# InnoDB plugin essentially ignores table_definition_cache size +# and hard-wires it to 400, which also is the minimum allowed value. +SET GLOBAL table_definition_cache= 400; +SET GLOBAL table_open_cache= 1024; + +CREATE TABLE to_be_evicted(a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB; +INSERT INTO to_be_evicted VALUES(1,2),(2,1); + +connect(ddl,localhost,root,,); +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL scanned WAIT_FOR got_duplicate'; +--send +ALTER TABLE to_be_evicted ADD UNIQUE INDEX(b); + +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; + +# During the ADD UNIQUE INDEX, start a transaction that inserts a duplicate +# and then hogs the table lock, so that the unique index cannot be dropped. +BEGIN; +INSERT INTO to_be_evicted VALUES(3, 2); +SET DEBUG_SYNC = 'now SIGNAL got_duplicate'; + +connection ddl; +--error ER_DUP_ENTRY +reap; + +disconnect ddl; +connection default; +# Release the table lock. +COMMIT; +SET DEBUG_SYNC = RESET; + +# Allow cache eviction. +FLUSH TABLES; +--disable_query_log + +# Pollute the cache with many tables, so that our table will be evicted. +let $N=1000; +let $loop=$N; +while ($loop) +{ + eval CREATE TABLE t_$loop(id INT)ENGINE=InnoDB; + dec $loop; +} + +# Hopefully let InnoDB evict the tables. +sleep 10; + +let $loop=$N; +while ($loop) +{ + eval DROP TABLE t_$loop; + dec $loop; +} + +SET GLOBAL table_definition_cache= @save_tdc; +SET GLOBAL table_open_cache= @save_toc; + +DROP TABLE to_be_evicted; |