summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/r/xa_recovery.result10
-rw-r--r--mysql-test/suite/innodb/t/xa_recovery.test13
-rw-r--r--storage/innobase/buf/buf0flu.cc6
-rw-r--r--storage/innobase/fil/fil0crypt.cc1
-rw-r--r--storage/innobase/fts/fts0opt.cc3
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc2
-rw-r--r--storage/innobase/include/srv0start.h2
-rw-r--r--storage/innobase/log/log0log.cc8
-rw-r--r--storage/innobase/os/os0file.cc4
-rw-r--r--storage/innobase/row/row0mysql.cc67
-rw-r--r--storage/innobase/row/row0purge.cc4
-rw-r--r--storage/innobase/srv/srv0srv.cc25
-rw-r--r--storage/innobase/srv/srv0start.cc1
13 files changed, 95 insertions, 51 deletions
diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result
index a93afcb07f8..a618154804c 100644
--- a/mysql-test/suite/innodb/r/xa_recovery.result
+++ b/mysql-test/suite/innodb/r/xa_recovery.result
@@ -5,11 +5,19 @@ XA START 'x';
UPDATE t1 set a=2;
XA END 'x';
XA PREPARE 'x';
+connect con2,localhost,root;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+XA START 'y';
+INSERT INTO t2 VALUES (1);
+XA END 'y';
+XA PREPARE 'y';
connection default;
disconnect con1;
+disconnect con2;
connect con1,localhost,root;
SELECT * FROM t1 LOCK IN SHARE MODE;
connection default;
+DROP TABLE t2;
disconnect con1;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t1;
@@ -20,3 +28,5 @@ SELECT * FROM t1;
a
1
DROP TABLE t1;
+SET GLOBAL innodb_fast_shutdown=0;
+XA ROLLBACK 'y';
diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test
index 20bb52c22f2..bb8e3316860 100644
--- a/mysql-test/suite/innodb/t/xa_recovery.test
+++ b/mysql-test/suite/innodb/t/xa_recovery.test
@@ -5,7 +5,7 @@
# MDEV-8841 - close tables opened by previous tests,
# so they don't get marked crashed when the server gets crashed
--disable_query_log
-call mtr.add_suppression("Found 1 prepared XA transactions");
+call mtr.add_suppression("Found [12] prepared XA transactions");
FLUSH TABLES;
--enable_query_log
@@ -13,6 +13,9 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connect (con1,localhost,root);
XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x';
+connect (con2,localhost,root);
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+XA START 'y'; INSERT INTO t2 VALUES (1); XA END 'y'; XA PREPARE 'y';
connection default;
# innodb_force_recovery=2 prevents the purge and tests that the fix of
@@ -25,6 +28,7 @@ connection default;
--let $shutdown_timeout=
disconnect con1;
+disconnect con2;
connect (con1,localhost,root);
--send SELECT * FROM t1 LOCK IN SHARE MODE
@@ -35,6 +39,8 @@ let $wait_condition=
info = 'SELECT * FROM t1 LOCK IN SHARE MODE';
--source include/wait_condition.inc
+DROP TABLE t2;
+
--source include/restart_mysqld.inc
disconnect con1;
@@ -45,3 +51,8 @@ XA ROLLBACK 'x';
SELECT * FROM t1;
DROP TABLE t1;
+
+SET GLOBAL innodb_fast_shutdown=0;
+--source include/restart_mysqld.inc
+
+XA ROLLBACK 'y';
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 7318d4f1eb6..77bbc530637 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -3150,7 +3150,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
ulint last_activity = srv_get_activity_count();
ulint last_pages = 0;
- while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
ulint curr_time = ut_time_ms();
/* The page_cleaner skips sleep if the server is
@@ -3168,7 +3168,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
ret_sleep = 0;
}
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
break;
}
@@ -3335,7 +3335,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
ut_d(buf_flush_page_cleaner_disabled_loop());
}
- ut_ad(srv_shutdown_state > 0);
+ ut_ad(srv_shutdown_state > SRV_SHUTDOWN_INITIATED);
if (srv_fast_shutdown == 2
|| srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
/* In very fast shutdown or when innodb failed to start, we
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 331516e868a..8243fa5801d 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -1076,6 +1076,7 @@ struct rotate_thread_t {
case SRV_SHUTDOWN_EXIT_THREADS:
/* srv_init_abort() must have been invoked */
case SRV_SHUTDOWN_CLEANUP:
+ case SRV_SHUTDOWN_INITIATED:
return true;
case SRV_SHUTDOWN_FLUSH_PHASE:
case SRV_SHUTDOWN_LAST_PHASE:
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index ae943577348..39720b07bd1 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -2790,8 +2790,7 @@ fts_optimize_thread(
/* Assign number of tables added in fts_slots_t to n_tables */
n_tables = ib_vector_size(fts_slots);
- while (!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
-
+ while (!done && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
/* If there is no message in the queue and we have tables
to optimize then optimize the tables. */
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 1ee1624ca8b..2eea443a434 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -2614,7 +2614,7 @@ ibuf_merge(
when a slow shutdown is being executed. During a slow
shutdown, the insert buffer merge must be completed. */
- if (ibuf->empty && !srv_shutdown_state) {
+ if (ibuf->empty && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
return(0);
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
} else if (ibuf_debug) {
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index 8b39733335d..e559814b33d 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -113,6 +113,8 @@ extern ibool srv_start_raw_disk_in_use;
/** Shutdown state */
enum srv_shutdown_t {
SRV_SHUTDOWN_NONE = 0, /*!< Database running normally */
+ /** Shutdown initiated in srv_shutdown_bg_undo_sources() */
+ SRV_SHUTDOWN_INITIATED,
SRV_SHUTDOWN_CLEANUP, /*!< Cleaning up in
logs_empty_and_mark_files_at_shutdown() */
SRV_SHUTDOWN_FLUSH_PHASE,/*!< At this phase the master and the
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 9ad551f805d..ea657e49d07 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -1203,7 +1203,7 @@ loop:
}
}
- if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE)) {
+ if (UNIV_UNLIKELY(srv_shutdown_state > SRV_SHUTDOWN_INITIATED)) {
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
"InnoDB log write: "
LSN_PF "," LSN_PF,
@@ -1430,7 +1430,7 @@ log_group_checkpoint(lsn_t end_lsn)
ut_ad(end_lsn == 0 || end_lsn >= log_sys->next_checkpoint_lsn);
ut_ad(end_lsn <= log_sys->lsn);
ut_ad(end_lsn + SIZE_OF_MLOG_CHECKPOINT <= log_sys->lsn
- || srv_shutdown_state != SRV_SHUTDOWN_NONE);
+ || srv_shutdown_state > SRV_SHUTDOWN_INITIATED);
DBUG_PRINT("ib_log", ("checkpoint " UINT64PF " at " LSN_PF
" written",
@@ -1600,7 +1600,7 @@ bool log_checkpoint(bool sync)
if (oldest_lsn
> log_sys->last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) {
/* Some log has been written since the previous checkpoint. */
- } else if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ } else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
/* MariaDB 10.3 startup expects the redo log file to be
logically empty (not even containing a MLOG_CHECKPOINT record)
after a clean shutdown. Perform an extra checkpoint at
@@ -1625,7 +1625,7 @@ bool log_checkpoint(bool sync)
lsn_t flush_lsn = oldest_lsn;
const lsn_t end_lsn = log_sys->lsn;
const bool do_write
- = srv_shutdown_state == SRV_SHUTDOWN_NONE
+ = srv_shutdown_state <= SRV_SHUTDOWN_INITIATED
|| flush_lsn != end_lsn;
if (fil_names_clear(flush_lsn, do_write)) {
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index e468b842ce2..56b42700be4 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -5435,7 +5435,7 @@ fallback:
? 0 : posix_fallocate(file, current_size,
size - current_size);
} while (err == EINTR
- && srv_shutdown_state == SRV_SHUTDOWN_NONE);
+ && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED);
switch (err) {
case 0:
@@ -5475,7 +5475,7 @@ fallback:
os_offset_t current_size = os_file_get_size(file);
while (current_size < size
- && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
ulint n_bytes;
if (size - current_size < (os_offset_t) buf_size) {
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index d3efc5fc256..3989095d6c6 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -100,7 +100,7 @@ static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
static ib_mutex_t row_drop_list_mutex;
/** Flag: has row_mysql_drop_list been initialized? */
-static ibool row_mysql_drop_list_inited = FALSE;
+static bool row_mysql_drop_list_inited;
/*******************************************************************//**
Determine if the given name is a name reserved for MySQL system tables.
@@ -2572,15 +2572,33 @@ next:
ut_a(!table->can_be_evicted);
+ bool skip = false;
+
if (!table->to_be_dropped) {
+skip:
dict_table_close(table, FALSE, FALSE);
mutex_enter(&row_drop_list_mutex);
UT_LIST_REMOVE(row_mysql_drop_list, drop);
- UT_LIST_ADD_LAST(row_mysql_drop_list, drop);
+ if (!skip) {
+ UT_LIST_ADD_LAST(row_mysql_drop_list, drop);
+ } else {
+ ut_free(drop);
+ }
goto next;
}
+ if (!srv_fast_shutdown && !trx_sys_any_active_transactions()) {
+ lock_mutex_enter();
+ skip = UT_LIST_GET_LEN(table->locks) != 0;
+ lock_mutex_exit();
+ if (skip) {
+ /* We cannot drop tables that are locked by XA
+ PREPARE transactions. */
+ goto skip;
+ }
+ }
+
char* name = mem_strdup(table->name.m_name);
dict_table_close(table, FALSE, FALSE);
@@ -3390,15 +3408,15 @@ row_drop_table_for_mysql(
btr_defragment_remove_table(table);
}
- /* Remove stats for this table and all of its indexes from the
- persistent storage if it exists and if there are stats for this
- table in there. This function creates its own trx and commits
- it. */
- char errstr[1024];
- err = dict_stats_drop_table(name, errstr, sizeof(errstr));
-
- if (err != DB_SUCCESS) {
- ib::warn() << errstr;
+ if (UNIV_LIKELY(!strstr(name, "/" TEMP_FILE_PREFIX_INNODB))) {
+ /* Remove any persistent statistics for this table,
+ in a separate transaction. */
+ char errstr[1024];
+ err = dict_stats_drop_table(name, errstr,
+ sizeof errstr);
+ if (err != DB_SUCCESS) {
+ ib::warn() << errstr;
+ }
}
}
@@ -4808,19 +4826,22 @@ row_mysql_init(void)
row_mysql_drop_list,
&row_mysql_drop_t::row_mysql_drop_list);
- row_mysql_drop_list_inited = TRUE;
+ row_mysql_drop_list_inited = true;
}
-/*********************************************************************//**
-Close this module */
-void
-row_mysql_close(void)
-/*================*/
+void row_mysql_close()
{
- ut_a(UT_LIST_GET_LEN(row_mysql_drop_list) == 0);
-
- if (row_mysql_drop_list_inited) {
- mutex_free(&row_drop_list_mutex);
- row_mysql_drop_list_inited = FALSE;
- }
+ ut_ad(!UT_LIST_GET_LEN(row_mysql_drop_list) ||
+ srv_force_recovery >= SRV_FORCE_NO_BACKGROUND);
+ if (row_mysql_drop_list_inited)
+ {
+ row_mysql_drop_list_inited= false;
+ mutex_free(&row_drop_list_mutex);
+
+ while (row_mysql_drop_t *drop= UT_LIST_GET_FIRST(row_mysql_drop_list))
+ {
+ UT_LIST_REMOVE(row_mysql_drop_list, drop);
+ ut_free(drop);
+ }
+ }
}
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index f4fd617f154..e79784a5a5f 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -1004,7 +1004,7 @@ try_again:
dict_table_close(node->table, FALSE, FALSE);
rw_lock_s_unlock(&dict_operation_lock);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return(false);
}
os_thread_sleep(1000000);
@@ -1167,7 +1167,7 @@ row_purge(
ut_ad(!rw_lock_own(&dict_operation_lock, RW_LOCK_S));
if (purged
- || srv_shutdown_state != SRV_SHUTDOWN_NONE
+ || srv_shutdown_state > SRV_SHUTDOWN_INITIATED
|| node->vcol_op_failed()) {
return;
}
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 19d4c7fb7d7..cc85416aac7 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1802,7 +1802,7 @@ loop:
srv_refresh_innodb_monitor_stats();
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
goto exit_func;
}
@@ -1914,7 +1914,7 @@ loop:
os_event_wait_time_low(srv_error_event, 1000000, sig_count);
- if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
goto loop;
}
@@ -1964,7 +1964,7 @@ srv_get_active_thread_type(void)
srv_sys_mutex_exit();
- if (ret == SRV_NONE && srv_shutdown_state != SRV_SHUTDOWN_NONE
+ if (ret == SRV_NONE && srv_shutdown_state > SRV_SHUTDOWN_INITIATED
&& purge_sys != NULL) {
/* Check only on shutdown. */
switch (trx_purge_state()) {
@@ -2219,7 +2219,7 @@ srv_master_do_active_tasks(void)
ut_d(srv_master_do_disabled_loop());
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2244,7 +2244,7 @@ srv_master_do_active_tasks(void)
/* Now see if various tasks that are performed at defined
intervals need to be performed. */
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2269,7 +2269,7 @@ srv_master_do_active_tasks(void)
early and often to avoid those situations. */
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2312,7 +2312,7 @@ srv_master_do_idle_tasks(void)
ut_d(srv_master_do_disabled_loop());
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2328,7 +2328,7 @@ srv_master_do_idle_tasks(void)
MONITOR_INC_TIME_IN_MICRO_SECS(
MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2356,7 +2356,7 @@ srv_master_do_idle_tasks(void)
early and often to avoid those situations. */
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
+ if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
return;
}
@@ -2454,8 +2454,7 @@ DECLARE_THREAD(srv_master_thread)(
ut_a(slot == srv_sys.sys_threads);
loop:
- while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
-
+ while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
srv_master_sleep();
MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);
@@ -2470,6 +2469,7 @@ loop:
switch (srv_shutdown_state) {
case SRV_SHUTDOWN_NONE:
+ case SRV_SHUTDOWN_INITIATED:
break;
case SRV_SHUTDOWN_FLUSH_PHASE:
case SRV_SHUTDOWN_LAST_PHASE:
@@ -2508,8 +2508,7 @@ static
bool
srv_purge_should_exit(ulint n_purged)
{
- ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE
- || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
+ ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP);
if (srv_undo_sources) {
return(false);
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index d6ad7bf437a..8efae318ee0 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2757,6 +2757,7 @@ srv_shutdown_bg_undo_sources()
{
if (srv_undo_sources) {
ut_ad(!srv_read_only_mode);
+ srv_shutdown_state = SRV_SHUTDOWN_INITIATED;
fts_optimize_shutdown();
dict_stats_shutdown();
while (row_get_background_drop_list_len_low()) {