Commit 782b2a75 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-29144 ER_TABLE_SCHEMA_MISMATCH or crash on DISCARD/IMPORT

mysql_discard_or_import_tablespace(): On successful
ALTER TABLE...DISCARD TABLESPACE, evict the table handle from the
table definition cache, so that ha_innobase::close() will be invoked,
like InnoDB expects to be the case. This will avoid an assertion failure
ut_a(table->get_ref_count() == 0) during IMPORT TABLESPACE.

ha_innobase::open(): Do not issue any ER_TABLESPACE_DISCARDED warning.
Member functions for DML will do that.

ha_innobase::truncate(), ha_innobase::check_if_supported_inplace_alter():
Issue ER_TABLESPACE_DISCARDED warnings, to compensate for the removal of
the warning in ha_innobase::open().

row_quiesce_write_indexes(): Only write information about committed
indexes. The ALTER TABLE t NOWAIT ADD INDEX(c) in the nondeterministic
test case will most of the time fail due to a metadata lock (MDL) timeout
and leave behind an uncommitted index.

Reviewed by: Sergei Golubchik
parent 8f3631d0
......@@ -44,7 +44,6 @@ ALTER TABLE t1 DISCARD TABLESPACE;
restore: t1 .ibd and .cfg files
ALTER TABLE t1 DISCARD TABLESPACE;
Warnings:
Warning 1814 Tablespace has been discarded for table `t1`
Warning 1812 Tablespace is missing for table 'test/t1'
restore: t1 .ibd and .cfg files
ALTER TABLE t1 IMPORT TABLESPACE;
......
#
# MDEV-29144 ER_TABLE_SCHEMA_MISMATCH or crash on DISCARD/IMPORT
#
CREATE TABLE t (pk int PRIMARY KEY, c varchar(1024))
ENGINE=InnoDB CHARSET latin1;
INSERT INTO t SELECT seq, 'x' FROM seq_1_to_100;
connect con1,localhost,root,,test;
BEGIN NOT ATOMIC
DECLARE a INT DEFAULT 0;
REPEAT
SET a= a+1;
UPDATE t SET c = 'xx' WHERE pk = a;
UNTIL a = 100
END REPEAT;
END
$
connection default;
ALTER TABLE t NOWAIT ADD INDEX (c);
connection con1;
connection default;
FLUSH TABLE t FOR EXPORT;
UNLOCK TABLES;
DROP TABLE t;
ALTER TABLE t DISCARD TABLESPACE;
ALTER TABLE t IMPORT TABLESPACE;
DROP TABLE t;
--source include/have_innodb.inc
--source include/have_sequence.inc
--echo #
--echo # MDEV-29144 ER_TABLE_SCHEMA_MISMATCH or crash on DISCARD/IMPORT
--echo #
CREATE TABLE t (pk int PRIMARY KEY, c varchar(1024))
ENGINE=InnoDB CHARSET latin1;
INSERT INTO t SELECT seq, 'x' FROM seq_1_to_100;
--connect (con1,localhost,root,,test)
--delimiter $
--send
BEGIN NOT ATOMIC
DECLARE a INT DEFAULT 0;
REPEAT
SET a= a+1;
UPDATE t SET c = 'xx' WHERE pk = a;
UNTIL a = 100
END REPEAT;
END
$
--delimiter ;
--connection default
--error 0,ER_LOCK_WAIT_TIMEOUT
ALTER TABLE t NOWAIT ADD INDEX (c);
--connection con1
--reap
--connection default
--let $datadir= `select @@datadir`
FLUSH TABLE t FOR EXPORT;
--let $create= query_get_value(SHOW CREATE TABLE t, Create Table, 1)
--copy_file $datadir/test/t.cfg $MYSQL_TMP_DIR/t.cfg
--copy_file $datadir/test/t.ibd $MYSQL_TMP_DIR/t.ibd
UNLOCK TABLES;
DROP TABLE t;
--disable_query_log
eval $create;
--enable_query_log
ALTER TABLE t DISCARD TABLESPACE;
--move_file $MYSQL_TMP_DIR/t.cfg $datadir/test/t.cfg
--move_file $MYSQL_TMP_DIR/t.ibd $datadir/test/t.ibd
ALTER TABLE t IMPORT TABLESPACE;
# Cleanup
DROP TABLE t;
......@@ -6075,6 +6075,10 @@ int mysql_discard_or_import_tablespace(THD *thd,
if (unlikely(error))
goto err;
if (discard)
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, table_list->table->s->db.str,
table_list->table->s->table_name.str, true);
/*
The 0 in the call below means 'not in a transaction', which means
immediate invalidation; that is probably what we wish here
......
......@@ -6268,11 +6268,6 @@ ha_innobase::open(const char* name, int, uint)
MONITOR_INC(MONITOR_TABLE_OPEN);
if ((ib_table->flags2 & DICT_TF2_DISCARDED)) {
ib_senderrf(thd,
IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
table->s->table_name.str);
/* Allow an open because a proper DISCARD should have set
all the flags and index root page numbers to FIL_NULL that
should prevent any DML from running but it should allow DDL
......@@ -13631,6 +13626,12 @@ int ha_innobase::truncate()
if (ib_table->is_temporary()) {
info.options|= HA_LEX_CREATE_TMP_TABLE;
} else {
if (!ib_table->space) {
ib_senderrf(m_user_thd,
IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
table->s->table_name.str);
}
dict_get_and_save_data_dir_path(ib_table, false);
}
......
......@@ -1013,6 +1013,12 @@ ha_innobase::check_if_supported_inplace_alter(
update_thd();
if (!m_prebuilt->table->space) {
ib_senderrf(m_user_thd, IB_LOG_LEVEL_WARN,
ER_TABLESPACE_DISCARDED,
table->s->table_name.str);
}
if (ha_alter_info->handler_flags
& ~(INNOBASE_INPLACE_IGNORE
| INNOBASE_ALTER_INSTANT
......
......@@ -106,11 +106,17 @@ row_quiesce_write_indexes(
FILE* file, /*!< in: file to write to */
THD* thd) /*!< in/out: session */
{
ulint n_indexes = 0;
for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
index; index = UT_LIST_GET_NEXT(indexes, index)) {
n_indexes += index->is_committed();
}
{
byte row[sizeof(ib_uint32_t)];
/* Write the number of indexes in the table. */
mach_write_to_4(row, UT_LIST_GET_LEN(table->indexes));
mach_write_to_4(row, n_indexes);
DBUG_EXECUTE_IF("ib_export_io_write_failure_11",
close(fileno(file)););
......@@ -132,6 +138,12 @@ row_quiesce_write_indexes(
index != 0 && err == DB_SUCCESS;
index = UT_LIST_GET_NEXT(indexes, index)) {
if (!index->is_committed()) {
continue;
}
ut_ad(n_indexes); ut_d(n_indexes--);
byte* ptr;
byte row[sizeof(index_id_t)
+ sizeof(ib_uint32_t) * 8];
......@@ -202,6 +214,7 @@ row_quiesce_write_indexes(
err = row_quiesce_write_index_fields(index, file, thd);
}
ut_ad(!n_indexes);
return(err);
}
......
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