diff options
author | Vlad Lesin <vlad_lesin@mail.ru> | 2020-04-03 00:43:09 +0300 |
---|---|---|
committer | Vlad Lesin <vlad_lesin@mail.ru> | 2020-04-07 14:57:24 +0300 |
commit | 4c7207e255e06cb2a76223e51e93e17aa7fe4a60 (patch) | |
tree | a72477c3e435971aebdf36846a08b39c8970ef92 | |
parent | cd88a606f5c50db2c6ffe79c8a1a2fa00c06d4c4 (diff) | |
download | mariadb-git-bb-10.2-MDEV-21168-xa-prepare-rollback-on-backup-prepare.tar.gz |
MDEV-21168: Active XA transactions stop slave from working after backupbb-10.2-MDEV-21168-xa-prepare-rollback-on-backup-prepare
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.
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 68 | ||||
-rw-r--r-- | mysql-test/suite/mariabackup/innodb_xa_rollback.result | 45 | ||||
-rw-r--r-- | mysql-test/suite/mariabackup/innodb_xa_rollback.test | 77 | ||||
-rw-r--r-- | sql/handler.cc | 32 | ||||
-rw-r--r-- | sql/handler.h | 12 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 3 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 35 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 12 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 15 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 15 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 34 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 3 |
12 files changed, 276 insertions, 75 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 828c2e06fc2..1abd1167992 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -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, @@ -855,6 +859,11 @@ struct my_option xb_client_options[] = {"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}, @@ -5555,7 +5564,9 @@ static bool xtrabackup_prepare_func(char** argv) } srv_operation = xtrabackup_export - ? SRV_OPERATION_RESTORE_EXPORT : SRV_OPERATION_RESTORE; + ? SRV_OPERATION_RESTORE_EXPORT + : (xtrabackup_rollback_xa + ? SRV_OPERATION_RESTORE_ROLLBACK_XA : SRV_OPERATION_RESTORE); if (innodb_init_param()) { goto error_cleanup; @@ -5578,10 +5589,48 @@ 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 +5666,22 @@ static bool xtrabackup_prepare_func(char** argv) else if (ok) xb_write_galera_info(xtrabackup_incremental); #endif - innodb_shutdown(); + 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 */ diff --git a/mysql-test/suite/mariabackup/innodb_xa_rollback.result b/mysql-test/suite/mariabackup/innodb_xa_rollback.result new file mode 100644 index 00000000000..cd5e2cd39a9 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_xa_rollback.result @@ -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; diff --git a/mysql-test/suite/mariabackup/innodb_xa_rollback.test b/mysql-test/suite/mariabackup/innodb_xa_rollback.test new file mode 100644 index 00000000000..f8ba5ea8cfa --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_xa_rollback.test @@ -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; diff --git a/sql/handler.cc b/sql/handler.cc index 914a4dc07b1..64db45d9cca 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -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 } @@ -1994,7 +2000,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, { char buf[XIDDATASIZE*4+6]; // see xid_to_str DBUG_PRINT("info", ("rollback xid %s", - xid_to_str(buf, info->list+i))); + xid_to_str(buf, info->list[i]))); } #endif } diff --git a/sql/handler.h b/sql/handler.h index a51d5dae01a..a0a43daf144 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -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 */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 4192008ecf0..d4b0d3f4377 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -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)) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 044d407f7e7..10f5e0a2f4b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -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); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 1de26e03607..b66a53bfcd0 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -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(); diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index c1dcb2273e6..f4e8655b273 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -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,19 @@ 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; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 73230def4a1..c458292ecf5 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -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); @@ -2412,8 +2410,7 @@ 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; + || 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. */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 75bdf17eab7..387f05b0f78 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -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,8 @@ 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) { - return(DB_SUCCESS); - } - } + if (i == 0 && is_mariabackup_restore_or_export()) + return(DB_SUCCESS); /* opened all files */ break; @@ -1984,10 +1979,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 +2209,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 +2314,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 +2329,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,8 +2623,10 @@ files_checked: srv_start_state_set(SRV_START_STATE_MASTER); } - if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL - && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) { + 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 */ srv_dict_stats_thread_active = true; @@ -2787,6 +2780,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: diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 7e72b909e2d..75f14b8bc38 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -585,8 +585,7 @@ trx_free_prepared( && (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 + || 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); |