Commit 8c1c6130 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-27274: DROP TABLE does not delete detached InnoDB files

In commit 1bd681c8 (MDEV-25506 part 3)
the way how DDL transactions delete files was rewritten.
Only files that are actually attached to InnoDB tablespaces would be
deleted, and only after the DDL transaction was durably committed.

After a failed ALTER TABLE...IMPORT TABLESPACE, any data files that
the user might have moved to the data directory will not be attached
to the InnoDB data dictionary. Therefore, DROP TABLE would not
attempt to delete those files, and a subsequent CREATE TABLE would
fail. The logic was that the user who created the files outside the
DBMS is still the owner of those files, and InnoDB should not delete
those files because an "ownership transfer" (IMPORT TABLESPACE) was
not successfully completed.

However, not deleting those detached files could surprise users.

ha_innobase::delete_table(): Even if no tablespace exists, try to
delete any files that might match the table name.

Reviewed by: Thirunarayanan Balathandayuthapani
parent 03e703fd
...@@ -8,13 +8,19 @@ FLUSH TABLES t1 FOR EXPORT; ...@@ -8,13 +8,19 @@ FLUSH TABLES t1 FOR EXPORT;
UNLOCK TABLES; UNLOCK TABLES;
ALTER TABLE imp_t1 IMPORT TABLESPACE; ALTER TABLE imp_t1 IMPORT TABLESPACE;
ERROR HY000: Schema mismatch (ROW_FORMAT mismatch) ERROR HY000: Schema mismatch (ROW_FORMAT mismatch)
CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
ERROR 42S01: Table 'imp_t1' already exists
DROP TABLE imp_t1;
CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE imp_t1, t1; DROP TABLE imp_t1, t1;
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm; SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
# #
# MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)' --echo # failed in dberr_t row_discard_tablespace_for_mysql # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)'
# failed in dberr_t row_discard_tablespace_for_mysql
# (dict_table_t*, trx_t*) # (dict_table_t*, trx_t*)
CREATE TABLE t1 (c INT KEY) ENGINE=INNODB; CREATE TABLE t1 (c INT KEY) ENGINE=INNODB;
CREATE TABLE t2 (c INT KEY,FOREIGN KEY(c) REFERENCES t1 (c)) ENGINE=INNODB; CREATE TABLE t2 (c INT KEY,FOREIGN KEY(c) REFERENCES t1 (c)) ENGINE=INNODB;
ALTER TABLE t1 DISCARD TABLESPACE; ALTER TABLE t1 DISCARD TABLESPACE;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
DROP TABLE t2, t1; DROP TABLE t2, t1;
# End of 10.6 tests
...@@ -14,16 +14,22 @@ let $datadir=`select @@datadir`; ...@@ -14,16 +14,22 @@ let $datadir=`select @@datadir`;
UNLOCK TABLES; UNLOCK TABLES;
--error ER_TABLE_SCHEMA_MISMATCH --error ER_TABLE_SCHEMA_MISMATCH
ALTER TABLE imp_t1 IMPORT TABLESPACE; ALTER TABLE imp_t1 IMPORT TABLESPACE;
--error ER_TABLE_EXISTS_ERROR
CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE imp_t1;
CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE imp_t1, t1; DROP TABLE imp_t1, t1;
--remove_file $datadir/test/imp_t1.ibd
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm; SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
--echo # --echo #
--echo # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)' --echo # failed in dberr_t row_discard_tablespace_for_mysql --echo # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)'
--echo # failed in dberr_t row_discard_tablespace_for_mysql
--echo # (dict_table_t*, trx_t*) --echo # (dict_table_t*, trx_t*)
CREATE TABLE t1 (c INT KEY) ENGINE=INNODB; CREATE TABLE t1 (c INT KEY) ENGINE=INNODB;
CREATE TABLE t2 (c INT KEY,FOREIGN KEY(c) REFERENCES t1 (c)) ENGINE=INNODB; CREATE TABLE t2 (c INT KEY,FOREIGN KEY(c) REFERENCES t1 (c)) ENGINE=INNODB;
--error ER_ROW_IS_REFERENCED_2 --error ER_ROW_IS_REFERENCED_2
ALTER TABLE t1 DISCARD TABLESPACE; ALTER TABLE t1 DISCARD TABLESPACE;
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo # End of 10.6 tests
...@@ -56,14 +56,10 @@ CREATE TABLE t2 ( ...@@ -56,14 +56,10 @@ CREATE TABLE t2 (
ALTER TABLE t2 DISCARD TABLESPACE; ALTER TABLE t2 DISCARD TABLESPACE;
--copy_file $MYSQLD_DATADIR/test/tmp.ibd $MYSQLD_DATADIR/test/t2.ibd --move_file $MYSQLD_DATADIR/test/tmp.ibd $MYSQLD_DATADIR/test/t2.ibd
--copy_file $MYSQLD_DATADIR/test/tmp.cfg $MYSQLD_DATADIR/test/t2.cfg --move_file $MYSQLD_DATADIR/test/tmp.cfg $MYSQLD_DATADIR/test/t2.cfg
--error ER_NOT_KEYFILE --error ER_NOT_KEYFILE
ALTER TABLE t2 IMPORT TABLESPACE; ALTER TABLE t2 IMPORT TABLESPACE;
DROP TABLE t2; DROP TABLE t2;
--remove_file $MYSQLD_DATADIR/test/t2.ibd
--remove_file $MYSQLD_DATADIR/test/tmp.ibd
--remove_file $MYSQLD_DATADIR/test/tmp.cfg
...@@ -98,10 +98,6 @@ if ($checksum_algorithm == "strict_full_crc32") { ...@@ -98,10 +98,6 @@ if ($checksum_algorithm == "strict_full_crc32") {
ALTER TABLE t2 IMPORT TABLESPACE; ALTER TABLE t2 IMPORT TABLESPACE;
DROP TABLE t2; DROP TABLE t2;
if ($error_code) {
--remove_file $MYSQLD_DATADIR/test/t2.ibd
}
SET GLOBAL innodb_file_per_table = 1; SET GLOBAL innodb_file_per_table = 1;
SELECT @@innodb_file_per_table; SELECT @@innodb_file_per_table;
...@@ -1102,7 +1098,6 @@ DROP TABLE t1, t2; ...@@ -1102,7 +1098,6 @@ DROP TABLE t1, t2;
CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb; CREATE TABLE t1 ( id INT NOT NULL, i1 INT, i2 INT, PRIMARY KEY (id)) engine=innodb;
--remove_file $MYSQLD_DATADIR/test/t2.ibd
CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb; CREATE TABLE t2 ( id INT NOT NULL, i1 INT, i2 INT, i3 INT, PRIMARY KEY (id)) engine=innodb;
ALTER TABLE t2 DISCARD TABLESPACE; ALTER TABLE t2 DISCARD TABLESPACE;
...@@ -1114,18 +1109,9 @@ FLUSH TABLES t1 FOR EXPORT; ...@@ -1114,18 +1109,9 @@ FLUSH TABLES t1 FOR EXPORT;
UNLOCK TABLES; UNLOCK TABLES;
--error ER_TABLE_SCHEMA_MISMATCH --error ER_TABLE_SCHEMA_MISMATCH
ALTER TABLE t2 IMPORT TABLESPACE; ALTER TABLE t2 IMPORT TABLESPACE;
--remove_file $MYSQLD_DATADIR/test/t2.ibd
--remove_file $MYSQLD_DATADIR/test/t2.cfg
DROP TABLE t1, t2; DROP TABLE t1, t2;
call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("Got error -1 when reading table '.*'");
call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'");
call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded");
# cleanup
--remove_file $MYSQLTEST_VARDIR/tmp/t1.cfg
--remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd
...@@ -13616,7 +13616,28 @@ int ha_innobase::delete_table(const char *name) ...@@ -13616,7 +13616,28 @@ int ha_innobase::delete_table(const char *name)
} }
if (err == DB_SUCCESS) if (err == DB_SUCCESS)
{
if (!table->space)
{
const char *data_dir_path= DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
char *path= fil_make_filepath(data_dir_path, table->name, CFG,
data_dir_path != nullptr);
os_file_delete_if_exists(innodb_data_file_key, path, nullptr);
ut_free(path);
path= fil_make_filepath(data_dir_path, table->name, IBD,
data_dir_path != nullptr);
os_file_delete_if_exists(innodb_data_file_key, path, nullptr);
ut_free(path);
if (data_dir_path)
{
path= fil_make_filepath(nullptr, table->name, ISL, false);
os_file_delete_if_exists(innodb_data_file_key, path, nullptr);
ut_free(path);
}
}
err= lock_sys_tables(trx); err= lock_sys_tables(trx);
}
dict_sys.lock(SRW_LOCK_CALL); dict_sys.lock(SRW_LOCK_CALL);
......
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