From 620cd292c2193db943d0740ae3d87628f23b567c Mon Sep 17 00:00:00 2001 From: Satya Bodapati Date: Wed, 17 Jul 2024 18:12:49 +0100 Subject: [PATCH 1/2] PXB-3295 : Undo tablespaces are not tracked properly with lock-ddl=REDUCED Problem: -------- 1. Undo tablespaces are not tracked properly. Since undo tablespaces are not opened via fil_open_for_xtrabackup(), they are not tracked as 'copied'. This leads to wrong decisions in handle_ddl_operations. 2. When new undo tablespaces are created, Server doesn't write a MLOG_FILE_CREATE record and so these are missed by the tracking system. Fix: ---- 1. track undo tablespaces that xtrabackup copies without lock (before lock state) 2. After lock is taken, undo tablespces are discovered again (after lock state) With this before and after states, we now determine undo files to be deleted, undo files to be copied. Truncated undo tablespace use different tablespace id, so old undo file is marked as deleted and new version of undo tablespace is copied For example undo_001.ibu of space_id 10 is truncated, the filename remains same but it space_id becomes 11. xtrabackup creates 11.ibu.del for undo tablespace to be deleted. then undo_001.ibu.new with space_id 11 is copied under lock --- storage/innobase/fil/fil0fil.cc | 63 ++++++--- storage/innobase/include/fil0fil.h | 9 +- storage/innobase/os/os0file.cc | 4 +- storage/innobase/srv/srv0start.cc | 9 +- .../innobase/xtrabackup/src/ddl_tracker.cc | 130 +++++++++++++++++- storage/innobase/xtrabackup/src/ddl_tracker.h | 8 ++ storage/innobase/xtrabackup/src/xtrabackup.cc | 13 +- storage/innobase/xtrabackup/src/xtrabackup.h | 2 + .../xtrabackup/test/suites/lockless/undo_2.sh | 116 ++++++++++++++++ 9 files changed, 321 insertions(+), 33 deletions(-) create mode 100644 storage/innobase/xtrabackup/test/suites/lockless/undo_2.sh diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 9efde5d00bc..3936d23a904 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -518,8 +518,15 @@ class Tablespace_dirs { void set_scan_dirs(const std::string &directories); /** Discover tablespaces by reading the header from .ibd files. + @param[in] populate_fil_cache if true, tabelspace are loaded to cache + @param[in] is_prep_handled_ddls if true, xtrabackup uses + ibd_open_for_recovery instead of + fil_open_for_xtrabackup() + @param[in] only_undo if true, only the undo tablespaces are + discovered @return DB_SUCCESS if all goes well */ - [[nodiscard]] dberr_t scan(bool populate_fil_cache, bool is_prep_handle_ddls); + [[nodiscard]] dberr_t scan(bool populate_fil_cache, bool is_prep_handle_ddls, + bool only_undo); /** Clear all the tablespace file data but leave the list of scanned directories in place. */ @@ -1700,9 +1707,17 @@ class Fil_system { } /** Scan the directories to build the tablespace ID to file name - mapping table. */ - dberr_t scan(bool populate_fil_cache, bool is_prep_handle_ddls) { - return (m_dirs.scan(populate_fil_cache, is_prep_handle_ddls)); + mapping table + @param[in] populate_fil_cache if true, tabelspace are loaded to cache + @param[in] is_prep_handled_ddls if true, xtrabackup uses + ibd_open_for_recovery instead of + fil_open_for_xtrabackup() + @param[in] only_undo if true, only the undo tablespaces are + discovered + @return DB_SUCCESS on success, other codes on errors */ + dberr_t scan(bool populate_fil_cache, bool is_prep_handle_ddls, + bool only_undo) { + return (m_dirs.scan(populate_fil_cache, is_prep_handle_ddls, only_undo)); } /** Open all known tablespaces. */ @@ -11964,10 +11979,14 @@ void Tablespace_dirs::set_scan_dirs(const std::string &in_directories) { } /** Discover tablespaces by reading the header from .ibd files. -@param[in] in_directories Directories to scan +@param[in] populate_fil_cache if true, tabelspace are loaded to cache +@param[in] is_prep_handled_ddls if true, xtrabackup uses ibd_open_for_recovery + instead of fil_open_for_xtrabackup() +@param[in] only_undo if true, only the undo tablespaces are +discovered @return DB_SUCCESS if all goes well */ -dberr_t Tablespace_dirs::scan(bool populate_fil_cache, - bool is_prep_handle_ddls) { +dberr_t Tablespace_dirs::scan(bool populate_fil_cache, bool is_prep_handle_ddls, + bool only_undo) { Scanned_files ibd_files; Scanned_files undo_files; uint16_t count = 0; @@ -11982,9 +12001,10 @@ dberr_t Tablespace_dirs::scan(bool populate_fil_cache, ib::info(ER_IB_MSG_379) << "Scanning '" << dir.path() << "'"; - /* Walk the sub-tree of dir. */ - - Dir_Walker::walk(real_path_dir, true, [&](const std::string &path) { + /* Walk the sub-tree of dir. If it is undo tablespaces only discovery, + used by xtrabackup, we dont do look into sub directories */ + bool walk_subtree = only_undo ? false : true; + Dir_Walker::walk(real_path_dir, walk_subtree, [&](const std::string &path) { /* If it is a file and the suffix matches ".ibd" or the undo file name format then store it for determining the space ID. */ @@ -12001,11 +12021,12 @@ dberr_t Tablespace_dirs::scan(bool populate_fil_cache, using Value = Scanned_files::value_type; - if (Fil_path::has_suffix(IBD, file.c_str())) { - ibd_files.push_back(Value{count, file}); - - } else if (Fil_path::is_undo_tablespace_name(file)) { + if (Fil_path::is_undo_tablespace_name(file)) { undo_files.push_back(Value{count, file}); + } else if (only_undo) { + return; + } else if (Fil_path::has_suffix(IBD, file.c_str())) { + ibd_files.push_back(Value{count, file}); } if (std::chrono::steady_clock::now() - start_time >= PRINT_INTERVAL) { @@ -12055,7 +12076,7 @@ dberr_t Tablespace_dirs::scan(bool populate_fil_cache, check = std::bind(&Tablespace_dirs::duplicate_check, this, _1, _2, _3, _4, _5, _6); - if (!populate_fil_cache) { + if (!populate_fil_cache && ibd_files.size() > 0) { par_for(PFS_NOT_INSTRUMENTED, ibd_files, n_threads, check, &m, &unique, &duplicates); } @@ -12081,7 +12102,7 @@ dberr_t Tablespace_dirs::scan(bool populate_fil_cache, debug_sync_point("xtrabackup_suspend_between_file_discovery_and_open"); - if (err == DB_SUCCESS && populate_fil_cache) { + if (err == DB_SUCCESS && populate_fil_cache && !only_undo) { bool result = true; std::function @@ -12105,11 +12126,15 @@ void fil_set_scan_dirs(const std::string &directories) { } /** Discover tablespaces by reading the header from .ibd files. -@param[in] populate_fil_cache Whether to load tablespaces into fil cache +@param[in] populate_fil_cache Whether to load tablespaces into fil cache +@param[in] is_prep_handled_ddls if true, xtrabackup uses ibd_open_for_recovery + instead of fil_open_for_xtrabackup() +@param[in] only_undo if true, only the undo tablespaces are + discovered @return DB_SUCCESS if all goes well */ dberr_t fil_scan_for_tablespaces(bool populate_fil_cache, - bool is_prep_handle_ddls) { - return (fil_system->scan(populate_fil_cache, is_prep_handle_ddls)); + bool is_prep_handle_ddls, bool only_undo) { + return (fil_system->scan(populate_fil_cache, is_prep_handle_ddls, only_undo)); } /** Open all known tablespaces. */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index ed5aa3529df..7434f11e491 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -2240,12 +2240,13 @@ void fil_set_scan_dir(const std::string &directory, bool is_undo_dir = false); void fil_set_scan_dirs(const std::string &directories); /** Discover tablespaces by reading the header from .ibd files. -@param[in] populate_fil_cache Whether to load tablespaces into fil cache -@param[in] is_prep_handle_ddls Whether loading tablespaces on prepare phase - to handle the ddls +@param[in] populate_fil_cache Whether to load tablespaces into fil cache +@param[in] is_prep_handle_ddls Whether loading tablespaces on prepare phase + to handle the ddls +@param[in] only_undo if true, only the undo tablespaces are discovered @return DB_SUCCESS if all goes well */ dberr_t fil_scan_for_tablespaces(bool populate_fil_cache, - bool is_prep_handle_ddls); + bool is_prep_handle_ddls, bool only_undo); /** Open the tablespace and also get the tablespace filenames, space_id must already be known. diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index a537c44f5f7..6567ad7a6a2 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3708,8 +3708,8 @@ void Dir_Walker::walk_posix(const Path &basedir, bool recursive, Function &&f) { continue; } - if (file_type == OS_FILE_TYPE_DIR && recursive) { - directories.push(Entry(path, current.m_depth + 1)); + if (file_type == OS_FILE_TYPE_DIR) { + if (recursive) directories.push(Entry(path, current.m_depth + 1)); } else { f(path, current.m_depth + 1); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 3577bc515af..ac2b2aa6334 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -675,6 +675,13 @@ dberr_t srv_undo_tablespace_open(undo::Tablespace &undo_space) { } } + // Track undo tablespaces that are found after server is locked + // if lock_ddl is REDUCED, we will do one more undo scan via + // srv_undo_tablespaces_init()/open() + if (ddl_tracker && is_server_locked()) { + ddl_tracker->add_undo_tablespace(space_id, file_name); + } + if (undo::is_reserved(space_id)) { undo::spaces->add(undo_space); } @@ -1782,7 +1789,7 @@ dberr_t srv_start(bool create_new_db IF_XB(, lsn_t to_lsn)) { return (srv_init_abort(err)); } - err = fil_scan_for_tablespaces(false, false); + err = fil_scan_for_tablespaces(false, false, false); if (err != DB_SUCCESS) { return (srv_init_abort(err)); diff --git a/storage/innobase/xtrabackup/src/ddl_tracker.cc b/storage/innobase/xtrabackup/src/ddl_tracker.cc index ad598d49fc2..ca43631034d 100644 --- a/storage/innobase/xtrabackup/src/ddl_tracker.cc +++ b/storage/innobase/xtrabackup/src/ddl_tracker.cc @@ -23,9 +23,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include #include "backup_copy.h" #include "file_utils.h" +#include "fsp0fsp.h" // fsp_is_undo_tablespace #include "sql_thd_internal_api.h" // create_thd, destroy_thd -#include "xb0xb.h" // check_if_skip_table -#include "xtrabackup.h" // datafiles_iter_t +#include "srv0start.h" +#include "xb0xb.h" // check_if_skip_table +#include "xtrabackup.h" // datafiles_iter_t void ddl_tracker_t::backup_file_op(uint32_t space_id, mlog_id_t type, const byte *buf, ulint len, @@ -78,6 +80,17 @@ void ddl_tracker_t::add_table_from_ibd_scan(const space_id_t space_id, tables_in_backup[space_id] = name; } +void ddl_tracker_t::add_undo_tablespace(const space_id_t space_id, + std::string name) { + Fil_path::normalize(name); + std::lock_guard lock(m_ddl_tracker_mutex); + if (is_server_locked()) { + after_lock_undo[name] = space_id; + } else { + before_lock_undo[name] = space_id; + } +} + void ddl_tracker_t::add_corrupted_tablespace(const space_id_t space_id, const std::string &path) { std::lock_guard lock(m_ddl_tracker_mutex); @@ -87,6 +100,13 @@ void ddl_tracker_t::add_corrupted_tablespace(const space_id_t space_id, void ddl_tracker_t::add_to_recopy_tables(space_id_t space_id, lsn_t start_lsn, const std::string operation) { + // There should never be MLOG_INDEX_LOAD. However MLOG_WRITE_STRING on + // new undo tabelsapce creation is possible. But we ignore this as the UNDOs + // are tracked separately + if (fsp_is_undo_tablespace(space_id)) { + return; + } + std::lock_guard lock(m_ddl_tracker_mutex); recopy_tables.insert(space_id); xb::info() << "DDL tracking : LSN: " << start_lsn << " " << operation @@ -105,6 +125,11 @@ void ddl_tracker_t::add_missing_table(std::string path) { void ddl_tracker_t::add_create_table_from_redo(const space_id_t space_id, lsn_t start_lsn, const char *name) { + // undo tablespaces are tracked separately. + if (fsp_is_undo_tablespace(space_id)) { + return; + } + std::string new_space_name = name; Fil_path::normalize(new_space_name); if (Fil_path::has_prefix(new_space_name, Fil_path::DOT_SLASH)) { @@ -147,6 +172,11 @@ void ddl_tracker_t::add_rename_table_from_redo(const space_id_t space_id, void ddl_tracker_t::add_drop_table_from_redo(const space_id_t space_id, lsn_t start_lsn, const char *name) { + // undo tablespaces are tracked separately. + if (fsp_is_undo_tablespace(space_id)) { + return; + } + std::string new_space_name{name}; Fil_path::normalize(new_space_name); if (Fil_path::has_prefix(new_space_name, Fil_path::DOT_SLASH)) { @@ -169,6 +199,13 @@ bool ddl_tracker_t::is_missing_table(const std::string &name) { void ddl_tracker_t::add_renamed_table(const space_id_t &space_id, std::string new_name) { + // undo tablespaces are tracked separately. + if (fsp_is_undo_tablespace(space_id)) { + // MLOG_FILE_RENAME is never done for undo tablespace + ut_ad(0); + return; + } + Fil_path::normalize(new_name); if (Fil_path::has_prefix(new_name, Fil_path::DOT_SLASH)) { new_name.erase(0, 2); @@ -233,15 +270,89 @@ std::string ddl_tracker_t::convert_file_name(space_id_t space_id, return file_name.substr(0, sep_pos + 1) + std::to_string(space_id) + ext; } +// Helper function to print the contents of a vector of pairs +void printVector(const filevec &vec) { + for (const auto &element : vec) { + xb::info() << element.first << ": " << element.second << " "; + } +} + +// Function to find new, deleted, and changed files between two unordered_maps +std::tuple findChanges(const name_to_space_id_t &before, + const name_to_space_id_t &after) { + filevec newFiles; + filevec deletedOrChangedFiles; + + // Iterate through the after map to find new, changed, and unchanged files + for (const auto &pair : after) { + auto itBefore = before.find(pair.first); + if (itBefore == before.end()) { + // Element is new + newFiles.emplace_back(pair.first, pair.second); + } else { + // Element exists in before map + if (itBefore->second != pair.second) { + // Element value has changed + deletedOrChangedFiles.emplace_back( + pair.first, itBefore->second); // Use old value from before map + newFiles.emplace_back(pair.first, pair.second); + } + } + } + + // Look for deleted + for (const auto &pair : before) { + auto itAfter = after.find(pair.first); + + if (itAfter == after.end()) { + // Element is not present in the after map. This is deleted + deletedOrChangedFiles.emplace_back(pair.first, pair.second); + } + } + + return {newFiles, deletedOrChangedFiles}; +} + +std::tuple ddl_tracker_t::handle_undo_ddls() { + xb::info() << "DDL tracking: handling undo DDLs"; + + undo_spaces_deinit(); + undo_spaces_init(); + xb_scan_for_tablespaces(false, true); + + // Generates the after_lock_undo list + srv_undo_tablespaces_init(false, true); + + auto [newfiles, deletedOrChangedFiles] = + findChanges(before_lock_undo, after_lock_undo); + + // Print the results + xb::info() << "New UNDO files: "; + printVector(newfiles); + + xb::info() << "Deleted or truncated UNDO files: "; + printVector(deletedOrChangedFiles); + + return {newfiles, deletedOrChangedFiles}; +} + void ddl_tracker_t::handle_ddl_operations() { + fil_close_all_files(); + fil_close(); + fil_init(LONG_MAX); + + auto [new_undo_files, deleted_undo_files] = handle_undo_ddls(); + xb::info() << "DDL tracking : handling DDL operations"; if (new_tables.empty() && renames.empty() && drops.empty() && - recopy_tables.empty() && corrupted_tablespaces.empty()) { + recopy_tables.empty() && corrupted_tablespaces.empty() && + new_undo_files.empty() && deleted_undo_files.empty()) { xb::info() << "DDL tracking : Finished handling DDL operations - No changes"; return; } + dberr_t err; for (auto &tablespace : corrupted_tablespaces) { @@ -333,7 +444,6 @@ void ddl_tracker_t::handle_ddl_operations() { "%s", table.second.second.c_str()); } - fil_close_all_files(); for (auto table = new_tables.begin(); table != new_tables.end();) { if (check_if_skip_table(table->second.c_str())) { table = new_tables.erase(table); @@ -344,6 +454,18 @@ void ddl_tracker_t::handle_ddl_operations() { table++; } + // Create .del files for deleted undo tablespaces + for (auto &elem : deleted_undo_files) { + backup_file_printf( + convert_file_name(elem.second, elem.first, ".ibu.del").c_str(), "%s", + ""); + } + + // Add new undo files to be recopied + for (auto &elem : new_undo_files) { + new_tables[elem.second] = elem.first; + } + if (new_tables.empty()) return; /* Create data copying threads */ diff --git a/storage/innobase/xtrabackup/src/ddl_tracker.h b/storage/innobase/xtrabackup/src/ddl_tracker.h index 092557420b7..27fa9dd61a5 100644 --- a/storage/innobase/xtrabackup/src/ddl_tracker.h +++ b/storage/innobase/xtrabackup/src/ddl_tracker.h @@ -23,7 +23,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include "log0types.h" #include "mtr0types.h" typedef std::unordered_map space_id_to_name_t; +typedef std::unordered_map name_to_space_id_t; typedef std::unordered_map meta_map_t; +using filevec = std::vector>; extern meta_map_t meta_map; @@ -32,6 +34,8 @@ class ddl_tracker_t { space_id_to_name_t tables_in_backup; /** Tablspaces with their ID and name, as they were copied to backup.*/ space_id_to_name_t new_tables; + name_to_space_id_t before_lock_undo; + name_to_space_id_t after_lock_undo; /** Tablespaces involved in encryption or bulk index load.*/ std::unordered_set recopy_tables; /** Drop operations found in redo log. */ @@ -53,7 +57,11 @@ class ddl_tracker_t { recopy_tables concurrently */ std::mutex m_ddl_tracker_mutex; + std::tuple handle_undo_ddls(); + public: + void add_undo_tablespace(const space_id_t space_id, std::string name); + /** Add a new table in the DDL tracker table list. @param[in] space_id tablespace identifier @param[in] name tablespace name */ diff --git a/storage/innobase/xtrabackup/src/xtrabackup.cc b/storage/innobase/xtrabackup/src/xtrabackup.cc index 79aeaebb7ed..91924e87aa7 100644 --- a/storage/innobase/xtrabackup/src/xtrabackup.cc +++ b/storage/innobase/xtrabackup/src/xtrabackup.cc @@ -2469,7 +2469,7 @@ static bool innodb_init_param(void) { return (true); } -static void xb_scan_for_tablespaces(bool is_prep_handle_ddls) { +void xb_scan_for_tablespaces(bool is_prep_handle_ddls, bool only_undo) { /* This is the default directory for IBD and IBU files. Put it first in the list of known directories. */ fil_set_scan_dir(MySQL_datadir_path.path()); @@ -2488,7 +2488,8 @@ static void xb_scan_for_tablespaces(bool is_prep_handle_ddls) { --innodb-undo-directory also. */ fil_set_scan_dir(Fil_path::remove_quotes(MySQL_undo_path), true); - if (fil_scan_for_tablespaces(true, is_prep_handle_ddls) != DB_SUCCESS) { + if (fil_scan_for_tablespaces(true, is_prep_handle_ddls, only_undo) != + DB_SUCCESS) { exit(EXIT_FAILURE); } } @@ -3362,6 +3363,11 @@ static void data_copy_thread_func(data_thread_ctxt_t *ctxt) { if (xtrabackup_copy_datafile(node, num)) { xb::error() << "failed to copy datafile " << node->name; *(ctxt->error) = true; + } else { + if (ddl_tracker && fsp_is_undo_tablespace(node->space->id)) { + ddl_tracker->add_undo_tablespace(node->space->id, + node->space->files.front().name); + } } } @@ -3615,7 +3621,7 @@ static dberr_t xb_load_tablespaces(bool is_prep_handle_ddls) } xb::info() << "Generating a list of tablespaces"; - xb_scan_for_tablespaces(is_prep_handle_ddls); + xb_scan_for_tablespaces(is_prep_handle_ddls, false); /* Add separate undo tablespaces to fil_system */ @@ -7045,6 +7051,7 @@ static void xtrabackup_prepare_func(int argc, char **argv) { xb_data_files_close(); fil_close(); innodb_free_param(); + undo_spaces_deinit(); /* Handle `CREATE` DDL files produced by DDL tracking during backup */ if (xtrabackup_incremental_dir) { diff --git a/storage/innobase/xtrabackup/src/xtrabackup.h b/storage/innobase/xtrabackup/src/xtrabackup.h index 6613badcb42..6d427775fdd 100644 --- a/storage/innobase/xtrabackup/src/xtrabackup.h +++ b/storage/innobase/xtrabackup/src/xtrabackup.h @@ -342,4 +342,6 @@ bool xb_process_datadir(const char *path, /*! >( tee $XB_ERROR_LOG)& + +job_pid=$! +pid_file=$topdir/backup/xtrabackup_debug_sync +wait_for_xb_to_suspend $pid_file +xb_pid=`cat $pid_file` +echo "backup pid is $job_pid" + +UNDO_2_BI_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_3'") +mysql -e "ALTER UNDO TABLESPACE UNDO_2 SET INACTIVE" +mysql -e "SET GLOBAL innodb_purge_rseg_truncate_frequency=1" +sleep 1 +UNDO_2_BI_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_3'") +mysql -e "DROP UNDO TABLESPACE UNDO_2" + +# before inactive +UNDO_3_BI_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_3'") + +mysql -e "ALTER UNDO TABLESPACE UNDO_3 SET INACTIVE" +mysql -e "SET GLOBAL innodb_purge_rseg_truncate_frequency=1" +sleep 2 + +# after inactive +UNDO_3_AI_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_3'") +mysql -e "CREATE UNDO TABLESPACE UNDO_4 ADD DATAFILE 'undo_4.ibu'" + +# Resume the xtrabackup process +vlog "Resuming xtrabackup" +kill -SIGCONT $xb_pid +run_cmd wait $job_pid + +UNDO_1_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_1'") +UNDO_4_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_4'") + +xtrabackup --prepare --target-dir=$BACKUP_DIR +stop_server + +rm -rf $mysql_datadir/* +xtrabackup --copy-back --target-dir=$BACKUP_DIR +start_server + +UNDO_BACKUP_1_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_1'") +UNDO_BACKUP_2_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_2'") +UNDO_BACKUP_3_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_3'") +UNDO_BACKUP_4_SPACE_ID=$($MYSQL $MYSQL_ARGS -BN -e "select space from information_schema.innodb_tablespaces where name = 'UNDO_4'") + +echo "UNDO_1 space_id is $UNDO_BACKUP_1_SPACE_ID" +echo "UNDO_2 space_id is $UNDO_BACKUP_2_SPACE_ID" +echo "UNDO_3 space_id is $UNDO_BACKUP_3_SPACE_ID" +echo "UNDO_4 space_id is $UNDO_BACKUP_4_SPACE_ID" + +# UNDO_1 no space_id change +if [ $UNDO_1_SPACE_ID != $UNDO_BACKUP_1_SPACE_ID ]; then + echo "space_id of undo_01 shouldn't have changed. Before backup: undo_1 space_id $UNDO_1_SPACE_ID. After backup and restore undo_1 space_id is $UNDO_BACKUP_1_SPACE_ID" + exit 1 +fi + +## UNDO_4 no space_id change. If we get this it means undo_04 is copied. +#FILE=$BACKUP_DIR/undo_4.ibu +#[ -f $FILE ] || die "$FILE did NOT exist. It should have been backuped. It is created before end of backup. Server did CREATE UNDO TABLESPACE undo_04, right before DDL lock is taken" +# +#if [ -z ${UNDO_BACKUP_4_SPACE_ID+x} ]; then +# echo "UNDO TABLESPACE 4 should have been present in backup. But it is not found." +# exit 1 +#if +# +#if [ $UNDO_4_SPACE_ID != $UNDO_BACKUP_4_SPACE_ID ]; then +# echo "space_id of undo_04 shouldn't have changed. Before backup: undo_4 space_id $UNDO_4_SPACE_ID. After backup and restore undo_4 space_id is $UNDO_BACKUP_4_SPACE_ID" +# exit 1 +#fi + +# UND0_3 should have AI space_id and not BI space_id +if [ $UNDO_3_AI_SPACE_ID != $UNDO_BACKUP_3_SPACE_ID ]; then + echo "space_id of undo_03 should have space_id after truncation. space_id at time of the backup: undo_3 space_id $UNDO_3_AF_SPACE_ID. After backup and restore undo_1 space_id is $UNDO_BACKUP_3_SPACE_ID" + exit 1 +fi + +# UNDO_3 shouldn't have space_id before truncation +if [ $UNDO_3_BI_SPACE_ID == $UNDO_BACKUP_3_SPACE_ID ]; then + echo "space_id of undo_03 should NOT have space_id before truncation. space_id before_truncation undo_3 space_id $UNDO_3_BI_SPACE_ID. After backup and restore undo_1 space_id is $UNDO_BACKUP_3_SPACE_ID" + exit 1 +fi + +FILE=$BACKUP_DIR/undo_2.ibu +[ ! -f $FILE ] || die "$FILE exists. It should have been deleted by prepare. Server did DROP UNDO TABLESPACE undo_02" + +# UNDO_2 should be empty because it was dropped. We should also check physical presence of undo_02.ibu file +if [ ! -z "${UNDO_BACKUP_2_SPACE_ID}" ]; then + echo "UNDO TABLESPACE 2 should have been dropped in backup. Found UNDO_2 with space_id: $UNDO_BACKUP_2_SPACE_ID" + exit 1 +fi + + +stop_server + +rm -rf $mysql_datadir $BACKUP_DIR +rm $XB_ERROR_LOG From 49c8a34e183ab8709f2b96c73bb3b93b2cc1b0d3 Mon Sep 17 00:00:00 2001 From: Satya Bodapati Date: Thu, 18 Jul 2024 11:29:11 +0100 Subject: [PATCH 2/2] PXB-3295: fix testcase --- storage/innobase/srv/srv0start.cc | 10 ++++++---- storage/innobase/xtrabackup/src/ddl_tracker.cc | 8 ++++---- .../innobase/xtrabackup/test/suites/lockless/undo.sh | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ac2b2aa6334..2525dfe8128 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -657,10 +657,12 @@ dberr_t srv_undo_tablespace_open(undo::Tablespace &undo_space) { } DBUG_EXECUTE_IF( - "undo_space_open", - if (strncmp(file_name, "./undo_1.ibu", strlen("./undo_1.ibu")) == 0) { - *const_cast(&xtrabackup_debug_sync) = "undo_space_open"; - debug_sync_point("undo_space_open"); + "undo_space_open", if (!is_server_locked()) { + if (strncmp(file_name, "./undo_1.ibu", strlen("./undo_1.ibu")) == 0) { + *const_cast(&xtrabackup_debug_sync) = + "undo_space_open"; + debug_sync_point("undo_space_open"); + } }); /* Now that space and node exist, make sure this undo tablespace diff --git a/storage/innobase/xtrabackup/src/ddl_tracker.cc b/storage/innobase/xtrabackup/src/ddl_tracker.cc index ca43631034d..06b030d8bd9 100644 --- a/storage/innobase/xtrabackup/src/ddl_tracker.cc +++ b/storage/innobase/xtrabackup/src/ddl_tracker.cc @@ -271,9 +271,9 @@ std::string ddl_tracker_t::convert_file_name(space_id_t space_id, } // Helper function to print the contents of a vector of pairs -void printVector(const filevec &vec) { +void printVector(const std::string &operation, const filevec &vec) { for (const auto &element : vec) { - xb::info() << element.first << ": " << element.second << " "; + xb::info() << operation << element.first << " : " << element.second << " "; } } @@ -328,10 +328,10 @@ std::tuple ddl_tracker_t::handle_undo_ddls() { // Print the results xb::info() << "New UNDO files: "; - printVector(newfiles); + printVector("New undo file: ", newfiles); xb::info() << "Deleted or truncated UNDO files: "; - printVector(deletedOrChangedFiles); + printVector("Deleted undo file: ", deletedOrChangedFiles); return {newfiles, deletedOrChangedFiles}; } diff --git a/storage/innobase/xtrabackup/test/suites/lockless/undo.sh b/storage/innobase/xtrabackup/test/suites/lockless/undo.sh index fe4fe3bbaf5..eeea4d26617 100644 --- a/storage/innobase/xtrabackup/test/suites/lockless/undo.sh +++ b/storage/innobase/xtrabackup/test/suites/lockless/undo.sh @@ -54,11 +54,11 @@ vlog "Resuming xtrabackup" kill -SIGCONT $xb_pid run_cmd wait $job_pid -if ! egrep -q 'DDL tracking : LSN: [0-9]* delete space ID: [0-9]* Name: undo_1.ibu' $topdir/backup.log ; then +if ! egrep -q 'Deleted undo file: ./undo_1.ibu : [0-9]*' $topdir/backup.log ; then die "xtrabackup did not handle delete table DDL" fi -if ! egrep -q 'DDL tracking : LSN: [0-9]* create space ID: [0-9]* Name: undo_1.ibu' $topdir/backup.log ; then +if ! egrep -q 'New undo file: ./undo_1.ibu : [0-9]*' $topdir/backup.log ; then die "xtrabackup did not handle new table DDL" fi