diff options
author | Yuchen Pei <yuchen.pei@mariadb.com> | 2023-03-15 14:50:22 +1100 |
---|---|---|
committer | Yuchen Pei <yuchen.pei@mariadb.com> | 2023-03-16 12:41:08 +1100 |
commit | a614c74cff1049608f8717e7c7e99bf863724d83 (patch) | |
tree | b5f37794980f29380c0abccc3c31c8ff57c7fc88 | |
parent | 2919d886358eb74f8756e5d3803f5dc47d967e03 (diff) | |
download | mariadb-git-bb-11.0-mdev-26137-unsquashed.tar.gz |
wip please ignorebb-11.0-mdev-26137-unsquashed
-rw-r--r-- | mysql-test/suite/innodb/r/import_recovery.result | 38 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/import_no_cfg.test | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/import_recovery.test | 85 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 32 |
4 files changed, 105 insertions, 52 deletions
diff --git a/mysql-test/suite/innodb/r/import_recovery.result b/mysql-test/suite/innodb/r/import_recovery.result index 0ffecbb9116..bc8bb33dd45 100644 --- a/mysql-test/suite/innodb/r/import_recovery.result +++ b/mysql-test/suite/innodb/r/import_recovery.result @@ -1,18 +1,20 @@ -call mtr.add_suppression('.*Assertion.*failed.'); +# +# MDEV-26137 ALTER TABLE IMPORT enhancement +# call mtr.add_suppression('InnoDB: Tablespace for table `test`.`t2` is set as discarded.'); -call mtr.add_suppression('InnoDB: ./test/t2.ibd: Page 0 at offset 0 looks corrupted.'); -call mtr.add_suppression("mariadbd: Index for table 't2' is corrupt; try to repair it"); # Recovery from crashes ## Creation of stub succeeds; server crashes; second import attempt succeeds CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; +connect hang,localhost,root; +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; ALTER TABLE t2 IMPORT TABLESPACE; -ERROR HY000: Lost connection to server during query -# Restart mysqld after the crash and reconnect. +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; # restart +disconnect hang; ALTER TABLE t2 IMPORT TABLESPACE; SELECT * FROM t2; a @@ -23,13 +25,17 @@ CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; +connect hang,localhost,root; +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; ALTER TABLE t2 IMPORT TABLESPACE; -ERROR HY000: Lost connection to server during query -# Restart mysqld after the crash and reconnect. +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; # restart +disconnect hang; DROP TABLE t1, t2; # Recovery from corruption +call mtr.add_suppression('InnoDB: ./test/t2.ibd: Page 0 at offset 0 looks corrupted.'); +call mtr.add_suppression("mariadbd: Index for table 't2' is corrupt; try to repair it"); ## Recovery from corruption, with cfg CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); @@ -54,9 +60,12 @@ CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; +connect hang,localhost,root; +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; ALTER TABLE t2 IMPORT TABLESPACE; -ERROR HY000: Lost connection to server during query +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +disconnect hang; # corrupting the 0th page # Restart mysqld after the crash and reconnect. # restart @@ -68,9 +77,12 @@ CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; +connect hang,localhost,root; +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; ALTER TABLE t2 IMPORT TABLESPACE; -ERROR HY000: Lost connection to server during query +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +disconnect hang; # corrupting the 0th page # Restart mysqld after the crash and reconnect. # restart diff --git a/mysql-test/suite/innodb/t/import_no_cfg.test b/mysql-test/suite/innodb/t/import_no_cfg.test new file mode 100644 index 00000000000..2cc0e0feed5 --- /dev/null +++ b/mysql-test/suite/innodb/t/import_no_cfg.test @@ -0,0 +1,2 @@ +--source include/import_begin.inc +--source include/import_end.inc diff --git a/mysql-test/suite/innodb/t/import_recovery.test b/mysql-test/suite/innodb/t/import_recovery.test index f1cc50abb51..f3501145a3a 100644 --- a/mysql-test/suite/innodb/t/import_recovery.test +++ b/mysql-test/suite/innodb/t/import_recovery.test @@ -1,16 +1,13 @@ --source include/have_innodb.inc --source include/have_debug.inc -let MYSQLD_DATADIR = `SELECT @@datadir`; -let INNODB_PAGE_SIZE=`select @@innodb_page_size`; +--echo # +--echo # MDEV-26137 ALTER TABLE IMPORT enhancement +--echo # + let $MYSQLD_DATADIR = `SELECT @@datadir`; ---let $_server_id= `SELECT @@server_id` ---let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect -call mtr.add_suppression('.*Assertion.*failed.'); call mtr.add_suppression('InnoDB: Tablespace for table `test`.`t2` is set as discarded.'); -call mtr.add_suppression('InnoDB: ./test/t2.ibd: Page 0 at offset 0 looks corrupted.'); -call mtr.add_suppression("mariadbd: Index for table 't2' is corrupt; try to repair it"); --echo # Recovery from crashes --echo ## Creation of stub succeeds; server crashes; second import attempt succeeds @@ -21,13 +18,19 @@ FLUSH TABLES t1 FOR EXPORT; --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm --copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; -# Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---error 2013 + +connect (hang,localhost,root); +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; +send + ALTER TABLE t2 IMPORT TABLESPACE; ---echo # Restart mysqld after the crash and reconnect. ---source include/start_mysqld.inc + +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +let $shutdown_timeout=0; +--source include/restart_mysqld.inc +disconnect hang; + ALTER TABLE t2 IMPORT TABLESPACE; SELECT * FROM t2; DROP TABLE t1, t2; @@ -40,16 +43,29 @@ FLUSH TABLES t1 FOR EXPORT; --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm --copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; -# Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---error 2013 + +connect (hang,localhost,root); +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; +send + ALTER TABLE t2 IMPORT TABLESPACE; ---echo # Restart mysqld after the crash and reconnect. ---source include/start_mysqld.inc + +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +let $shutdown_timeout=0; +--source include/restart_mysqld.inc +disconnect hang; + DROP TABLE t1, t2; --echo # Recovery from corruption + +let MYSQLD_DATADIR = `SELECT @@datadir`; +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; + +call mtr.add_suppression('InnoDB: ./test/t2.ibd: Page 0 at offset 0 looks corrupted.'); +call mtr.add_suppression("mariadbd: Index for table 't2' is corrupt; try to repair it"); + --echo ## Recovery from corruption, with cfg CREATE TABLE t1 (a int) ENGINE=InnoDB; INSERT INTO t1 VALUES(42); @@ -117,12 +133,19 @@ FLUSH TABLES t1 FOR EXPORT; --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm --copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; -# Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---error 2013 + +connect (hang,localhost,root); +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; +send + ALTER TABLE t2 IMPORT TABLESPACE; +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +let $shutdown_timeout=0; +--source include/shutdown_mysqld.inc +disconnect hang; + --echo # corrupting the 0th page perl; my $ps = $ENV{INNODB_PAGE_SIZE}; @@ -154,12 +177,19 @@ FLUSH TABLES t1 FOR EXPORT; --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm --copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd UNLOCK TABLES; -SET DEBUG_DBUG='+d,die_after_create_stub_for_import'; -# Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---error 2013 + +connect (hang,localhost,root); +SET DEBUG_SYNC='ib_after_create_stub_for_import SIGNAL hung WAIT_FOR ever'; +send + ALTER TABLE t2 IMPORT TABLESPACE; +connection default; +SET DEBUG_SYNC='now WAIT_FOR hung'; +let $shutdown_timeout=0; +--source include/shutdown_mysqld.inc +disconnect hang; + --echo # corrupting the 0th page perl; my $ps = $ENV{INNODB_PAGE_SIZE}; @@ -182,4 +212,3 @@ EOF --error ER_TABLE_SCHEMA_MISMATCH ALTER TABLE t2 IMPORT TABLESPACE; DROP TABLE t1, t2; - diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 88e7aec7aad..bc0af456b54 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1921,16 +1921,19 @@ static int prepare_create_stub_for_import(THD *thd, const char *name, HA_CREATE_INFO& create_info) { DBUG_ENTER("prepare_create_stub_for_import"); - char norm_name[FN_REFLEN]; - normalize_table_name(norm_name, name); FetchIndexRootPages fetchIndexRootPages(name); if (fil_tablespace_iterate(fil_path_to_mysql_datadir, name, IO_BUFFER_SIZE(srv_page_size), fetchIndexRootPages) != DB_SUCCESS) { - sql_print_error("InnoDB: failed to get row format from ibd for %s.\n", - norm_name); + const char *ibd_path = fil_make_filepath( + fil_path_to_mysql_datadir, table_name_t(const_cast<char*>(name)), IBD, + fil_path_to_mysql_datadir != nullptr); + if (!ibd_path) + return(DB_OUT_OF_MEMORY); + sql_print_error("InnoDB: failed to get row format from %s.\n", + ibd_path); DBUG_RETURN(ER_INNODB_IMPORT_ERROR); } create_info.init(); @@ -1952,9 +1955,11 @@ static int prepare_create_stub_for_import(THD *thd, const char *name, rec_format_from_cfg == REC_FORMAT_DYNAMIC) && create_info.row_type == ROW_TYPE_NOT_USED)) { + char norm_name[FN_REFLEN]; + normalize_table_name(norm_name, name); sql_print_error( - "InnoDB: cfg and ibd disagree on row format for table %s.\n", - norm_name); + "InnoDB: cfg and ibd disagree on row format for table %s.\n", + norm_name); DBUG_RETURN(ER_INNODB_IMPORT_ERROR); } else @@ -5928,10 +5933,9 @@ ha_innobase::open(const char* name, int, uint) create_info)) DBUG_RETURN(err); create(name, table, &create_info, true, nullptr); - DBUG_EXECUTE_IF("die_after_create_stub_for_import", ut_ad(0);); + DEBUG_SYNC(thd, "ib_after_create_stub_for_import"); ib_table = open_dict_table(name, norm_name, is_part, DICT_ERR_IGNORE_FK_NOKEY); - DEBUG_SYNC(thd, "ib_open_after_create_stub_for_import"); } if (NULL == ib_table) { @@ -13230,9 +13234,12 @@ ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info, row_mysql_lock_data_dictionary(trx); } + const bool importing= thd_ddl_options(ha_thd())->import_tablespace(); if (!error) - error= info.create_table(own_trx && - !thd_ddl_options(ha_thd())->import_tablespace()); + /* We can't possibly have foreign key information when creating a + stub table for importing .frm / .cfg / .ibd because it is not + stored in any of these files. */ + error= info.create_table(own_trx && !importing); if (own_trx || (info.flags2() & DICT_TF2_TEMPORARY)) { @@ -13254,7 +13261,10 @@ ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info, if (!error) { - if (!thd_ddl_options(ha_thd())->import_tablespace()) + /* Skip stats update when creating a stub table for importing, + as it is not needed and would report error due to the table + not being readable yet. */ + if (!importing) dict_stats_update(info.table(), DICT_STATS_EMPTY_TABLE); if (!info.table()->is_temporary()) log_write_up_to(trx->commit_lsn, true); |