From 0bd45dd2cc854023c3a186ffe5438b5c9b9fb4ec Mon Sep 17 00:00:00 2001 From: Aibek Bukabayev <aibek.bukabayev@percona.com> Date: Wed, 24 Jan 2024 16:26:08 +0600 Subject: [PATCH] PXB-3220 tolerate file deletion between discovery and file open --- storage/innobase/fil/fil0fil.cc | 27 +++++++++--------- .../innobase/xtrabackup/src/ddl_tracker.cc | 28 +++++++++++++++++-- storage/innobase/xtrabackup/src/ddl_tracker.h | 10 +++++++ 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index aa292b536f58..651d06a5671d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1610,7 +1610,6 @@ class Fil_system { @param[in] f Callback @return any error returned by the callback function. */ [[nodiscard]] dberr_t iterate_spaces(Fil_space_iterator::Function &f); - #endif /* XTRABACKUP */ /** Iterate through all persistent tablespace files (FIL_TYPE_TABLESPACE) returning the nodes via callback function cbk. @@ -4097,7 +4096,6 @@ void fil_node_close_file(fil_node_t *file) { shard->mutex_release(); } - #endif /* XTRABACKUP */ /** Iterate through all tablespaces @@ -11593,7 +11591,6 @@ void Tablespace_dirs::open_ibd(const Const_iter &start, const Const_iter &end, size_t thread_id, bool &result) { if (!result) return; - uint8_t max_attempt_retries = (opt_lock_ddl == LOCK_DDL_REDUCED) ? 10 : 1; for (auto it = start; it != end; ++it) { const std::string filename = it->second; const auto &files = m_dirs[it->first]; @@ -11606,17 +11603,19 @@ void Tablespace_dirs::open_ibd(const Const_iter &start, const Const_iter &end, /* cannot use auto [err, space_id] = fil_open_for_xtrabackup() as space_id is unused here and we get unused variable error during compilation */ dberr_t err; - uint8_t attempts = 0; - while (attempts < max_attempt_retries) { - attempts++; - std::tie(err, std::ignore) = fil_open_for_xtrabackup( - phy_filename, filename.substr(0, filename.length() - 4)); - /* PXB-2275 - Allow DB_INVALID_ENCRYPTION_META as we will test it in the - end of the backup */ - if (err == DB_SUCCESS || err == DB_INVALID_ENCRYPTION_META) break; - - if (attempts == max_attempt_retries) result = false; - } + std::tie(err, std::ignore) = fil_open_for_xtrabackup( + phy_filename, filename.substr(0, filename.length() - 4)); + + /* Allow deleted tables between disovery and file open when + LOCK_DDL_REDUCED, they will be handled by ddl_tracker */ + if (err == DB_CANNOT_OPEN_FILE && opt_lock_ddl == LOCK_DDL_REDUCED) { + ddl_tracker->add_missing_table(phy_filename); + } else + /* PXB-2275 - Allow DB_INVALID_ENCRYPTION_META as we will test it in + the end of the backup */ + if (err != DB_SUCCESS && err != DB_INVALID_ENCRYPTION_META) { + result = false; + } } } diff --git a/storage/innobase/xtrabackup/src/ddl_tracker.cc b/storage/innobase/xtrabackup/src/ddl_tracker.cc index 80057522ab29..aed4c61c4ef1 100644 --- a/storage/innobase/xtrabackup/src/ddl_tracker.cc +++ b/storage/innobase/xtrabackup/src/ddl_tracker.cc @@ -121,6 +121,21 @@ void ddl_tracker_t::add_table(const space_id_t &space_id, std::string name) { tables_in_backup[space_id] = name; } +void ddl_tracker_t::add_missing_table(std::string path) { + Fil_path::normalize(path); + if (Fil_path::has_prefix(path, Fil_path::DOT_SLASH)) { + path.erase(0, 2); + } + missing_tables.insert(path); +} + +bool ddl_tracker_t::is_missing_table(const std::string &name) { + if (missing_tables.count(name)) { + return true; + } + return false; +} + /* ======== Data copying thread context ======== */ typedef struct { @@ -226,8 +241,17 @@ void ddl_tracker_t::handle_ddl_operations() { if (check_if_skip_table(table.second.first.c_str())) { continue; } - /* renamed new table. update new table entry to renamed table name */ - if (new_tables.find(table.first) != new_tables.end()) { + + /* renamed new table. update new table entry to renamed table name + or if table is missing and renamed, add the renamed table to the new_table + list. for example: 1. t1.ibd is discovered + 2. t1.ibd renamed to t2.ibd + 3. t2.ibd is opened and loaded to cache to copy + 4. t1.ibd is missing now + so we should add t2.ibd to new_tables and skip .ren file so that we don't + try to rename t1.ibd to t2.idb where t1.ibd is missing */ + if (new_tables.find(table.first) != new_tables.end() || + is_missing_table(table.second.first)) { new_tables[table.first] = table.second.second; continue; } diff --git a/storage/innobase/xtrabackup/src/ddl_tracker.h b/storage/innobase/xtrabackup/src/ddl_tracker.h index 36f6e3c4e6a9..4f09283066cf 100644 --- a/storage/innobase/xtrabackup/src/ddl_tracker.h +++ b/storage/innobase/xtrabackup/src/ddl_tracker.h @@ -35,6 +35,8 @@ class ddl_tracker_t { space_id_to_name_t drops; /* For DDL operation found in redo log, */ std::unordered_map<space_id_t, std::pair<std::string, std::string>> renames; + /** Tables that have been deleted between discovery and file open */ + std::unordered_set<std::string> missing_tables; public: /** Add a new table in the DDL tracker table list. @@ -52,5 +54,13 @@ class ddl_tracker_t { ulint len, lsn_t start_lsn); /** Function responsible to generate files based on DDL operations */ void handle_ddl_operations(); + + /** Note that a table has been deleted between disovery and file open + @param[in] path missing table name with path. */ + void add_missing_table(std::string path); + + /** Check if table is in missing list + @param[in] name tablespace name */ + bool is_missing_table(const std::string &name); }; #endif // DDL_TRACKER_H