From b1742a5c951633213d756600ee73ba7bfa7800ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 1 Apr 2020 09:13:01 +0300 Subject: MDEV-13626: Improve innodb.xa_recovery_debug Improve the test that was imported and adapted for MariaDB in commit fb217449dce9f6996563d5aa257be01c12df4a11. row_undo_step(): Move the DEBUG_SYNC point from trx_rollback_for_mysql(). This DEBUG_SYNC point is executed after rolling back one row. trx_rollback_for_mysql(): Clarify the comments that describe the scenario, and remove the DEBUG_SYNC point. If the statement "if (trx->has_logged_persistent())" and its body are removed from trx_rollback_for_mysql(), then the test innodb.xa_recovery_debug will fail because the transaction would still exist in the XA PREPARE state. If we allow the XA COMMIT statement to succeed in the test, we would observe an incorrect state of the XA transaction where the table would contain row (1,NULL). Depending on whether the XA transaction was committed, the table should either be empty or contain the record (1,1). The intermediate state of (1,NULL) should never be observed after completed recovery. --- storage/innobase/trx/trx0roll.cc | 47 +++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'storage/innobase/trx/trx0roll.cc') diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 20798323802..b6d7aa9f380 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -200,10 +200,21 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) case TRX_STATE_PREPARED_RECOVERED: ut_ad(!trx_is_autocommit_non_locking(trx)); if (trx->has_logged_persistent()) { - /* Change the undo log state back from - TRX_UNDO_PREPARED to TRX_UNDO_ACTIVE - so that if the system gets killed, - recovery will perform the rollback. */ + /* The XA ROLLBACK of a XA PREPARE transaction + will consist of multiple mini-transactions. + + As the very first step of XA ROLLBACK, we must + change the undo log state back from + TRX_UNDO_PREPARED to TRX_UNDO_ACTIVE, in order + to ensure that recovery will complete the + rollback. + + Failure to perform this step could cause a + situation where we would roll back part of + a XA PREPARE transaction, the server would be + killed, and finally, the transaction would be + recovered in XA PREPARE state, with some of + the actions already having been rolled back. */ trx_undo_ptr_t* undo_ptr = &trx->rsegs.m_redo; mtr_t mtr; mtr.start(); @@ -219,29 +230,15 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) true, &mtr); } mutex_exit(&trx->rsegs.m_redo.rseg->mutex); - /* Persist the XA ROLLBACK, so that crash - recovery will replay the rollback in case - the redo log gets applied past this point. */ + /* Write the redo log for the XA ROLLBACK + state change to the global buffer. It is + not necessary to flush the redo log. If + a durable log write of a later mini-transaction + takes place for whatever reason, then this state + change will be durable as well. */ mtr.commit(); ut_ad(mtr.commit_lsn() > 0); } -#ifdef ENABLED_DEBUG_SYNC - if (trx->mysql_thd == NULL) { - /* We could be executing XA ROLLBACK after - XA PREPARE and a server restart. */ - } else if (!trx->has_logged_persistent()) { - /* innobase_close_connection() may roll back a - transaction that did not generate any - persistent undo log. The DEBUG_SYNC - would cause an assertion failure for a - disconnected thread. - - NOTE: InnoDB will not know about the XID - if no persistent undo log was generated. */ - } else { - DEBUG_SYNC_C("trx_xa_rollback"); - } -#endif /* ENABLED_DEBUG_SYNC */ return(trx_rollback_for_mysql_low(trx)); case TRX_STATE_COMMITTED_IN_MEMORY: -- cgit v1.2.1