Commit 85db5347 authored by Marko Mäkelä's avatar Marko Mäkelä Committed by Oleksandr Byelkin

MDEV-33400 Adaptive hash index corruption after DISCARD TABLESPACE

row_discard_tablespace(): Do not invoke dict_index_t::clear_instant_alter()
because that would corrupt any adaptive hash index entries in the table.

row_import_for_mysql(): Invoke dict_index_t::clear_instant_alter()
after detaching any adaptive hash index entries.
parent 23101304
......@@ -10,3 +10,19 @@ ALTER TABLE imp_t1 IMPORT TABLESPACE;
ERROR HY000: Schema mismatch (ROW_FORMAT mismatch)
DROP TABLE imp_t1, t1;
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
#
# MDEV-33400 Adaptive hash index corruption after DISCARD TABLESPACE
#
SET @save_adaptive=@@GLOBAL.innodb_adaptive_hash_index;
SET GLOBAL innodb_adaptive_hash_index=ON;
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t SELECT * FROM seq_1_to_131;
ALTER TABLE t ADD hid INT DEFAULT 2;
INSERT INTO t VALUES (251,1);
ALTER TABLE t DISCARD TABLESPACE;
CHECK TABLE mysql.innodb_table_stats;
Table Op Msg_type Msg_text
mysql.innodb_table_stats check status OK
DROP TABLE t;
SET GLOBAL innodb_adaptive_hash_index=@save_adaptive;
# End of 10.4 tests
--source include/have_innodb.inc
--source include/have_sequence.inc
call mtr.add_suppression("Index for table 'imp_t1' is corrupt; try to repair it");
......@@ -17,3 +18,21 @@ ALTER TABLE imp_t1 IMPORT TABLESPACE;
DROP TABLE imp_t1, t1;
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
--echo #
--echo # MDEV-33400 Adaptive hash index corruption after DISCARD TABLESPACE
--echo #
SET @save_adaptive=@@GLOBAL.innodb_adaptive_hash_index;
SET GLOBAL innodb_adaptive_hash_index=ON;
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t SELECT * FROM seq_1_to_131;
ALTER TABLE t ADD hid INT DEFAULT 2;
INSERT INTO t VALUES (251,1);
ALTER TABLE t DISCARD TABLESPACE;
CHECK TABLE mysql.innodb_table_stats;
DROP TABLE t;
SET GLOBAL innodb_adaptive_hash_index=@save_adaptive;
--echo # End of 10.4 tests
......@@ -4383,6 +4383,23 @@ row_import_for_mysql(
ibuf_delete_for_discarded_space(table->space_id);
#ifdef BTR_CUR_HASH_ADAPT
/* On DISCARD TABLESPACE, we did not drop any adaptive hash
index entries. If we replaced the discarded tablespace with a
smaller one here, there could still be some adaptive hash
index entries that point to cached garbage pages in the buffer
pool, because PageConverter::operator() only evicted those
pages that were replaced by the imported pages. We must
detach any remaining adaptive hash index entries, because the
adaptive hash index must be a subset of the table contents;
false positives are not tolerated. */
for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index;
index = UT_LIST_GET_NEXT(indexes, index)) {
index = index->clone_if_needed();
}
#endif /* BTR_CUR_HASH_ADAPT */
UT_LIST_GET_FIRST(table->indexes)->clear_instant_alter();
trx_start_if_not_started(prebuilt->trx, true);
trx = trx_create();
......@@ -4540,21 +4557,6 @@ row_import_for_mysql(
DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure",
err = DB_TOO_MANY_CONCURRENT_TRXS;);
#ifdef BTR_CUR_HASH_ADAPT
/* On DISCARD TABLESPACE, we did not drop any adaptive hash
index entries. If we replaced the discarded tablespace with a
smaller one here, there could still be some adaptive hash
index entries that point to cached garbage pages in the buffer
pool, because PageConverter::operator() only evicted those
pages that were replaced by the imported pages. We must
detach any remaining adaptive hash index entries, because the
adaptive hash index must be a subset of the table contents;
false positives are not tolerated. */
for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index;
index = UT_LIST_GET_NEXT(indexes, index)) {
index = index->clone_if_needed();
}
#endif /* BTR_CUR_HASH_ADAPT */
if (err != DB_SUCCESS) {
char table_name[MAX_FULL_NAME_LEN + 1];
......
......@@ -3047,7 +3047,6 @@ row_discard_tablespace(
dict_table_change_id_in_cache(table, new_id);
dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
if (index) index->clear_instant_alter();
/* Reset the root page numbers. */
for (; index; index = UT_LIST_GET_NEXT(indexes, index)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment