From 35c2e8b5071f62531b710ea914e1e3d3da546022 Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 7 Dec 2023 11:44:51 +0800 Subject: [PATCH] ddl: Support `FLASHBACK DATABASE` (#8424) close pingcap/tiflash#8450 --- dbms/src/Databases/DatabaseTiFlash.cpp | 24 ++- dbms/src/Databases/DatabaseTiFlash.h | 2 +- dbms/src/Databases/IDatabase.h | 11 +- dbms/src/Databases/test/gtest_database.cpp | 35 +++- dbms/src/TiDB/Schema/SchemaBuilder.cpp | 85 ++++++-- dbms/src/TiDB/Schema/SchemaBuilder.h | 18 +- dbms/src/TiDB/Schema/SchemaGetter.cpp | 4 +- .../ddl/alter_drop_database.test | 51 ----- .../ddl/flashback/flashback_database.test | 187 ++++++++++++++++++ .../ddl/partitions/reorganize_partition.test | 2 +- 10 files changed, 329 insertions(+), 90 deletions(-) delete mode 100644 tests/fullstack-test2/ddl/alter_drop_database.test create mode 100644 tests/fullstack-test2/ddl/flashback/flashback_database.test diff --git a/dbms/src/Databases/DatabaseTiFlash.cpp b/dbms/src/Databases/DatabaseTiFlash.cpp index f7b300e1efc..05382aa11a8 100644 --- a/dbms/src/Databases/DatabaseTiFlash.cpp +++ b/dbms/src/Databases/DatabaseTiFlash.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include namespace DB @@ -610,7 +611,7 @@ void DatabaseTiFlash::shutdown() tables.clear(); } -void DatabaseTiFlash::alterTombstone(const Context & context, Timestamp tombstone_) +void DatabaseTiFlash::alterTombstone(const Context & context, Timestamp tombstone_, const TiDB::DBInfoPtr & new_db_info) { const auto database_metadata_path = getDatabaseMetadataPath(metadata_path); const auto database_metadata_tmp_path = database_metadata_path + ".tmp"; @@ -622,7 +623,18 @@ void DatabaseTiFlash::alterTombstone(const Context & context, Timestamp tombston { // Alter the attach statement in metadata. - auto dbinfo_literal = std::make_shared(Field(db_info == nullptr ? "" : (db_info->serialize()))); + std::shared_ptr dbinfo_literal = [&]() { + String seri_info; + if (new_db_info != nullptr) + { + seri_info = new_db_info->serialize(); + } + else if (db_info != nullptr) + { + seri_info = db_info->serialize(); + } + return std::make_shared(Field(seri_info)); + }(); Field format_version_field(static_cast(DatabaseTiFlash::CURRENT_VERSION)); auto version_literal = std::make_shared(format_version_field); auto tombstone_literal = std::make_shared(Field(tombstone_)); @@ -651,6 +663,9 @@ void DatabaseTiFlash::alterTombstone(const Context & context, Timestamp tombston } else { + // update the seri dbinfo + args.children[0] = dbinfo_literal; + args.children[1] = version_literal; // udpate the tombstone mark args.children[2] = tombstone_literal; } @@ -704,6 +719,11 @@ void DatabaseTiFlash::alterTombstone(const Context & context, Timestamp tombston // After all done, set the tombstone tombstone = tombstone_; + // Overwrite db_info if not null + if (new_db_info) + { + db_info = new_db_info; + } } void DatabaseTiFlash::drop(const Context & context) diff --git a/dbms/src/Databases/DatabaseTiFlash.h b/dbms/src/Databases/DatabaseTiFlash.h index 178e7e00c39..51f446fd2ae 100644 --- a/dbms/src/Databases/DatabaseTiFlash.h +++ b/dbms/src/Databases/DatabaseTiFlash.h @@ -89,7 +89,7 @@ class DatabaseTiFlash : public DatabaseWithOwnTablesBase bool isTombstone() const override { return tombstone != 0; } Timestamp getTombstone() const override { return tombstone; } - void alterTombstone(const Context & context, Timestamp tombstone_) override; + void alterTombstone(const Context & context, Timestamp tombstone_, const TiDB::DBInfoPtr & new_db_info) override; void drop(const Context & context) override; diff --git a/dbms/src/Databases/IDatabase.h b/dbms/src/Databases/IDatabase.h index 15fdce40c40..d6414c7a924 100644 --- a/dbms/src/Databases/IDatabase.h +++ b/dbms/src/Databases/IDatabase.h @@ -24,6 +24,11 @@ #include #include +namespace TiDB +{ +struct DBInfo; +using DBInfoPtr = std::shared_ptr; +} // namespace TiDB namespace DB { @@ -144,7 +149,11 @@ class IDatabase : public std::enable_shared_from_this virtual bool isTombstone() const { return false; } virtual Timestamp getTombstone() const { return 0; } - virtual void alterTombstone(const Context & /*context*/, Timestamp /*tombstone_*/) {} + virtual void alterTombstone( + const Context & /*context*/, + Timestamp /*tombstone_*/, + const TiDB::DBInfoPtr & /*new_db_info*/) + {} /// Delete metadata, the deletion of which differs from the recursive deletion of the directory, if any. virtual void drop(const Context & context) = 0; diff --git a/dbms/src/Databases/test/gtest_database.cpp b/dbms/src/Databases/test/gtest_database.cpp index 9a009874891..5b5062b1d84 100644 --- a/dbms/src/Databases/test/gtest_database.cpp +++ b/dbms/src/Databases/test/gtest_database.cpp @@ -28,10 +28,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -942,6 +944,7 @@ try )", }; + size_t case_no = 0; for (const auto & statement : statements) { { @@ -968,22 +971,48 @@ try LOG_DEBUG(log, "After create [meta={}]", meta); DB::Timestamp tso = 1000; - db->alterTombstone(*ctx, tso); + db->alterTombstone(*ctx, tso, nullptr); EXPECT_TRUE(db->isTombstone()); EXPECT_EQ(db->getTombstone(), tso); + if (case_no != 0) + { + auto db_tiflash = std::dynamic_pointer_cast(db); + ASSERT_NE(db_tiflash, nullptr); + auto db_info = db_tiflash->getDatabaseInfo(); + ASSERT_EQ(db_info.name, "test_db"); // not changed + } // Try restore from disk db = detachThenAttach(*ctx, db_name, std::move(db), log); EXPECT_TRUE(db->isTombstone()); EXPECT_EQ(db->getTombstone(), tso); - // Recover - db->alterTombstone(*ctx, 0); + // Recover, usually recover with a new database name + auto new_db_info = std::make_shared( + R"json({"charset":"utf8mb4","collate":"utf8mb4_bin","db_name":{"L":"test_new_db","O":"test_db"},"id":1010,"state":5})json", + NullspaceID); + db->alterTombstone(*ctx, 0, new_db_info); EXPECT_FALSE(db->isTombstone()); + if (case_no != 0) + { + auto db_tiflash = std::dynamic_pointer_cast(db); + ASSERT_NE(db_tiflash, nullptr); + auto db_info = db_tiflash->getDatabaseInfo(); + ASSERT_EQ(db_info.name, "test_new_db"); // changed by the `new_db_info` + } // Try restore from disk db = detachThenAttach(*ctx, db_name, std::move(db), log); EXPECT_FALSE(db->isTombstone()); + if (case_no != 0) + { + auto db_tiflash = std::dynamic_pointer_cast(db); + ASSERT_NE(db_tiflash, nullptr); + auto db_info = db_tiflash->getDatabaseInfo(); + ASSERT_EQ(db_info.name, "test_new_db"); // changed by the `new_db_info` + } + + case_no += 1; } } CATCH diff --git a/dbms/src/TiDB/Schema/SchemaBuilder.cpp b/dbms/src/TiDB/Schema/SchemaBuilder.cpp index c80c4c7260c..7727e36e004 100644 --- a/dbms/src/TiDB/Schema/SchemaBuilder.cpp +++ b/dbms/src/TiDB/Schema/SchemaBuilder.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -259,12 +260,17 @@ void SchemaBuilder::applyDiff(const SchemaDiff & diff) { case SchemaActionType::CreateSchema: { - applyCreateSchema(diff.schema_id); + applyCreateDatabase(diff.schema_id); break; } case SchemaActionType::DropSchema: { - applyDropSchema(diff.schema_id); + applyDropDatabase(diff.schema_id); + break; + } + case SchemaActionType::ActionRecoverSchema: + { + applyRecoverDatabase(diff.schema_id); break; } case SchemaActionType::CreateTables: @@ -872,19 +878,19 @@ String createDatabaseStmt(Context & context, const DBInfo & db_info, const Schem } template -bool SchemaBuilder::applyCreateSchema(DatabaseID schema_id) +bool SchemaBuilder::applyCreateDatabase(DatabaseID database_id) { - auto db_info = getter.getDatabase(schema_id); + auto db_info = getter.getDatabase(database_id); if (unlikely(db_info == nullptr)) { return false; } - applyCreateSchema(db_info); + applyCreateDatabaseByInfo(db_info); return true; } template -void SchemaBuilder::applyCreateSchema(const TiDB::DBInfoPtr & db_info) +void SchemaBuilder::applyCreateDatabaseByInfo(const TiDB::DBInfoPtr & db_info) { GET_METRIC(tiflash_schema_internal_ddl_count, type_create_db).Increment(); LOG_INFO(log, "Create database {} begin, database_id={}", name_mapper.debugDatabaseName(*db_info), db_info->id); @@ -904,29 +910,72 @@ void SchemaBuilder::applyCreateSchema(const TiDB::DBInfoPtr } template -void SchemaBuilder::applyDropSchema(DatabaseID schema_id) +void SchemaBuilder::applyRecoverDatabase(DatabaseID database_id) +{ + auto db_info = getter.getDatabase(database_id); + if (unlikely(db_info == nullptr)) + { + LOG_INFO( + log, + "Recover database is ignored because database is not exist in TiKV," + " database_id={}", + database_id); + return; + } + LOG_INFO(log, "Recover database begin, database_id={}", database_id); + auto db_name = name_mapper.mapDatabaseName(database_id, keyspace_id); + auto db = context.tryGetDatabase(db_name); + if (unlikely(!db)) + { + LOG_ERROR( + log, + "Recover database is ignored because instance is not exists, may have been physically dropped, " + "database_id={}", + db_name, + database_id); + return; + } + + { + //TODO: it seems may need a lot time, maybe we can do it in a background thread + auto table_ids = table_id_map.findTablesByDatabaseID(database_id); + for (auto table_id : table_ids) + { + auto table_info = getter.getTableInfo(database_id, table_id); + applyRecoverLogicalTable(db_info, table_info); + } + } + + // Usually `FLASHBACK DATABASE ... TO ...` will rename the database + db->alterTombstone(context, 0, db_info); + databases.addDatabaseInfo(db_info); // add back database info cache + LOG_INFO(log, "Recover database end, database_id={}", database_id); +} + +template +void SchemaBuilder::applyDropDatabase(DatabaseID database_id) { - TiDB::DBInfoPtr db_info = databases.getDBInfo(schema_id); + TiDB::DBInfoPtr db_info = databases.getDBInfo(database_id); if (unlikely(db_info == nullptr)) { - LOG_INFO(log, "Try to drop database but not found, may has been dropped, database_id={}", schema_id); + LOG_INFO(log, "Try to drop database but not found, may has been dropped, database_id={}", database_id); return; } { //TODO: it seems may need a lot time, maybe we can do it in a background thread - auto table_ids = table_id_map.findTablesByDatabaseID(schema_id); + auto table_ids = table_id_map.findTablesByDatabaseID(database_id); for (auto table_id : table_ids) - applyDropTable(schema_id, table_id); + applyDropTable(database_id, table_id); } - applyDropSchema(name_mapper.mapDatabaseName(*db_info)); + applyDropDatabaseByName(name_mapper.mapDatabaseName(database_id, keyspace_id)); - databases.eraseDBInfo(schema_id); + databases.eraseDBInfo(database_id); } template -void SchemaBuilder::applyDropSchema(const String & db_name) +void SchemaBuilder::applyDropDatabaseByName(const String & db_name) { GET_METRIC(tiflash_schema_internal_ddl_count, type_drop_db).Increment(); LOG_INFO(log, "Tombstone database begin, db_name={}", db_name); @@ -948,7 +997,7 @@ void SchemaBuilder::applyDropSchema(const String & db_name) // In such way our database (and its belonging tables) will be GC-ed later than TiDB, which is safe and correct. auto & tmt_context = context.getTMTContext(); auto tombstone = tmt_context.getPDClient()->getTS(); - db->alterTombstone(context, tombstone); + db->alterTombstone(context, tombstone, /*new_db_info*/ nullptr); // keep the old db_info LOG_INFO(log, "Tombstone database end, db_name={} tombstone={}", db_name, tombstone); } @@ -1209,7 +1258,7 @@ void SchemaBuilder::syncAllSchema() { break; } - applyCreateSchema(db_info); + applyCreateDatabaseByInfo(db_info); { std::unique_lock created_db_set_lock(created_db_set_mutex); created_db_set.emplace(name_mapper.mapDatabaseName(*db_info)); @@ -1307,7 +1356,7 @@ void SchemaBuilder::syncAllSchema() } if (created_db_set.count(it->first) == 0 && !isReservedDatabase(context, it->first)) { - applyDropSchema(it->first); + applyDropDatabaseByName(it->first); LOG_INFO(log, "Database {} dropped during sync all schemas", it->first); } } @@ -1479,7 +1528,7 @@ void SchemaBuilder::dropAllSchema() { continue; } - applyDropSchema(db.first); + applyDropDatabaseByName(db.first); LOG_INFO(log, "Database {} dropped during drop all schemas", db.first); } diff --git a/dbms/src/TiDB/Schema/SchemaBuilder.h b/dbms/src/TiDB/Schema/SchemaBuilder.h index 53207d8f320..8e84fbeb2df 100644 --- a/dbms/src/TiDB/Schema/SchemaBuilder.h +++ b/dbms/src/TiDB/Schema/SchemaBuilder.h @@ -64,29 +64,29 @@ struct SchemaBuilder bool applyTable(DatabaseID database_id, TableID logical_table_id, TableID physical_table_id, bool force); private: - void applyDropSchema(DatabaseID schema_id); - + void applyDropDatabase(DatabaseID database_id); /// Parameter db_name should be mapped. - void applyDropSchema(const String & db_name); + void applyDropDatabaseByName(const String & db_name); - bool applyCreateSchema(DatabaseID schema_id); + bool applyCreateDatabase(DatabaseID database_id); + void applyCreateDatabaseByInfo(const TiDB::DBInfoPtr & db_info); - void applyCreateSchema(const TiDB::DBInfoPtr & db_info); + void applyRecoverDatabase(DatabaseID database_id); + void applyCreateTable(DatabaseID database_id, TableID table_id); void applyCreateStorageInstance( const TiDB::DBInfoPtr & db_info, const TiDB::TableInfoPtr & table_info, bool is_tombstone); void applyDropTable(DatabaseID database_id, TableID table_id); + /// Parameter schema_name should be mapped. + void applyDropPhysicalTable(const String & db_name, TableID table_id); void applyRecoverTable(DatabaseID database_id, TiDB::TableID table_id); void applyRecoverLogicalTable(const TiDB::DBInfoPtr & db_info, const TiDB::TableInfoPtr & table_info); bool tryRecoverPhysicalTable(const TiDB::DBInfoPtr & db_info, const TiDB::TableInfoPtr & table_info); - /// Parameter schema_name should be mapped. - void applyDropPhysicalTable(const String & db_name, TableID table_id); - void applyPartitionDiff(DatabaseID database_id, TableID table_id); void applyPartitionDiffOnLogicalTable( const TiDB::DBInfoPtr & db_info, @@ -107,8 +107,6 @@ struct SchemaBuilder void applySetTiFlashReplica(DatabaseID database_id, TableID table_id); - void applyCreateTable(DatabaseID database_id, TableID table_id); - void applyExchangeTablePartition(const SchemaDiff & diff); }; diff --git a/dbms/src/TiDB/Schema/SchemaGetter.cpp b/dbms/src/TiDB/Schema/SchemaGetter.cpp index 1197fa3f043..26dae26bb82 100644 --- a/dbms/src/TiDB/Schema/SchemaGetter.cpp +++ b/dbms/src/TiDB/Schema/SchemaGetter.cpp @@ -115,8 +115,7 @@ struct TxnStructure static String hGet(KeyspaceSnapshot & snap, const String & key, const String & field) { String encode_key = encodeHashDataKey(key, field); - String value = snap.Get(encode_key); - return value; + return snap.Get(encode_key); } static String mvccGet(KeyspaceSnapshot & snap, const String & key, const String & field) @@ -273,7 +272,6 @@ TiDB::DBInfoPtr SchemaGetter::getDatabase(DatabaseID db_id) { String key = getDBKey(db_id); String json = TxnStructure::hGet(snap, DBs, key); - if (json.empty()) return nullptr; diff --git a/tests/fullstack-test2/ddl/alter_drop_database.test b/tests/fullstack-test2/ddl/alter_drop_database.test deleted file mode 100644 index 838d46afbcf..00000000000 --- a/tests/fullstack-test2/ddl/alter_drop_database.test +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2023 PingCAP, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -=> DBGInvoke __enable_schema_sync_service('false') ->> DBGInvoke __init_fail_point() - -mysql> drop database if exists d1; -mysql> create database d1; - -=> DBGInvoke __refresh_schemas() - -=> DBGInvoke mapped_database_exists(d1) -┌─mapped_database_exists(d1)───┐ -│ true │ -└──────────────────────────────┘ - -mysql> create table d1.t1 (a int); -mysql> alter table d1.t1 set tiflash replica 1; -mysql> insert into d1.t1 values(1); - -func> wait_table d1 t1 - -mysql> alter table d1.t1 add column b int; - ->> DBGInvoke __enable_fail_point(pause_before_apply_raft_cmd) - -# exactly write until fail point "pause_before_apply_raft_cmd" to be disable -mysql> insert into d1.t1 values(1,2); - -mysql> drop database d1; - -=> DBGInvoke __refresh_schemas() - -# make write cmd take effect ->> DBGInvoke __disable_fail_point(pause_before_apply_raft_cmd) - -# the `t1` is still mark as tombstone ->> select tidb_database,tidb_name from system.tables where is_tombstone = 0 and tidb_database = 'd1' and tidb_name='t1'; -#TODO: check the row is written to the storage or not - diff --git a/tests/fullstack-test2/ddl/flashback/flashback_database.test b/tests/fullstack-test2/ddl/flashback/flashback_database.test new file mode 100644 index 00000000000..dd541b5d2a4 --- /dev/null +++ b/tests/fullstack-test2/ddl/flashback/flashback_database.test @@ -0,0 +1,187 @@ +# Copyright 2023 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +## case 1, normal flashback without failpoints + +mysql> drop database if exists d1; +mysql> drop database if exists d1_new; + +# non-partition table +mysql> create database d1; +mysql> create table d1.t3 (a int); +mysql> insert into d1.t3 values(1); +# partition table +mysql> create table d1.t4(id INT NOT NULL,name VARCHAR(30)) PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (50),PARTITION p1 VALUES LESS THAN (100)); +mysql> insert into d1.t4 values(1, 'abc'),(2, 'cde'),(53, 'efg'); + +mysql> alter table d1.t3 set tiflash replica 1; +mysql> alter table d1.t4 set tiflash replica 1; +func> wait_table d1 t3 t4 + +mysql> alter table d1.t3 add column b int; +mysql> insert into d1.t3 values(2,2); +mysql> alter table d1.t4 add column b int; + +mysql> drop database d1; + +mysql> flashback database d1 to d1_new +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t3 order by a; ++------+------+ +| a | b | ++------+------+ +| 1 | NULL | +| 2 | 2 | ++------+------+ +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t4 order by id; ++----+------+------+ +| id | name | b | ++----+------+------+ +| 1 | abc | NULL | +| 2 | cde | NULL | +| 53 | efg | NULL | ++----+------+------+ + +# ensure the flashbacked table and database is not mark as tombstone +>> DBGInvoke __enable_schema_sync_service('true') +>> DBGInvoke __gc_schemas(18446744073709551615) + +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t3 order by a; ++------+------+ +| a | b | ++------+------+ +| 1 | NULL | +| 2 | 2 | ++------+------+ +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t4 order by id; ++----+------+------+ +| id | name | b | ++----+------+------+ +| 1 | abc | NULL | +| 2 | cde | NULL | +| 53 | efg | NULL | ++----+------+------+ + +=> DBGInvoke __enable_schema_sync_service('false') +>> DBGInvoke __init_fail_point() + +mysql> drop database if exists d1; +mysql> drop database if exists d1_new; + +## case 2, non-partition table +mysql> create database d1; + +=> DBGInvoke __refresh_schemas() + +=> DBGInvoke mapped_database_exists(d1) +┌─mapped_database_exists(d1)───┐ +│ true │ +└──────────────────────────────┘ + +mysql> create table d1.t1 (a int); +mysql> alter table d1.t1 set tiflash replica 1; +mysql> insert into d1.t1 values(1); + +func> wait_table d1 t1 + +mysql> alter table d1.t1 add column b int; + +>> DBGInvoke __enable_fail_point(pause_before_apply_raft_cmd) + +# exactly write until fail point "pause_before_apply_raft_cmd" to be disable +mysql> insert into d1.t1 values(2,2); + +mysql> drop database d1; + +=> DBGInvoke __refresh_schemas() + +# make write cmd take effect +>> DBGInvoke __disable_fail_point(pause_before_apply_raft_cmd) + +# the `t1` is still mark as tombstone +>> select tidb_database,tidb_name,is_tombstone,tidb_table_id from system.tables where is_tombstone = 0 and tidb_database = 'd1' and tidb_name='t1'; +# check the row is written to the storage or not +mysql> flashback database d1 to d1_new +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t1 order by a; ++------+------+ +| a | b | ++------+------+ +| 1 | NULL | +| 2 | 2 | ++------+------+ + +=> DBGInvoke __refresh_schemas() +# ensure the flashbacked table and database is not mark as tombstone +>> DBGInvoke __enable_schema_sync_service('true') +>> DBGInvoke __gc_schemas(18446744073709551615) +>> DBGInvoke __enable_schema_sync_service('false') +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t1 order by a; ++------+------+ +| a | b | ++------+------+ +| 1 | NULL | +| 2 | 2 | ++------+------+ + +mysql> drop database if exists d1; +mysql> drop database if exists d1_new; + +## case 3, partition table +mysql> create database d1; + +=> DBGInvoke __refresh_schemas() + +mysql> create table d1.t2(id INT NOT NULL,name VARCHAR(30)) PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (50),PARTITION p1 VALUES LESS THAN (100)); +mysql> insert into d1.t2 values(1, 'abc'),(2, 'cde'),(53, 'efg'); + +>> DBGInvoke __enable_fail_point(pause_before_apply_raft_cmd) +mysql> alter table d1.t2 set tiflash replica 1; +mysql> alter table d1.t2 add column b int; + +mysql> drop database d1; + +=> DBGInvoke __refresh_schemas() + +# make write cmd take effect +>> DBGInvoke __disable_fail_point(pause_before_apply_raft_cmd) + +# check the row is written to the storage or not +mysql> flashback database d1 to d1_new + +func> wait_table d1_new t2 +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t2 order by id; ++----+------+------+ +| id | name | b | ++----+------+------+ +| 1 | abc | NULL | +| 2 | cde | NULL | +| 53 | efg | NULL | ++----+------+------+ + +=> DBGInvoke __refresh_schemas() +# ensure the flashbacked table and database is not mark as tombstone +>> DBGInvoke __enable_schema_sync_service('true') +>> DBGInvoke __gc_schemas(18446744073709551615) +>> DBGInvoke __enable_schema_sync_service('false') +mysql> set session tidb_isolation_read_engines='tiflash'; select * from d1_new.t2 order by id; ++----+------+------+ +| id | name | b | ++----+------+------+ +| 1 | abc | NULL | +| 2 | cde | NULL | +| 53 | efg | NULL | ++----+------+------+ + +# cleanup +mysql> drop database if exists d1; +mysql> drop database if exists d1_new; diff --git a/tests/fullstack-test2/ddl/partitions/reorganize_partition.test b/tests/fullstack-test2/ddl/partitions/reorganize_partition.test index 7c208d843d8..47482e1c30a 100644 --- a/tests/fullstack-test2/ddl/partitions/reorganize_partition.test +++ b/tests/fullstack-test2/ddl/partitions/reorganize_partition.test @@ -185,4 +185,4 @@ mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t1 | 80 | aaa | 2 | +----+------+------+ -#mysql> drop table test.t1; +mysql> drop table test.t1;