From 20e8347447d55c06e426821de207091059ebd214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 3 Feb 2017 12:25:42 +0200 Subject: MDEV-11985 Make innodb_read_only shutdown more robust If InnoDB is started in innodb_read_only mode such that recovered incomplete transactions exist at startup (but the redo logs are clean), an assertion will fail at shutdown, because there would exist some non-prepared transactions. logs_empty_and_mark_files_at_shutdown(): Do not wait for incomplete transactions to finish if innodb_read_only or innodb_force_recovery>=3. Wait for purge to finish in only one place. trx_sys_close(): Relax the assertion that would fail first. trx_free_prepared(): Also free recovered TRX_STATE_ACTIVE transactions if innodb_read_only or innodb_force_recovery>=3. --- storage/innobase/trx/trx0sys.cc | 4 +++- storage/innobase/trx/trx0trx.cc | 6 +++++- storage/innobase/trx/trx0undo.cc | 29 +++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'storage/innobase/trx') diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index e5f03f4b96a..62c9ee3546a 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1190,7 +1190,9 @@ trx_sys_close(void) ut_a(UT_LIST_GET_LEN(trx_sys->ro_trx_list) == 0); /* Only prepared transactions may be left in the system. Free them. */ - ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx); + ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx + || srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); while ((trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) != NULL) { trx_free_prepared(trx); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 522908397ec..f06d8c33183 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -307,7 +307,11 @@ trx_free_prepared( /*==============*/ trx_t* trx) /*!< in, own: trx object */ { - ut_a(trx_state_eq(trx, TRX_STATE_PREPARED)); + ut_a(trx_state_eq(trx, TRX_STATE_PREPARED) + || (trx_state_eq(trx, TRX_STATE_ACTIVE) + && trx->is_recovered + && (srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO))); ut_a(trx->magic_n == TRX_MAGIC_N); lock_trx_release_locks(trx); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index cdd23726f2e..220589dd9ff 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. 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 @@ -2011,13 +2012,37 @@ trx_undo_free_prepared( ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); if (trx->update_undo) { - ut_a(trx->update_undo->state == TRX_UNDO_PREPARED); + switch (trx->update_undo->state) { + case TRX_UNDO_PREPARED: + break; + case TRX_UNDO_ACTIVE: + /* lock_trx_release_locks() assigns + trx->is_recovered=false */ + ut_a(srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); + break; + default: + ut_error; + } + UT_LIST_REMOVE(undo_list, trx->rseg->update_undo_list, trx->update_undo); trx_undo_mem_free(trx->update_undo); } if (trx->insert_undo) { - ut_a(trx->insert_undo->state == TRX_UNDO_PREPARED); + switch (trx->insert_undo->state) { + case TRX_UNDO_PREPARED: + break; + case TRX_UNDO_ACTIVE: + /* lock_trx_release_locks() assigns + trx->is_recovered=false */ + ut_a(srv_read_only_mode + || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); + break; + default: + ut_error; + } + UT_LIST_REMOVE(undo_list, trx->rseg->insert_undo_list, trx->insert_undo); trx_undo_mem_free(trx->insert_undo); -- cgit v1.2.1