mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
MDEV-21168: Active XA transactions stop slave from working after backup
was restored. Optionally rollback prepared XA's on "mariabackup --prepare". The fix MUST NOT be ported on 10.5+, as MDEV-742 fix solves the issue for slaves.
This commit is contained in:
parent
cd88a606f5
commit
5836191c8f
12 changed files with 682 additions and 432 deletions
|
|
@ -71,6 +71,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|||
#include <srv0start.h>
|
||||
#include "trx0sys.h"
|
||||
#include <buf0dblwr.h>
|
||||
#include "ha_innodb.h"
|
||||
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
|
@ -120,6 +121,8 @@ my_bool xtrabackup_print_param;
|
|||
|
||||
my_bool xtrabackup_export;
|
||||
|
||||
my_bool xtrabackup_rollback_xa;
|
||||
|
||||
longlong xtrabackup_use_memory;
|
||||
|
||||
uint opt_protocol;
|
||||
|
|
@ -741,6 +744,7 @@ enum options_xtrabackup
|
|||
OPT_XTRA_BACKUP,
|
||||
OPT_XTRA_PREPARE,
|
||||
OPT_XTRA_EXPORT,
|
||||
OPT_XTRA_ROLLBACK_XA,
|
||||
OPT_XTRA_PRINT_PARAM,
|
||||
OPT_XTRA_USE_MEMORY,
|
||||
OPT_XTRA_THROTTLE,
|
||||
|
|
@ -836,85 +840,120 @@ enum options_xtrabackup
|
|||
OPT_XTRA_CHECK_PRIVILEGES
|
||||
};
|
||||
|
||||
struct my_option xb_client_options[] =
|
||||
{
|
||||
{"verbose", 'V', "display verbose output",
|
||||
(G_PTR*) &verbose, (G_PTR*) &verbose, 0, GET_BOOL, NO_ARG,
|
||||
FALSE, 0, 0, 0, 0, 0},
|
||||
struct my_option xb_client_options[]= {
|
||||
{"verbose", 'V', "display verbose output", (G_PTR *) &verbose,
|
||||
(G_PTR *) &verbose, 0, GET_BOOL, NO_ARG, FALSE, 0, 0, 0, 0, 0},
|
||||
{"version", 'v', "print xtrabackup version information",
|
||||
(G_PTR *) &xtrabackup_version, (G_PTR *) &xtrabackup_version, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"target-dir", OPT_XTRA_TARGET_DIR, "destination directory", (G_PTR*) &xtrabackup_target_dir,
|
||||
(G_PTR*) &xtrabackup_target_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"target-dir", OPT_XTRA_TARGET_DIR, "destination directory",
|
||||
(G_PTR *) &xtrabackup_target_dir, (G_PTR *) &xtrabackup_target_dir, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"backup", OPT_XTRA_BACKUP, "take backup to target-dir",
|
||||
(G_PTR*) &xtrabackup_backup, (G_PTR*) &xtrabackup_backup,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"prepare", OPT_XTRA_PREPARE, "prepare a backup for starting mysql server on the backup.",
|
||||
(G_PTR*) &xtrabackup_prepare, (G_PTR*) &xtrabackup_prepare,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"export", OPT_XTRA_EXPORT, "create files to import to another database when prepare.",
|
||||
(G_PTR*) &xtrabackup_export, (G_PTR*) &xtrabackup_export,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"print-param", OPT_XTRA_PRINT_PARAM, "print parameter of mysqld needed for copyback.",
|
||||
(G_PTR*) &xtrabackup_print_param, (G_PTR*) &xtrabackup_print_param,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"use-memory", OPT_XTRA_USE_MEMORY, "The value is used instead of buffer_pool_size",
|
||||
(G_PTR*) &xtrabackup_use_memory, (G_PTR*) &xtrabackup_use_memory,
|
||||
0, GET_LL, REQUIRED_ARG, 100*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
|
||||
(G_PTR *) &xtrabackup_backup, (G_PTR *) &xtrabackup_backup, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"prepare", OPT_XTRA_PREPARE,
|
||||
"prepare a backup for starting mysql server on the backup.",
|
||||
(G_PTR *) &xtrabackup_prepare, (G_PTR *) &xtrabackup_prepare, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"export", OPT_XTRA_EXPORT,
|
||||
"create files to import to another database when prepare.",
|
||||
(G_PTR *) &xtrabackup_export, (G_PTR *) &xtrabackup_export, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"rollback-xa", OPT_XTRA_ROLLBACK_XA,
|
||||
"Rollback prepared XA's on --prepare. "
|
||||
"After preparing target directory with this option "
|
||||
"it can no longer be a base for incremental backup.",
|
||||
(G_PTR *) &xtrabackup_rollback_xa, (G_PTR *) &xtrabackup_rollback_xa, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"print-param", OPT_XTRA_PRINT_PARAM,
|
||||
"print parameter of mysqld needed for copyback.",
|
||||
(G_PTR *) &xtrabackup_print_param, (G_PTR *) &xtrabackup_print_param, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"use-memory", OPT_XTRA_USE_MEMORY,
|
||||
"The value is used instead of buffer_pool_size",
|
||||
(G_PTR *) &xtrabackup_use_memory, (G_PTR *) &xtrabackup_use_memory, 0,
|
||||
GET_LL, REQUIRED_ARG, 100 * 1024 * 1024L, 1024 * 1024L, LONGLONG_MAX, 0,
|
||||
1024 * 1024L, 0},
|
||||
{"throttle", OPT_XTRA_THROTTLE, "limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')",
|
||||
(G_PTR*) &xtrabackup_throttle, (G_PTR*) &xtrabackup_throttle,
|
||||
0, GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0},
|
||||
{"throttle", OPT_XTRA_THROTTLE,
|
||||
"limit count of IO operations (pairs of read&write) per second to IOS "
|
||||
"values (for '--backup')",
|
||||
(G_PTR *) &xtrabackup_throttle, (G_PTR *) &xtrabackup_throttle, 0,
|
||||
GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0},
|
||||
{"log", OPT_LOG, "Ignored option for MySQL option compatibility",
|
||||
(G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0,
|
||||
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"log-copy-interval", OPT_XTRA_LOG_COPY_INTERVAL, "time interval between checks done by log copying thread in milliseconds (default is 1 second).",
|
||||
(G_PTR*) &xtrabackup_log_copy_interval, (G_PTR*) &xtrabackup_log_copy_interval,
|
||||
0, GET_LONG, REQUIRED_ARG, 1000, 0, LONG_MAX, 0, 1, 0},
|
||||
{"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR, "(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory.",
|
||||
(G_PTR*) &xtrabackup_extra_lsndir, (G_PTR*) &xtrabackup_extra_lsndir,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"incremental-lsn", OPT_XTRA_INCREMENTAL, "(for --backup): copy only .ibd pages newer than specified LSN 'high:low'. ##ATTENTION##: If a wrong LSN value is specified, it is impossible to diagnose this, causing the backup to be unusable. Be careful!",
|
||||
(G_PTR*) &xtrabackup_incremental, (G_PTR*) &xtrabackup_incremental,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"incremental-basedir", OPT_XTRA_INCREMENTAL_BASEDIR, "(for --backup): copy only .ibd pages newer than backup at specified directory.",
|
||||
(G_PTR*) &xtrabackup_incremental_basedir, (G_PTR*) &xtrabackup_incremental_basedir,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, "(for --prepare): apply .delta files and logfile in the specified directory.",
|
||||
(G_PTR*) &xtrabackup_incremental_dir, (G_PTR*) &xtrabackup_incremental_dir,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(G_PTR *) &log_ignored_opt, (G_PTR *) &log_ignored_opt, 0, GET_STR,
|
||||
OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"log-copy-interval", OPT_XTRA_LOG_COPY_INTERVAL,
|
||||
"time interval between checks done by log copying thread in milliseconds "
|
||||
"(default is 1 second).",
|
||||
(G_PTR *) &xtrabackup_log_copy_interval,
|
||||
(G_PTR *) &xtrabackup_log_copy_interval, 0, GET_LONG, REQUIRED_ARG, 1000,
|
||||
0, LONG_MAX, 0, 1, 0},
|
||||
{"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR,
|
||||
"(for --backup): save an extra copy of the xtrabackup_checkpoints file "
|
||||
"in this directory.",
|
||||
(G_PTR *) &xtrabackup_extra_lsndir, (G_PTR *) &xtrabackup_extra_lsndir, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"incremental-lsn", OPT_XTRA_INCREMENTAL,
|
||||
"(for --backup): copy only .ibd pages newer than specified LSN "
|
||||
"'high:low'. ##ATTENTION##: If a wrong LSN value is specified, it is "
|
||||
"impossible to diagnose this, causing the backup to be unusable. Be "
|
||||
"careful!",
|
||||
(G_PTR *) &xtrabackup_incremental, (G_PTR *) &xtrabackup_incremental, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"incremental-basedir", OPT_XTRA_INCREMENTAL_BASEDIR,
|
||||
"(for --backup): copy only .ibd pages newer than backup at specified "
|
||||
"directory.",
|
||||
(G_PTR *) &xtrabackup_incremental_basedir,
|
||||
(G_PTR *) &xtrabackup_incremental_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
{"incremental-dir", OPT_XTRA_INCREMENTAL_DIR,
|
||||
"(for --prepare): apply .delta files and logfile in the specified "
|
||||
"directory.",
|
||||
(G_PTR *) &xtrabackup_incremental_dir,
|
||||
(G_PTR *) &xtrabackup_incremental_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
0, 0, 0},
|
||||
{"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.",
|
||||
(G_PTR*) &xtrabackup_tables, (G_PTR*) &xtrabackup_tables,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"tables_file", OPT_XTRA_TABLES_FILE, "filtering by list of the exact database.table name in the file.",
|
||||
(G_PTR*) &xtrabackup_tables_file, (G_PTR*) &xtrabackup_tables_file,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(G_PTR *) &xtrabackup_tables, (G_PTR *) &xtrabackup_tables, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"tables_file", OPT_XTRA_TABLES_FILE,
|
||||
"filtering by list of the exact database.table name in the file.",
|
||||
(G_PTR *) &xtrabackup_tables_file, (G_PTR *) &xtrabackup_tables_file, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"databases", OPT_XTRA_DATABASES, "filtering by list of databases.",
|
||||
(G_PTR*) &xtrabackup_databases, (G_PTR*) &xtrabackup_databases,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(G_PTR *) &xtrabackup_databases, (G_PTR *) &xtrabackup_databases, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"databases_file", OPT_XTRA_DATABASES_FILE,
|
||||
"filtering by list of databases in the file.",
|
||||
(G_PTR*) &xtrabackup_databases_file, (G_PTR*) &xtrabackup_databases_file,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"tables-exclude", OPT_XTRA_TABLES_EXCLUDE, "filtering by regexp for table names. "
|
||||
"Operates the same way as --tables, but matched names are excluded from backup. "
|
||||
(G_PTR *) &xtrabackup_databases_file,
|
||||
(G_PTR *) &xtrabackup_databases_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
0, 0, 0},
|
||||
{"tables-exclude", OPT_XTRA_TABLES_EXCLUDE,
|
||||
"filtering by regexp for table names. "
|
||||
"Operates the same way as --tables, but matched names are excluded from "
|
||||
"backup. "
|
||||
"Note that this option has a higher priority than --tables.",
|
||||
(G_PTR*) &xtrabackup_tables_exclude, (G_PTR*) &xtrabackup_tables_exclude,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"databases-exclude", OPT_XTRA_DATABASES_EXCLUDE, "Excluding databases based on name, "
|
||||
"Operates the same way as --databases, but matched names are excluded from backup. "
|
||||
(G_PTR *) &xtrabackup_tables_exclude,
|
||||
(G_PTR *) &xtrabackup_tables_exclude, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
0, 0, 0},
|
||||
{"databases-exclude", OPT_XTRA_DATABASES_EXCLUDE,
|
||||
"Excluding databases based on name, "
|
||||
"Operates the same way as --databases, but matched names are excluded "
|
||||
"from backup. "
|
||||
"Note that this option has a higher priority than --databases.",
|
||||
(G_PTR*) &xtrabackup_databases_exclude, (G_PTR*) &xtrabackup_databases_exclude,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(G_PTR *) &xtrabackup_databases_exclude,
|
||||
(G_PTR *) &xtrabackup_databases_exclude, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"stream", OPT_XTRA_STREAM, "Stream all backup files to the standard output "
|
||||
{"stream", OPT_XTRA_STREAM,
|
||||
"Stream all backup files to the standard output "
|
||||
"in the specified format."
|
||||
"Supported format is 'mbstream' or 'xbstream'."
|
||||
,
|
||||
(G_PTR*) &xtrabackup_stream_str, (G_PTR*) &xtrabackup_stream_str, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
"Supported format is 'mbstream' or 'xbstream'.",
|
||||
(G_PTR *) &xtrabackup_stream_str, (G_PTR *) &xtrabackup_stream_str, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"compress", OPT_XTRA_COMPRESS, "Compress individual backup files using the "
|
||||
{"compress", OPT_XTRA_COMPRESS,
|
||||
"Compress individual backup files using the "
|
||||
"specified compression algorithm. Currently the only supported algorithm "
|
||||
"is 'quicklz'. It is also the default algorithm, i.e. the one used when "
|
||||
"--compress is used without an argument.",
|
||||
|
|
@ -922,61 +961,70 @@ struct my_option xb_client_options[] =
|
|||
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"compress-threads", OPT_XTRA_COMPRESS_THREADS,
|
||||
"Number of threads for parallel data compression. The default value is 1.",
|
||||
(G_PTR*) &xtrabackup_compress_threads, (G_PTR*) &xtrabackup_compress_threads,
|
||||
0, GET_UINT, REQUIRED_ARG, 1, 1, UINT_MAX, 0, 0, 0},
|
||||
"Number of threads for parallel data compression. The default value is "
|
||||
"1.",
|
||||
(G_PTR *) &xtrabackup_compress_threads,
|
||||
(G_PTR *) &xtrabackup_compress_threads, 0, GET_UINT, REQUIRED_ARG, 1, 1,
|
||||
UINT_MAX, 0, 0, 0},
|
||||
|
||||
{"compress-chunk-size", OPT_XTRA_COMPRESS_CHUNK_SIZE,
|
||||
"Size of working buffer(s) for compression threads in bytes. The default value is 64K.",
|
||||
(G_PTR*) &xtrabackup_compress_chunk_size, (G_PTR*) &xtrabackup_compress_chunk_size,
|
||||
0, GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0},
|
||||
"Size of working buffer(s) for compression threads in bytes. The default "
|
||||
"value is 64K.",
|
||||
(G_PTR *) &xtrabackup_compress_chunk_size,
|
||||
(G_PTR *) &xtrabackup_compress_chunk_size, 0, GET_ULL, REQUIRED_ARG,
|
||||
(1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0},
|
||||
|
||||
{"incremental-force-scan", OPT_XTRA_INCREMENTAL_FORCE_SCAN,
|
||||
"Perform a full-scan incremental backup even in the presence of changed "
|
||||
"page bitmap data",
|
||||
(G_PTR *) &xtrabackup_incremental_force_scan,
|
||||
(G_PTR*)&xtrabackup_incremental_force_scan, 0, GET_BOOL, NO_ARG,
|
||||
(G_PTR *) &xtrabackup_incremental_force_scan, 0, GET_BOOL, NO_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"close_files", OPT_CLOSE_FILES,
|
||||
"do not keep files opened. Use at your own "
|
||||
"risk.",
|
||||
(G_PTR *) &xb_close_files, (G_PTR *) &xb_close_files, 0, GET_BOOL, NO_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
|
||||
|
||||
{"close_files", OPT_CLOSE_FILES, "do not keep files opened. Use at your own "
|
||||
"risk.", (G_PTR*) &xb_close_files, (G_PTR*) &xb_close_files, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"core-file", OPT_CORE_FILE, "Write core on fatal signals", 0, 0, 0,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
|
||||
{"copy-back", OPT_COPY_BACK, "Copy all the files in a previously made "
|
||||
{"copy-back", OPT_COPY_BACK,
|
||||
"Copy all the files in a previously made "
|
||||
"backup from the backup directory to their original locations.",
|
||||
(uchar *) &xtrabackup_copy_back, (uchar *) &xtrabackup_copy_back, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"move-back", OPT_MOVE_BACK, "Move all the files in a previously made "
|
||||
{"move-back", OPT_MOVE_BACK,
|
||||
"Move all the files in a previously made "
|
||||
"backup from the backup directory to the actual datadir location. "
|
||||
"Use with caution, as it removes backup files.",
|
||||
(uchar *) &xtrabackup_move_back, (uchar *) &xtrabackup_move_back, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"galera-info", OPT_GALERA_INFO, "This options creates the "
|
||||
{"galera-info", OPT_GALERA_INFO,
|
||||
"This options creates the "
|
||||
"xtrabackup_galera_info file which contains the local node state at "
|
||||
"the time of the backup. Option should be used when performing the "
|
||||
"backup of MariaDB Galera Cluster. Has no effect when backup locks "
|
||||
"are used to create the backup.",
|
||||
(uchar *) &opt_galera_info, (uchar *) &opt_galera_info, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_galera_info, (uchar *) &opt_galera_info, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"slave-info", OPT_SLAVE_INFO, "This option is useful when backing "
|
||||
{"slave-info", OPT_SLAVE_INFO,
|
||||
"This option is useful when backing "
|
||||
"up a replication slave server. It prints the binary log position "
|
||||
"and name of the master server. It also writes this information to "
|
||||
"the \"xtrabackup_slave_info\" file as a \"CHANGE MASTER\" command. "
|
||||
"A new slave for this master can be set up by starting a slave server "
|
||||
"on this backup and issuing a \"CHANGE MASTER\" command with the "
|
||||
"binary log position saved in the \"xtrabackup_slave_info\" file.",
|
||||
(uchar *) &opt_slave_info, (uchar *) &opt_slave_info, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_slave_info, (uchar *) &opt_slave_info, 0, GET_BOOL, NO_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"no-lock", OPT_NO_LOCK, "Use this option to disable table lock "
|
||||
{"no-lock", OPT_NO_LOCK,
|
||||
"Use this option to disable table lock "
|
||||
"with \"FLUSH TABLES WITH READ LOCK\". Use it only if ALL your "
|
||||
"tables are InnoDB and you DO NOT CARE about the binary log "
|
||||
"position of the backup. This option shouldn't be used if there "
|
||||
|
|
@ -990,10 +1038,11 @@ struct my_option xb_client_options[] =
|
|||
"momentarily stop the replication slave thread, this may help "
|
||||
"the backup to succeed and you then don't need to resort to "
|
||||
"using this option.",
|
||||
(uchar *) &opt_no_lock, (uchar *) &opt_no_lock, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_no_lock, (uchar *) &opt_no_lock, 0, GET_BOOL, NO_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"safe-slave-backup", OPT_SAFE_SLAVE_BACKUP, "Stop slave SQL thread "
|
||||
{"safe-slave-backup", OPT_SAFE_SLAVE_BACKUP,
|
||||
"Stop slave SQL thread "
|
||||
"and wait to start backup until Slave_open_temp_tables in "
|
||||
"\"SHOW STATUS\" is zero. If there are no open temporary tables, "
|
||||
"the backup will take place, otherwise the SQL thread will be "
|
||||
|
|
@ -1001,82 +1050,86 @@ struct my_option xb_client_options[] =
|
|||
"The backup will fail if Slave_open_temp_tables does not become "
|
||||
"zero after --safe-slave-backup-timeout seconds. The slave SQL "
|
||||
"thread will be restarted when the backup finishes.",
|
||||
(uchar *) &opt_safe_slave_backup,
|
||||
(uchar *) &opt_safe_slave_backup,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_safe_slave_backup, (uchar *) &opt_safe_slave_backup, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"rsync", OPT_RSYNC, "Uses the rsync utility to optimize local file "
|
||||
{"rsync", OPT_RSYNC,
|
||||
"Uses the rsync utility to optimize local file "
|
||||
"transfers. When this option is specified, innobackupex uses rsync "
|
||||
"to copy all non-InnoDB files instead of spawning a separate cp for "
|
||||
"each file, which can be much faster for servers with a large number "
|
||||
"of databases or tables. This option cannot be used together with "
|
||||
"--stream.",
|
||||
(uchar *) &opt_rsync, (uchar *) &opt_rsync,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_rsync, (uchar *) &opt_rsync, 0, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
0, 0, 0},
|
||||
|
||||
{"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS, "This "
|
||||
{"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS,
|
||||
"This "
|
||||
"option, when specified, makes --copy-back or --move-back transfer "
|
||||
"files to non-empty directories. Note that no existing files will be "
|
||||
"overwritten. If --copy-back or --nove-back has to copy a file from "
|
||||
"the backup directory which already exists in the destination "
|
||||
"directory, it will still fail with an error.",
|
||||
(uchar *) &opt_force_non_empty_dirs,
|
||||
(uchar *) &opt_force_non_empty_dirs,
|
||||
(uchar *) &opt_force_non_empty_dirs, (uchar *) &opt_force_non_empty_dirs,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"no-version-check", OPT_NO_VERSION_CHECK, "This option disables the "
|
||||
{"no-version-check", OPT_NO_VERSION_CHECK,
|
||||
"This option disables the "
|
||||
"version check which is enabled by the --version-check option.",
|
||||
(uchar *) &opt_noversioncheck,
|
||||
(uchar *) &opt_noversioncheck,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_noversioncheck, (uchar *) &opt_noversioncheck, 0, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"no-backup-locks", OPT_NO_BACKUP_LOCKS, "This option controls if "
|
||||
{"no-backup-locks", OPT_NO_BACKUP_LOCKS,
|
||||
"This option controls if "
|
||||
"backup locks should be used instead of FLUSH TABLES WITH READ LOCK "
|
||||
"on the backup stage. The option has no effect when backup locks are "
|
||||
"not supported by the server. This option is enabled by default, "
|
||||
"disable with --no-backup-locks.",
|
||||
(uchar *) &opt_no_backup_locks,
|
||||
(uchar *) &opt_no_backup_locks,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_no_backup_locks, (uchar *) &opt_no_backup_locks, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"decompress", OPT_DECOMPRESS, "Decompresses all files with the .qp "
|
||||
{"decompress", OPT_DECOMPRESS,
|
||||
"Decompresses all files with the .qp "
|
||||
"extension in a backup previously made with the --compress option.",
|
||||
(uchar *) &opt_decompress,
|
||||
(uchar *) &opt_decompress,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"user", 'u', "This option specifies the MySQL username used "
|
||||
"when connecting to the server, if that's not the current user. "
|
||||
"The option accepts a string argument. See mysql --help for details.",
|
||||
(uchar*) &opt_user, (uchar*) &opt_user, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"host", 'H', "This option specifies the host to use when "
|
||||
"connecting to the database server with TCP/IP. The option accepts "
|
||||
"a string argument. See mysql --help for details.",
|
||||
(uchar*) &opt_host, (uchar*) &opt_host, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"port", 'P', "This option specifies the port to use when "
|
||||
"connecting to the database server with TCP/IP. The option accepts "
|
||||
"a string argument. See mysql --help for details.",
|
||||
&opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG,
|
||||
(uchar *) &opt_decompress, (uchar *) &opt_decompress, 0, GET_BOOL, NO_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"password", 'p', "This option specifies the password to use "
|
||||
{"user", 'u',
|
||||
"This option specifies the MySQL username used "
|
||||
"when connecting to the server, if that's not the current user. "
|
||||
"The option accepts a string argument. See mysql --help for details.",
|
||||
(uchar *) &opt_user, (uchar *) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"host", 'H',
|
||||
"This option specifies the host to use when "
|
||||
"connecting to the database server with TCP/IP. The option accepts "
|
||||
"a string argument. See mysql --help for details.",
|
||||
(uchar *) &opt_host, (uchar *) &opt_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"port", 'P',
|
||||
"This option specifies the port to use when "
|
||||
"connecting to the database server with TCP/IP. The option accepts "
|
||||
"a string argument. See mysql --help for details.",
|
||||
&opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"password", 'p',
|
||||
"This option specifies the password to use "
|
||||
"when connecting to the database. It accepts a string argument. "
|
||||
"See mysql --help for details.",
|
||||
0, 0, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"protocol", OPT_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).",
|
||||
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"socket", 'S', "This option specifies the socket to use when "
|
||||
{"protocol", OPT_PROTOCOL,
|
||||
"The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"socket", 'S',
|
||||
"This option specifies the socket to use when "
|
||||
"connecting to the local database server with a UNIX domain socket. "
|
||||
"The option accepts a string argument. See mysql --help for details.",
|
||||
(uchar*) &opt_socket, (uchar*) &opt_socket, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_socket, (uchar *) &opt_socket, 0, GET_STR, REQUIRED_ARG, 0,
|
||||
0, 0, 0, 0, 0},
|
||||
|
||||
{"incremental-history-name", OPT_INCREMENTAL_HISTORY_NAME,
|
||||
"This option specifies the name of the backup series stored in the "
|
||||
|
|
@ -1090,8 +1143,8 @@ struct my_option xb_client_options[] =
|
|||
"that name, no successful backups by that name) xtrabackup will "
|
||||
"return with an error. It is used with the --incremental option.",
|
||||
(uchar *) &opt_incremental_history_name,
|
||||
(uchar*) &opt_incremental_history_name, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_incremental_history_name, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"incremental-history-uuid", OPT_INCREMENTAL_HISTORY_UUID,
|
||||
"This option specifies the UUID of the specific history record "
|
||||
|
|
@ -1101,27 +1154,26 @@ struct my_option xb_client_options[] =
|
|||
"found (no success record with that uuid) xtrabackup will return "
|
||||
"with an error. It is used with the --incremental option.",
|
||||
(uchar *) &opt_incremental_history_uuid,
|
||||
(uchar*) &opt_incremental_history_uuid, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_incremental_history_uuid, 0, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"remove-original", OPT_REMOVE_ORIGINAL, "Remove .qp files after decompression.",
|
||||
(uchar *) &opt_remove_original,
|
||||
(uchar *) &opt_remove_original,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"remove-original", OPT_REMOVE_ORIGINAL,
|
||||
"Remove .qp files after decompression.", (uchar *) &opt_remove_original,
|
||||
(uchar *) &opt_remove_original, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"ftwrl-wait-query-type", OPT_LOCK_WAIT_QUERY_TYPE,
|
||||
"This option specifies which types of queries are allowed to complete "
|
||||
"before innobackupex will issue the global lock. Default is all.",
|
||||
(uchar*) &opt_lock_wait_query_type,
|
||||
(uchar*) &opt_lock_wait_query_type, &query_type_typelib,
|
||||
GET_ENUM, REQUIRED_ARG, QUERY_TYPE_ALL, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_lock_wait_query_type, (uchar *) &opt_lock_wait_query_type,
|
||||
&query_type_typelib, GET_ENUM, REQUIRED_ARG, QUERY_TYPE_ALL, 0, 0, 0, 0,
|
||||
0},
|
||||
|
||||
{"kill-long-query-type", OPT_KILL_LONG_QUERY_TYPE,
|
||||
"This option specifies which types of queries should be killed to "
|
||||
"unblock the global lock. Default is \"all\".",
|
||||
(uchar*) &opt_kill_long_query_type,
|
||||
(uchar*) &opt_kill_long_query_type, &query_type_typelib,
|
||||
GET_ENUM, REQUIRED_ARG, QUERY_TYPE_SELECT, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_kill_long_query_type, (uchar *) &opt_kill_long_query_type,
|
||||
&query_type_typelib, GET_ENUM, REQUIRED_ARG, QUERY_TYPE_SELECT, 0, 0, 0,
|
||||
0, 0},
|
||||
|
||||
{"history", OPT_HISTORY,
|
||||
"This option enables the tracking of backup history in the "
|
||||
|
|
@ -1136,8 +1188,8 @@ struct my_option xb_client_options[] =
|
|||
"queries that block it. Default is 0 seconds, which means "
|
||||
"innobackupex will not attempt to kill any queries.",
|
||||
(uchar *) &opt_kill_long_queries_timeout,
|
||||
(uchar*) &opt_kill_long_queries_timeout, 0, GET_UINT,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_kill_long_queries_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"ftwrl-wait-timeout", OPT_LOCK_WAIT_TIMEOUT,
|
||||
"This option specifies time in seconds that innobackupex should wait "
|
||||
|
|
@ -1145,9 +1197,8 @@ struct my_option xb_client_options[] =
|
|||
"still such queries when the timeout expires, innobackupex terminates "
|
||||
"with an error. Default is 0, in which case innobackupex does not "
|
||||
"wait for queries to complete and starts FTWRL immediately.",
|
||||
(uchar*) &opt_lock_wait_timeout,
|
||||
(uchar*) &opt_lock_wait_timeout, 0, GET_UINT,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_lock_wait_timeout, (uchar *) &opt_lock_wait_timeout, 0,
|
||||
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"ftwrl-wait-threshold", OPT_LOCK_WAIT_THRESHOLD,
|
||||
"This option specifies the query run time threshold which is used by "
|
||||
|
|
@ -1155,39 +1206,39 @@ struct my_option xb_client_options[] =
|
|||
"of --ftwrl-wait-timeout. FTWRL is not started until such "
|
||||
"long-running queries exist. This option has no effect if "
|
||||
"--ftwrl-wait-timeout is 0. Default value is 60 seconds.",
|
||||
(uchar*) &opt_lock_wait_threshold,
|
||||
(uchar*) &opt_lock_wait_threshold, 0, GET_UINT,
|
||||
REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_lock_wait_threshold, (uchar *) &opt_lock_wait_threshold, 0,
|
||||
GET_UINT, REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
|
||||
|
||||
{"debug-sleep-before-unlock", OPT_DEBUG_SLEEP_BEFORE_UNLOCK,
|
||||
"This is a debug-only option used by the XtraBackup test suite.",
|
||||
(uchar *) &opt_debug_sleep_before_unlock,
|
||||
(uchar*) &opt_debug_sleep_before_unlock, 0, GET_UINT,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_debug_sleep_before_unlock, 0, GET_UINT, REQUIRED_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
|
||||
{"safe-slave-backup-timeout", OPT_SAFE_SLAVE_BACKUP_TIMEOUT,
|
||||
"How many seconds --safe-slave-backup should wait for "
|
||||
"Slave_open_temp_tables to become zero. (default 300)",
|
||||
(uchar *) &opt_safe_slave_backup_timeout,
|
||||
(uchar*) &opt_safe_slave_backup_timeout, 0, GET_UINT,
|
||||
REQUIRED_ARG, 300, 0, 0, 0, 0, 0},
|
||||
(uchar *) &opt_safe_slave_backup_timeout, 0, GET_UINT, REQUIRED_ARG, 300,
|
||||
0, 0, 0, 0, 0},
|
||||
|
||||
{"binlog-info", OPT_BINLOG_INFO,
|
||||
"This option controls how XtraBackup should retrieve server's binary log "
|
||||
"coordinates corresponding to the backup. Possible values are OFF, ON, "
|
||||
"LOCKLESS and AUTO. See the XtraBackup manual for more information",
|
||||
&opt_binlog_info, &opt_binlog_info,
|
||||
&binlog_info_typelib, GET_ENUM, OPT_ARG, BINLOG_INFO_AUTO, 0, 0, 0, 0, 0},
|
||||
&opt_binlog_info, &opt_binlog_info, &binlog_info_typelib, GET_ENUM,
|
||||
OPT_ARG, BINLOG_INFO_AUTO, 0, 0, 0, 0, 0},
|
||||
|
||||
{"secure-auth", OPT_XB_SECURE_AUTH, "Refuse client connecting to server if it"
|
||||
" uses old (pre-4.1.1) protocol.", &opt_secure_auth,
|
||||
&opt_secure_auth, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
|
||||
{"secure-auth", OPT_XB_SECURE_AUTH,
|
||||
"Refuse client connecting to server if it"
|
||||
" uses old (pre-4.1.1) protocol.",
|
||||
&opt_secure_auth, &opt_secure_auth, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
|
||||
0},
|
||||
#define MYSQL_CLIENT
|
||||
#include "sslopt-longopts.h"
|
||||
#undef MYSQL_CLIENT
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
uint xb_client_options_count = array_elements(xb_client_options);
|
||||
|
||||
|
|
@ -5554,8 +5605,11 @@ static bool xtrabackup_prepare_func(char** argv)
|
|||
if (!ok) goto error_cleanup;
|
||||
}
|
||||
|
||||
srv_operation = xtrabackup_export
|
||||
? SRV_OPERATION_RESTORE_EXPORT : SRV_OPERATION_RESTORE;
|
||||
srv_operation=
|
||||
xtrabackup_export
|
||||
? SRV_OPERATION_RESTORE_EXPORT
|
||||
: (xtrabackup_rollback_xa ? SRV_OPERATION_RESTORE_ROLLBACK_XA
|
||||
: SRV_OPERATION_RESTORE);
|
||||
|
||||
if (innodb_init_param()) {
|
||||
goto error_cleanup;
|
||||
|
|
@ -5578,10 +5632,50 @@ static bool xtrabackup_prepare_func(char** argv)
|
|||
srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct;
|
||||
}
|
||||
|
||||
if (xtrabackup_rollback_xa)
|
||||
srv_fast_shutdown= 0;
|
||||
|
||||
if (innodb_init()) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
if (xtrabackup_rollback_xa)
|
||||
{
|
||||
/* Please do not merge MDEV-21168 fix in 10.5+ */
|
||||
compile_time_assert(MYSQL_VERSION_ID < 10 * 10000 + 5 * 100);
|
||||
XID *xid_list=
|
||||
(XID *) my_malloc(MAX_XID_LIST_SIZE * sizeof(XID), MYF(0));
|
||||
if (!xid_list)
|
||||
{
|
||||
msg("Can't allocate %i bytes for XID's list", MAX_XID_LIST_SIZE);
|
||||
ok= false;
|
||||
goto error_cleanup;
|
||||
}
|
||||
int got;
|
||||
ut_ad(recv_no_log_write);
|
||||
ut_d(recv_no_log_write= false);
|
||||
while ((got= trx_recover_for_mysql(xid_list, MAX_XID_LIST_SIZE)) > 0)
|
||||
{
|
||||
for (int i= 0; i < got; i++)
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
int rc=
|
||||
#endif // !DBUG_OFF
|
||||
innobase_rollback_by_xid(NULL, xid_list + i);
|
||||
#ifndef DBUG_OFF
|
||||
if (rc == 0)
|
||||
{
|
||||
char buf[XIDDATASIZE * 4 + 6]; // see xid_to_str
|
||||
DBUG_PRINT("info",
|
||||
("rollback xid %s", xid_to_str(buf, xid_list[i])));
|
||||
}
|
||||
#endif // !DBUG_OFF
|
||||
}
|
||||
}
|
||||
ut_d(recv_no_log_write= true);
|
||||
my_free(xid_list);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
|
|
@ -5617,7 +5711,24 @@ static bool xtrabackup_prepare_func(char** argv)
|
|||
else if (ok) xb_write_galera_info(xtrabackup_incremental);
|
||||
#endif
|
||||
|
||||
if (xtrabackup_rollback_xa)
|
||||
{
|
||||
// See innobase_end() and thd_destructor_proxy()
|
||||
while (srv_fast_shutdown == 0 &&
|
||||
(trx_sys_any_active_transactions() ||
|
||||
(uint) thread_count > srv_n_purge_threads + 1))
|
||||
{
|
||||
os_thread_sleep(1000);
|
||||
}
|
||||
srv_shutdown_bg_undo_sources();
|
||||
srv_purge_shutdown();
|
||||
buf_flush_sync_all_buf_pools();
|
||||
innodb_shutdown();
|
||||
innobase_space_shutdown();
|
||||
}
|
||||
else
|
||||
innodb_shutdown();
|
||||
|
||||
innodb_free_param();
|
||||
|
||||
/* output to metadata file */
|
||||
|
|
|
|||
45
mysql-test/suite/mariabackup/innodb_xa_rollback.result
Normal file
45
mysql-test/suite/mariabackup/innodb_xa_rollback.result
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
CALL mtr.add_suppression("Found 1 prepared XA transactions");
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT) ENGINE=INNODB;
|
||||
XA START 'test1';
|
||||
INSERT t1 VALUES (10);
|
||||
XA END 'test1';
|
||||
XA PREPARE 'test1';
|
||||
XA RECOVER;
|
||||
formatID gtrid_length bqual_length data
|
||||
1 5 0 test1
|
||||
# xtrabackup backup
|
||||
XA ROLLBACK 'test1';
|
||||
# xtrabackup prepare and rollback prepared XA
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart server
|
||||
XA RECOVER;
|
||||
formatID gtrid_length bqual_length data
|
||||
# xtrabackup prepare and DO NOT rollback prepared XA
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart server
|
||||
XA RECOVER;
|
||||
formatID gtrid_length bqual_length data
|
||||
1 5 0 test1
|
||||
XA ROLLBACK 'test1';
|
||||
# xtrabackup prepare for export and rollback prepared XA
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart server
|
||||
XA RECOVER;
|
||||
formatID gtrid_length bqual_length data
|
||||
# xtrabackup prepare for export and DO NOT rollback prepared XA
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart server
|
||||
XA RECOVER;
|
||||
formatID gtrid_length bqual_length data
|
||||
1 5 0 test1
|
||||
XA ROLLBACK 'test1';
|
||||
DROP TABLE t1;
|
||||
77
mysql-test/suite/mariabackup/innodb_xa_rollback.test
Normal file
77
mysql-test/suite/mariabackup/innodb_xa_rollback.test
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#
|
||||
# Optionally rollback prepared XA when backup is prepared
|
||||
#
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
|
||||
CALL mtr.add_suppression("Found 1 prepared XA transactions");
|
||||
|
||||
RESET MASTER;
|
||||
|
||||
let targetdir1=$MYSQLTEST_VARDIR/tmp/backup1;
|
||||
let targetdir2=$MYSQLTEST_VARDIR/tmp/backup2;
|
||||
let targetdir3=$MYSQLTEST_VARDIR/tmp/backup3;
|
||||
let targetdir4=$MYSQLTEST_VARDIR/tmp/backup4;
|
||||
|
||||
CREATE TABLE t1 (a INT) ENGINE=INNODB;
|
||||
XA START 'test1';
|
||||
INSERT t1 VALUES (10);
|
||||
XA END 'test1';
|
||||
XA PREPARE 'test1';
|
||||
XA RECOVER;
|
||||
|
||||
--echo # xtrabackup backup
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir1;
|
||||
--enable_result_log
|
||||
|
||||
perl;
|
||||
use lib "lib";
|
||||
use My::Handles { suppress_init_messages => 1 };
|
||||
use My::File::Path;
|
||||
copytree($ENV{'targetdir1'}, $ENV{'targetdir2'});
|
||||
copytree($ENV{'targetdir1'}, $ENV{'targetdir3'});
|
||||
copytree($ENV{'targetdir1'}, $ENV{'targetdir4'});
|
||||
EOF
|
||||
|
||||
XA ROLLBACK 'test1';
|
||||
|
||||
--echo # xtrabackup prepare and rollback prepared XA
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --rollback_xa --target-dir=$targetdir1;
|
||||
--let $targetdir = $targetdir1
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
XA RECOVER;
|
||||
|
||||
--echo # xtrabackup prepare and DO NOT rollback prepared XA
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir2;
|
||||
--let $targetdir = $targetdir2
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
XA RECOVER;
|
||||
XA ROLLBACK 'test1';
|
||||
|
||||
--echo # xtrabackup prepare for export and rollback prepared XA
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --rollback_xa --export --target-dir=$targetdir3;
|
||||
--let $targetdir = $targetdir3
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
XA RECOVER;
|
||||
|
||||
--echo # xtrabackup prepare for export and DO NOT rollback prepared XA
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --export --target-dir=$targetdir4;
|
||||
--let $targetdir = $targetdir4
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
XA RECOVER;
|
||||
XA ROLLBACK 'test1';
|
||||
|
||||
DROP TABLE t1;
|
||||
rmdir $targetdir1;
|
||||
rmdir $targetdir2;
|
||||
rmdir $targetdir3;
|
||||
rmdir $targetdir4;
|
||||
|
|
@ -1806,29 +1806,33 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
|
|||
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
/**
|
||||
@note
|
||||
This does not need to be multi-byte safe or anything
|
||||
*/
|
||||
static char* xid_to_str(char *buf, XID *xid)
|
||||
/** Converts XID to string.
|
||||
|
||||
@param[out] buf output buffer
|
||||
@param[in] xid XID to convert
|
||||
|
||||
@return pointer to converted string
|
||||
|
||||
@note This does not need to be multi-byte safe or anything */
|
||||
char *xid_to_str(char *buf, const XID &xid)
|
||||
{
|
||||
int i;
|
||||
char *s=buf;
|
||||
*s++='\'';
|
||||
for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
|
||||
for (i= 0; i < xid.gtrid_length + xid.bqual_length; i++)
|
||||
{
|
||||
uchar c=(uchar)xid->data[i];
|
||||
uchar c= (uchar) xid.data[i];
|
||||
/* is_next_dig is set if next character is a number */
|
||||
bool is_next_dig= FALSE;
|
||||
if (i < XIDDATASIZE)
|
||||
{
|
||||
char ch= xid->data[i+1];
|
||||
char ch= xid.data[i + 1];
|
||||
is_next_dig= (ch >= '0' && ch <='9');
|
||||
}
|
||||
if (i == xid->gtrid_length)
|
||||
if (i == xid.gtrid_length)
|
||||
{
|
||||
*s++='\'';
|
||||
if (xid->bqual_length)
|
||||
if (xid.bqual_length)
|
||||
{
|
||||
*s++='.';
|
||||
*s++='\'';
|
||||
|
|
@ -1949,7 +1953,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
|
|||
{
|
||||
#ifndef DBUG_OFF
|
||||
char buf[XIDDATASIZE*4+6]; // see xid_to_str
|
||||
DBUG_PRINT("info", ("ignore xid %s", xid_to_str(buf, info->list+i)));
|
||||
DBUG_PRINT("info",
|
||||
("ignore xid %s", xid_to_str(buf, info->list[i])));
|
||||
#endif
|
||||
xid_cache_insert(info->list+i, XA_PREPARED);
|
||||
info->found_foreign_xids++;
|
||||
|
|
@ -1979,7 +1984,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
|
|||
if (rc == 0)
|
||||
{
|
||||
char buf[XIDDATASIZE*4+6]; // see xid_to_str
|
||||
DBUG_PRINT("info", ("commit xid %s", xid_to_str(buf, info->list+i)));
|
||||
DBUG_PRINT("info",
|
||||
("commit xid %s", xid_to_str(buf, info->list[i])));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1993,8 +1999,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
|
|||
if (rc == 0)
|
||||
{
|
||||
char buf[XIDDATASIZE*4+6]; // see xid_to_str
|
||||
DBUG_PRINT("info", ("rollback xid %s",
|
||||
xid_to_str(buf, info->list+i)));
|
||||
DBUG_PRINT("info",
|
||||
("rollback xid %s", xid_to_str(buf, info->list[i])));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4387,4 +4387,16 @@ void print_keydup_error(TABLE *table, KEY *key, myf errflag);
|
|||
|
||||
int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info);
|
||||
int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table);
|
||||
#ifndef DBUG_OFF
|
||||
/** Converts XID to string.
|
||||
|
||||
@param[out] buf output buffer
|
||||
@param[in] xid XID to convert
|
||||
|
||||
@return pointer to converted string
|
||||
|
||||
@note This does not need to be multi-byte safe or anything */
|
||||
char *xid_to_str(char *buf, const XID &xid);
|
||||
#endif // !DBUG_OFF
|
||||
|
||||
#endif /* HANDLER_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -4253,6 +4253,7 @@ fil_ibd_discover(
|
|||
case SRV_OPERATION_RESTORE_DELTA:
|
||||
ut_ad(0);
|
||||
break;
|
||||
case SRV_OPERATION_RESTORE_ROLLBACK_XA:
|
||||
case SRV_OPERATION_RESTORE_EXPORT:
|
||||
case SRV_OPERATION_RESTORE:
|
||||
break;
|
||||
|
|
@ -4350,7 +4351,7 @@ fil_ibd_load(
|
|||
return(FIL_LOAD_OK);
|
||||
}
|
||||
|
||||
if (srv_operation == SRV_OPERATION_RESTORE) {
|
||||
if (is_mariabackup_restore()) {
|
||||
/* Replace absolute DATA DIRECTORY file paths with
|
||||
short names relative to the backup directory. */
|
||||
if (const char* name = strrchr(filename, OS_PATH_SEPARATOR)) {
|
||||
|
|
|
|||
|
|
@ -1408,18 +1408,6 @@ innobase_commit_by_xid(
|
|||
handlerton* hton, /*!< in: InnoDB handlerton */
|
||||
XID* xid); /*!< in: X/Open XA transaction
|
||||
identification */
|
||||
/*******************************************************************//**
|
||||
This function is used to rollback one X/Open XA distributed transaction
|
||||
which is in the prepared state
|
||||
@return 0 or error number */
|
||||
static
|
||||
int
|
||||
innobase_rollback_by_xid(
|
||||
/*=====================*/
|
||||
handlerton* hton, /*!< in: InnoDB handlerton */
|
||||
XID* xid); /*!< in: X/Open XA transaction
|
||||
identification */
|
||||
|
||||
/** Remove all tables in the named database inside InnoDB.
|
||||
@param[in] hton handlerton from InnoDB
|
||||
@param[in] path Database path; Inside InnoDB the name of the last
|
||||
|
|
@ -3591,12 +3579,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
|
|||
reset_template();
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Free tablespace resources allocated. */
|
||||
static
|
||||
void
|
||||
innobase_space_shutdown()
|
||||
/*=====================*/
|
||||
/** Free tablespace resources allocated. */
|
||||
void innobase_space_shutdown()
|
||||
{
|
||||
DBUG_ENTER("innobase_space_shutdown");
|
||||
|
||||
|
|
@ -17495,17 +17479,14 @@ innobase_commit_by_xid(
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
This function is used to rollback one X/Open XA distributed transaction
|
||||
/** This function is used to rollback one X/Open XA distributed transaction
|
||||
which is in the prepared state
|
||||
|
||||
@param[in] hton InnoDB handlerton
|
||||
@param[in] xid X/Open XA transaction identification
|
||||
|
||||
@return 0 or error number */
|
||||
static
|
||||
int
|
||||
innobase_rollback_by_xid(
|
||||
/*=====================*/
|
||||
handlerton* hton, /*!< in: InnoDB handlerton */
|
||||
XID* xid) /*!< in: X/Open XA transaction
|
||||
identification */
|
||||
int innobase_rollback_by_xid(handlerton* hton, XID* xid)
|
||||
{
|
||||
DBUG_ASSERT(hton == innodb_hton_ptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -970,3 +970,15 @@ ib_push_frm_error(
|
|||
@return true if index column length exceeds limit */
|
||||
MY_ATTRIBUTE((warn_unused_result))
|
||||
bool too_big_key_part_length(size_t max_field_len, const KEY& key);
|
||||
|
||||
/** This function is used to rollback one X/Open XA distributed transaction
|
||||
which is in the prepared state
|
||||
|
||||
@param[in] hton InnoDB handlerton
|
||||
@param[in] xid X/Open XA transaction identification
|
||||
|
||||
@return 0 or error number */
|
||||
int innobase_rollback_by_xid(handlerton* hton, XID* xid);
|
||||
|
||||
/** Free tablespace resources allocated. */
|
||||
void innobase_space_shutdown();
|
||||
|
|
|
|||
|
|
@ -518,6 +518,8 @@ enum srv_operation_mode {
|
|||
SRV_OPERATION_BACKUP,
|
||||
/** Mariabackup restoring a backup for subsequent --copy-back */
|
||||
SRV_OPERATION_RESTORE,
|
||||
/** Mariabackup restoring a backup with rolling back prepared XA's*/
|
||||
SRV_OPERATION_RESTORE_ROLLBACK_XA,
|
||||
/** Mariabackup restoring the incremental part of a backup */
|
||||
SRV_OPERATION_RESTORE_DELTA,
|
||||
/** Mariabackup restoring a backup for subsequent --export */
|
||||
|
|
@ -527,6 +529,21 @@ enum srv_operation_mode {
|
|||
/** Current mode of operation */
|
||||
extern enum srv_operation_mode srv_operation;
|
||||
|
||||
inline bool is_mariabackup_restore()
|
||||
{
|
||||
/* To rollback XA's trx_sys must be initialized, the rest is the same
|
||||
as regular backup restore, that is why we join this two operations in
|
||||
the most cases. */
|
||||
return srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_ROLLBACK_XA;
|
||||
}
|
||||
|
||||
inline bool is_mariabackup_restore_or_export()
|
||||
{
|
||||
return is_mariabackup_restore()
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT;
|
||||
}
|
||||
|
||||
extern my_bool srv_print_innodb_monitor;
|
||||
extern my_bool srv_print_innodb_lock_monitor;
|
||||
extern ibool srv_print_verbose_log;
|
||||
|
|
|
|||
|
|
@ -406,8 +406,7 @@ fil_name_process(
|
|||
}
|
||||
|
||||
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
|
||||
|| is_mariabackup_restore_or_export());
|
||||
|
||||
/* We will also insert space=NULL into the map, so that
|
||||
further checks can ensure that a MLOG_FILE_NAME record was
|
||||
|
|
@ -2392,8 +2391,7 @@ buf_block_t* recv_recovery_create_page_low(const page_id_t page_id)
|
|||
void recv_apply_hashed_log_recs(bool last_batch)
|
||||
{
|
||||
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
|
||||
|| is_mariabackup_restore_or_export());
|
||||
|
||||
mutex_enter(&recv_sys->mutex);
|
||||
|
||||
|
|
@ -2411,9 +2409,8 @@ void recv_apply_hashed_log_recs(bool last_batch)
|
|||
|
||||
ut_ad(!last_batch == log_mutex_own());
|
||||
|
||||
recv_no_ibuf_operations = !last_batch
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT;
|
||||
recv_no_ibuf_operations
|
||||
= !last_batch || is_mariabackup_restore_or_export();
|
||||
|
||||
ut_d(recv_no_log_write = recv_no_ibuf_operations);
|
||||
|
||||
|
|
@ -3519,8 +3516,7 @@ static
|
|||
dberr_t
|
||||
recv_init_missing_space(dberr_t err, const recv_spaces_t::const_iterator& i)
|
||||
{
|
||||
if (srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT) {
|
||||
if (is_mariabackup_restore_or_export()) {
|
||||
ib::warn() << "Tablespace " << i->first << " was not"
|
||||
" found at " << i->second.name << " when"
|
||||
" restoring a (partial?) backup. All redo log"
|
||||
|
|
@ -3697,8 +3693,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
|
|||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
|
||||
|| is_mariabackup_restore_or_export());
|
||||
|
||||
/* Initialize red-black tree for fast insertions into the
|
||||
flush_list during recovery process. */
|
||||
|
|
|
|||
|
|
@ -874,6 +874,7 @@ srv_undo_tablespaces_init(bool create_new_db)
|
|||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case SRV_OPERATION_RESTORE_ROLLBACK_XA:
|
||||
case SRV_OPERATION_RESTORE:
|
||||
case SRV_OPERATION_RESTORE_EXPORT:
|
||||
ut_ad(!create_new_db);
|
||||
|
|
@ -1280,6 +1281,7 @@ srv_shutdown_all_bg_threads()
|
|||
case SRV_OPERATION_RESTORE_DELTA:
|
||||
break;
|
||||
case SRV_OPERATION_NORMAL:
|
||||
case SRV_OPERATION_RESTORE_ROLLBACK_XA:
|
||||
case SRV_OPERATION_RESTORE:
|
||||
case SRV_OPERATION_RESTORE_EXPORT:
|
||||
if (!buf_page_cleaner_is_active
|
||||
|
|
@ -1471,8 +1473,7 @@ innobase_start_or_create_for_mysql()
|
|||
unsigned i = 0;
|
||||
|
||||
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
|
||||
|| is_mariabackup_restore_or_export());
|
||||
|
||||
if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
|
||||
srv_read_only_mode = true;
|
||||
|
|
@ -1950,14 +1951,9 @@ innobase_start_or_create_for_mysql()
|
|||
srv_read_only_mode);
|
||||
|
||||
if (err == DB_NOT_FOUND) {
|
||||
if (i == 0) {
|
||||
if (srv_operation
|
||||
== SRV_OPERATION_RESTORE
|
||||
|| srv_operation
|
||||
== SRV_OPERATION_RESTORE_EXPORT) {
|
||||
if (i == 0
|
||||
&& is_mariabackup_restore_or_export())
|
||||
return (DB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/* opened all files */
|
||||
break;
|
||||
|
|
@ -1984,10 +1980,7 @@ innobase_start_or_create_for_mysql()
|
|||
|
||||
if (i == 0) {
|
||||
if (size == 0
|
||||
&& (srv_operation
|
||||
== SRV_OPERATION_RESTORE
|
||||
|| srv_operation
|
||||
== SRV_OPERATION_RESTORE_EXPORT)) {
|
||||
&& is_mariabackup_restore_or_export()) {
|
||||
/* Tolerate an empty ib_logfile0
|
||||
from a previous run of
|
||||
mariabackup --prepare. */
|
||||
|
|
@ -2217,6 +2210,7 @@ files_checked:
|
|||
|
||||
switch (srv_operation) {
|
||||
case SRV_OPERATION_NORMAL:
|
||||
case SRV_OPERATION_RESTORE_ROLLBACK_XA:
|
||||
case SRV_OPERATION_RESTORE_EXPORT:
|
||||
/* Initialize the change buffer. */
|
||||
err = dict_boot();
|
||||
|
|
@ -2321,8 +2315,7 @@ files_checked:
|
|||
|
||||
recv_recovery_from_checkpoint_finish();
|
||||
|
||||
if (srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT) {
|
||||
if (is_mariabackup_restore_or_export()) {
|
||||
/* After applying the redo log from
|
||||
SRV_OPERATION_BACKUP, flush the changes
|
||||
to the data files and truncate or delete the log.
|
||||
|
|
@ -2337,8 +2330,7 @@ files_checked:
|
|||
fil_close_log_files(true);
|
||||
log_group_close_all();
|
||||
if (err == DB_SUCCESS) {
|
||||
bool trunc = srv_operation
|
||||
== SRV_OPERATION_RESTORE;
|
||||
bool trunc = is_mariabackup_restore();
|
||||
/* Delete subsequent log files. */
|
||||
delete_log_files(logfilename, dirnamelen,
|
||||
srv_n_log_files_found, trunc);
|
||||
|
|
@ -2632,7 +2624,9 @@ files_checked:
|
|||
srv_start_state_set(SRV_START_STATE_MASTER);
|
||||
}
|
||||
|
||||
if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL
|
||||
if (!srv_read_only_mode
|
||||
&& (srv_operation == SRV_OPERATION_NORMAL
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_ROLLBACK_XA)
|
||||
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
|
||||
srv_undo_sources = true;
|
||||
/* Create the dict stats gathering thread */
|
||||
|
|
@ -2787,6 +2781,7 @@ innodb_shutdown()
|
|||
case SRV_OPERATION_RESTORE:
|
||||
case SRV_OPERATION_RESTORE_DELTA:
|
||||
case SRV_OPERATION_RESTORE_EXPORT:
|
||||
case SRV_OPERATION_RESTORE_ROLLBACK_XA:
|
||||
fil_close_all_files();
|
||||
break;
|
||||
case SRV_OPERATION_NORMAL:
|
||||
|
|
|
|||
|
|
@ -584,9 +584,7 @@ trx_free_prepared(
|
|||
|| (trx->is_recovered
|
||||
&& (trx_state_eq(trx, TRX_STATE_ACTIVE)
|
||||
|| trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY))
|
||||
&& (!srv_was_started
|
||||
|| srv_operation == SRV_OPERATION_RESTORE
|
||||
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT
|
||||
&& (!srv_was_started || is_mariabackup_restore_or_export()
|
||||
|| srv_read_only_mode
|
||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
|
||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue