Commit e5b155a4 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-12091 Shutdown fails to wait for rollback of recovered transactions to finish

In the 10.1 InnoDB Plugin, a call os_event_free(buf_flush_event) was
misplaced. The event could be triggered by rollback of resurrected
transactions while shutdown was in progress. This bug was caught
by cmake -DWITH_ASAN testing. This call was only present in the
10.1 InnoDB Plugin, not in other versions, or in XtraDB.

That said, the bug affects all InnoDB versions. Shutdown assumes the
cessation of any page-dirtying activity, including the activity of
the background rollback thread. InnoDB only waited for the background
rollback to finish as part of a slow shutdown (innodb_fast_shutdown=0).
The default is a clean shutdown (innodb_fast_shutdown=1). In a scenario
where InnoDB is killed, restarted, and shut down soon enough, the data
files could become corrupted.

logs_empty_and_mark_files_at_shutdown(): Wait for the
rollback to finish, except if innodb_fast_shutdown=2
(crash-like shutdown) was requested.

trx_rollback_or_clean_recovered(): Before choosing the next
recovered transaction to roll back, terminate early if non-slow
shutdown was initiated. Roll back everything on slow shutdown
(innodb_fast_shutdown=0).

srv_innodb_monitor_mutex: Declare as static, because the mutex
is only used within one module.

In 10.2, os_event_destroy() sets the event to a NULL pointer,
while os_event_free() in earlier versions did not do that.
parent ff8bf6e9
......@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -2001,12 +2001,6 @@ logs_empty_and_mark_files_at_shutdown(void)
ib::info() << "Starting shutdown...";
while (srv_fast_shutdown == 0 && trx_rollback_or_clean_is_active) {
/* we should wait until rollback after recovery end
for slow shutdown */
os_thread_sleep(100000);
}
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
......@@ -2068,6 +2062,8 @@ logs_empty_and_mark_files_at_shutdown(void)
thread_name = "lock_wait_timeout_thread";
} else if (srv_buf_dump_thread_active) {
thread_name = "buf_dump_thread";
} else if (srv_fast_shutdown != 2 && trx_rollback_or_clean_is_active) {
thread_name = "rollback of recovered transactions";
} else {
thread_name = NULL;
}
......
......@@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -463,7 +463,7 @@ const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
time_t srv_last_monitor_time;
ib_mutex_t srv_innodb_monitor_mutex;
static ib_mutex_t srv_innodb_monitor_mutex;
/** Mutex protecting page_zip_stat_per_index */
ib_mutex_t page_zip_stat_per_index_mutex;
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2016, 2017, 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
......@@ -810,7 +810,7 @@ trx_rollback_or_clean_recovered(
if (all) {
ib::info() << "Starting in background the rollback"
" of uncommitted transactions";
" of recovered transactions";
}
/* Note: For XA recovered transactions, we rely on MySQL to
......@@ -830,6 +830,12 @@ trx_rollback_or_clean_recovered(
assert_trx_in_rw_list(trx);
if (srv_shutdown_state != SRV_SHUTDOWN_NONE
&& srv_fast_shutdown != 0) {
all = FALSE;
break;
}
/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
we need to reacquire it before retrying the loop. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment