summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorVlad Lesin <vlad_lesin@mail.ru>2020-04-03 00:43:09 +0300
committerVlad Lesin <vlad_lesin@mail.ru>2020-04-07 15:05:38 +0300
commit5836191c8f0658d5d75484766fdcc3d838b0a5c1 (patch)
treef55ca1a7ea0d0dbdf0757bb18bd9fd6d1f651081 /storage
parentcd88a606f5c50db2c6ffe79c8a1a2fa00c06d4c4 (diff)
downloadmariadb-git-5836191c8f0658d5d75484766fdcc3d838b0a5c1.tar.gz
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.
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/fil/fil0fil.cc3
-rw-r--r--storage/innobase/handler/ha_innodb.cc35
-rw-r--r--storage/innobase/handler/ha_innodb.h12
-rw-r--r--storage/innobase/include/srv0srv.h17
-rw-r--r--storage/innobase/log/log0recv.cc17
-rw-r--r--storage/innobase/srv/srv0start.cc33
-rw-r--r--storage/innobase/trx/trx0trx.cc4
7 files changed, 60 insertions, 61 deletions
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..cdbbce51085 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..767e24e9265 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,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;
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 73230def4a1..4ef22468f05 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);
@@ -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. */
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 75bdf17eab7..41a1d42f649 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,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) {
- return(DB_SUCCESS);
- }
- }
+ 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:
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 7e72b909e2d..458165a3816 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -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);