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 15:05:38 +0300 |
commit | 5836191c8f0658d5d75484766fdcc3d838b0a5c1 (patch) | |
tree | f55ca1a7ea0d0dbdf0757bb18bd9fd6d1f651081 /storage | |
parent | cd88a606f5c50db2c6ffe79c8a1a2fa00c06d4c4 (diff) | |
download | mariadb-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.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 | 17 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 17 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 33 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 4 |
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); |