summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-06-12 14:26:32 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-06-12 14:26:32 +0300
commitfa57479fcd893c290c8f6e8fef5367a5cf2b8c7a (patch)
tree5b6f0f3c3d641e034e5b5882589cbae680b17e64
parent58c56dd7f8e787c48b6f09a4d03cddd7c922588b (diff)
parent75b35a3b6897a0fcef28d73a480d6d9d65c7ac9b (diff)
downloadmariadb-git-fa57479fcd893c290c8f6e8fef5367a5cf2b8c7a.tar.gz
Merge 10.0 into 10.1
-rw-r--r--extra/mariabackup/xtrabackup.cc24
-rw-r--r--mysql-test/suite/innodb/r/row_format_redundant.result48
-rw-r--r--mysql-test/suite/innodb/t/row_format_redundant.test75
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_sched_priority_cleaner_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_sched_priority_cleaner_basic.test10
-rw-r--r--storage/innobase/buf/buf0flu.cc5
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc31
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc11
-rw-r--r--storage/innobase/handler/ha_innodb.cc29
-rw-r--r--storage/innobase/include/buf0flu.h2
-rw-r--r--storage/innobase/include/dict0stats_bg.h6
-rw-r--r--storage/innobase/include/srv0start.h20
-rw-r--r--storage/innobase/srv/srv0srv.cc69
-rw-r--r--storage/innobase/srv/srv0start.cc133
-rw-r--r--storage/innobase/trx/trx0purge.cc13
-rw-r--r--storage/xtradb/buf/buf0flu.cc10
-rw-r--r--storage/xtradb/dict/dict0stats_bg.cc31
-rw-r--r--storage/xtradb/fsp/fsp0fsp.cc11
-rw-r--r--storage/xtradb/handler/ha_innodb.cc37
-rw-r--r--storage/xtradb/include/buf0flu.h2
-rw-r--r--storage/xtradb/include/dict0stats_bg.h6
-rw-r--r--storage/xtradb/include/srv0start.h20
-rw-r--r--storage/xtradb/srv/srv0srv.cc69
-rw-r--r--storage/xtradb/srv/srv0start.cc143
-rw-r--r--storage/xtradb/trx/trx0purge.cc13
25 files changed, 373 insertions, 447 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 5b3f1527133..087fa142629 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -1899,8 +1899,8 @@ error:
return(TRUE);
}
-static my_bool
-innodb_end(void)
+static void
+innodb_end()
{
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
innodb_inited = 0;
@@ -1908,9 +1908,7 @@ innodb_end(void)
msg("xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
srv_fast_shutdown);
- if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
- goto error;
- }
+ innodb_shutdown();
free(internal_innobase_data_file_path);
internal_innobase_data_file_path = NULL;
@@ -1921,12 +1919,6 @@ innodb_end(void)
// pthread_mutex_destroy(&commit_threads_m);
// pthread_mutex_destroy(&commit_cond_m);
// pthread_cond_destroy(&commit_cond);
-
- return(FALSE);
-
-error:
- msg("xtrabackup: innodb_end(): Error occured.\n");
- return(TRUE);
}
/* ================= common ================= */
@@ -4819,8 +4811,7 @@ end:
xb_filters_free();
/* shutdown InnoDB */
- if(innodb_end())
- exit(EXIT_FAILURE);
+ innodb_end();
}
/* ================= prepare ================= */
@@ -6763,8 +6754,7 @@ next_node:
xb_write_galera_info(xtrabackup_incremental);
#endif
- if(innodb_end())
- goto error_cleanup;
+ innodb_end();
innodb_free_param();
@@ -6850,9 +6840,7 @@ next_node:
if(innodb_init())
goto error;
- if(innodb_end())
- goto error;
-
+ innodb_end();
innodb_free_param();
}
diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result
new file mode 100644
index 00000000000..db31c32559f
--- /dev/null
+++ b/mysql-test/suite/innodb/r/row_format_redundant.result
@@ -0,0 +1,48 @@
+create table t1 (a int not null, d varchar(15) not null, b
+varchar(198) not null, c char(156),
+fulltext ftsic(c)) engine=InnoDB
+row_format=redundant;
+insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(456, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(789, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(134, 'kasdfsdsadf', 'adfjlasdkfjasd', 'adfsadflkasdasdfljasdf');
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+SET GLOBAL innodb_file_per_table=OFF;
+create table t2 (a int not null, d varchar(15) not null, b
+varchar(198) not null, c char(156), fulltext ftsic(c)) engine=InnoDB
+row_format=redundant;
+insert into t2 select * from t1;
+create table t3 (a int not null, d varchar(15) not null, b varchar(198),
+c varchar(150), index k1(c(99), b(56)), index k2(b(5), c(10))) engine=InnoDB
+row_format=redundant;
+insert into t3 values(444, 'dddd', 'bbbbb', 'aaaaa');
+insert into t3 values(555, 'eeee', 'ccccc', 'aaaaa');
+SET GLOBAL innodb_fast_shutdown=0;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4096
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4096
+SELECT COUNT(*) FROM t3;
+COUNT(*)
+2
+TRUNCATE TABLE t1;
+ERROR HY000: Table 't1' is read only
+TRUNCATE TABLE t2;
+ERROR HY000: Table 't2' is read only
+TRUNCATE TABLE t3;
+ERROR HY000: Table 't3' is read only
+TRUNCATE TABLE t1;
+TRUNCATE TABLE t2;
+TRUNCATE TABLE t3;
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test
new file mode 100644
index 00000000000..974588d11eb
--- /dev/null
+++ b/mysql-test/suite/innodb/t/row_format_redundant.test
@@ -0,0 +1,75 @@
+--source include/innodb_page_size.inc
+# Embedded mode doesn't allow restarting
+--source include/not_embedded.inc
+
+# MDEV-13059 XtraDB hangs on Windows due to failing to release
+# block->lock X-latch in innodb_read_only mode
+if (`SELECT count(*) FROM information_schema.plugins WHERE
+ plugin_name = 'innodb' AND plugin_status = 'active' AND
+ plugin_description LIKE '%xtradb%'`){
+ if (`SELECT @@version_compile_os IN ('Win32','Win64','Windows')`) {
+ skip MDEV-13059 XtraDB hangs on Windows in innodb_read_only mode;
+ }
+}
+
+create table t1 (a int not null, d varchar(15) not null, b
+varchar(198) not null, c char(156),
+fulltext ftsic(c)) engine=InnoDB
+row_format=redundant;
+
+insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(456, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(789, 'abcdef', 'jghikl', 'mnop');
+insert into t1 values(134, 'kasdfsdsadf', 'adfjlasdkfjasd', 'adfsadflkasdasdfljasdf');
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+
+SET GLOBAL innodb_file_per_table=OFF;
+create table t2 (a int not null, d varchar(15) not null, b
+varchar(198) not null, c char(156), fulltext ftsic(c)) engine=InnoDB
+row_format=redundant;
+
+insert into t2 select * from t1;
+
+create table t3 (a int not null, d varchar(15) not null, b varchar(198),
+c varchar(150), index k1(c(99), b(56)), index k2(b(5), c(10))) engine=InnoDB
+row_format=redundant;
+
+insert into t3 values(444, 'dddd', 'bbbbb', 'aaaaa');
+insert into t3 values(555, 'eeee', 'ccccc', 'aaaaa');
+
+# read-only restart requires the change buffer to be empty; therefore we
+# do a slow shutdown.
+SET GLOBAL innodb_fast_shutdown=0;
+--let $restart_parameters = --innodb-read-only
+--source include/restart_mysqld.inc
+
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t3;
+
+--error ER_OPEN_AS_READONLY
+TRUNCATE TABLE t1;
+--error ER_OPEN_AS_READONLY
+TRUNCATE TABLE t2;
+--error ER_OPEN_AS_READONLY
+TRUNCATE TABLE t3;
+
+--let $restart_parameters =
+--source include/restart_mysqld.inc
+
+TRUNCATE TABLE t1;
+TRUNCATE TABLE t2;
+TRUNCATE TABLE t3;
+
+# TODO: Shutdown, corrupt the SYS_TABLES.TYPE of the tables, restart
+
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/suite/sys_vars/r/innodb_sched_priority_cleaner_basic.result b/mysql-test/suite/sys_vars/r/innodb_sched_priority_cleaner_basic.result
index 1183fb27732..f2bfaf2ed61 100644
--- a/mysql-test/suite/sys_vars/r/innodb_sched_priority_cleaner_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_sched_priority_cleaner_basic.result
@@ -1,4 +1,4 @@
-SET @start_value = @@GLOBAL.innodb_sched_priority_cleaner;
+SET GLOBAL innodb_sched_priority_cleaner=39;
SELECT @@GLOBAL.innodb_sched_priority_cleaner;
@@GLOBAL.innodb_sched_priority_cleaner
19
diff --git a/mysql-test/suite/sys_vars/t/innodb_sched_priority_cleaner_basic.test b/mysql-test/suite/sys_vars/t/innodb_sched_priority_cleaner_basic.test
index b2382fd7844..2c2037f167f 100644
--- a/mysql-test/suite/sys_vars/t/innodb_sched_priority_cleaner_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_sched_priority_cleaner_basic.test
@@ -4,7 +4,15 @@
# A dynamic, global variable
-SET @start_value = @@GLOBAL.innodb_sched_priority_cleaner;
+# Test in read-only mode
+--let $restart_parameters= --innodb-read-only
+--source include/restart_mysqld.inc
+--let $restart_parameters=
+
+# This has no actual effect in innodb_read_only mode
+SET GLOBAL innodb_sched_priority_cleaner=39;
+
+--source include/restart_mysqld.inc
# Default value
SELECT @@GLOBAL.innodb_sched_priority_cleaner;
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index b8429052e93..31feb322826 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -62,7 +62,7 @@ is set to TRUE by the page_cleaner thread when it is spawned and is set
back to FALSE at shutdown by the page_cleaner as well. Therefore no
need to protect it by a mutex. It is only ever read by the thread
doing the shutdown */
-UNIV_INTERN ibool buf_page_cleaner_is_active = FALSE;
+UNIV_INTERN bool buf_page_cleaner_is_active;
#ifdef UNIV_PFS_THREAD
UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key;
@@ -2326,7 +2326,6 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
fprintf(stderr, "InnoDB: page_cleaner thread running, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
- buf_page_cleaner_is_active = TRUE;
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
@@ -2422,7 +2421,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/* We have lived our life. Time to die. */
thread_exit:
- buf_page_cleaner_is_active = FALSE;
+ buf_page_cleaner_is_active = false;
my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 721e4706e2a..57a5912941e 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 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
@@ -39,12 +39,18 @@ Created Apr 25, 2012 Vasil Dimov
/** Minimum time interval between stats recalc for a given table */
#define MIN_RECALC_INTERVAL 10 /* seconds */
-#define SHUTTING_DOWN() (srv_shutdown_state != SRV_SHUTDOWN_NONE)
-
/** Event to wake up dict_stats_thread on dict_stats_recalc_pool_add()
or shutdown. Not protected by any mutex. */
UNIV_INTERN os_event_t dict_stats_event;
+/** Variable to initiate shutdown the dict stats thread. Note we don't
+use 'srv_shutdown_state' because we want to shutdown dict stats thread
+before purge thread. */
+static bool dict_stats_start_shutdown;
+
+/** Event to wait for shutdown of the dict stats thread */
+static os_event_t dict_stats_shutdown_event;
+
/** This mutex protects the "recalc_pool" variable. */
static ib_mutex_t recalc_pool_mutex;
static ib_mutex_t defrag_pool_mutex;
@@ -340,11 +346,11 @@ Must be called before dict_stats_thread() is started. */
UNIV_INTERN
void
dict_stats_thread_init()
-/*====================*/
{
ut_a(!srv_read_only_mode);
dict_stats_event = os_event_create();
+ dict_stats_shutdown_event = os_event_create();
/* The recalc_pool_mutex is acquired from:
1) the background stats gathering thread before any other latch
@@ -389,6 +395,9 @@ dict_stats_thread_deinit()
os_event_free(dict_stats_event);
dict_stats_event = NULL;
+ os_event_free(dict_stats_shutdown_event);
+ dict_stats_shutdown_event = NULL;
+ dict_stats_start_shutdown = false;
}
/*****************************************************************//**
@@ -532,7 +541,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
my_thread_init();
ut_a(!srv_read_only_mode);
- while (!SHUTTING_DOWN()) {
+ while (!dict_stats_start_shutdown) {
/* Wake up periodically even if not signaled. This is
because we may lose an event - if the below call to
@@ -542,7 +551,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
os_event_wait_time(
dict_stats_event, MIN_RECALC_INTERVAL * 1000000);
- if (SHUTTING_DOWN()) {
+ if (dict_stats_start_shutdown) {
break;
}
@@ -556,6 +565,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
srv_dict_stats_thread_active = false;
+ os_event_set(dict_stats_shutdown_event);
my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */
@@ -563,3 +573,12 @@ DECLARE_THREAD(dict_stats_thread)(void*)
OS_THREAD_DUMMY_RETURN;
}
+
+/** Shut down the dict_stats_thread. */
+void
+dict_stats_shutdown()
+{
+ dict_stats_start_shutdown = true;
+ os_event_set(dict_stats_event);
+ os_event_wait(dict_stats_shutdown_event);
+}
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 878b8d824c7..9d5e2e984fc 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -2731,7 +2731,6 @@ fsp_reserve_free_extents(
ibool success;
ulint n_pages_added;
size_t total_reserved = 0;
- ulint rounds = 0;
ut_ad(mtr);
*n_reserved = n_ext;
@@ -2811,17 +2810,7 @@ try_to_extend:
space_header, mtr);
if (success && n_pages_added > 0) {
-
- rounds++;
total_reserved += n_pages_added;
-
- if (rounds > 50) {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Space id %lu trying to reserve %lu extents actually reserved %lu "
- " reserve %lu free %lu size %lu rounds %lu total_reserved %llu",
- space, n_ext, n_pages_added, reserve, n_free, size, rounds, (ullint) total_reserved);
- }
-
goto try_again;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 012539d1ace..bd89744c1f0 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1380,14 +1380,11 @@ innobase_drop_database(
the path is used as the database name:
for example, in 'mysql/data/test' the
database name is 'test' */
-/*******************************************************************//**
-Closes an InnoDB database. */
+/** Shut down the InnoDB storage engine.
+@return 0 */
static
int
-innobase_end(
-/*=========*/
- handlerton* hton, /* in: Innodb handlerton */
- ha_panic_function type);
+innobase_end(handlerton*, ha_panic_function);
/*****************************************************************//**
Creates an InnoDB transaction struct for the thd if it does not yet have one.
@@ -4011,21 +4008,13 @@ error:
DBUG_RETURN(TRUE);
}
-/*******************************************************************//**
-Closes an InnoDB database.
-@return TRUE if error */
+/** Shut down the InnoDB storage engine.
+@return 0 */
static
int
-innobase_end(
-/*=========*/
- handlerton* hton, /*!< in/out: InnoDB handlerton */
- ha_panic_function type MY_ATTRIBUTE((unused)))
- /*!< in: ha_panic() parameter */
+innobase_end(handlerton*, ha_panic_function)
{
- int err= 0;
-
DBUG_ENTER("innobase_end");
- DBUG_ASSERT(hton == innodb_hton_ptr);
if (innodb_inited) {
@@ -4042,9 +4031,7 @@ innobase_end(
innodb_inited = 0;
hash_table_free(innobase_open_tables);
innobase_open_tables = NULL;
- if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
- err = 1;
- }
+ innodb_shutdown();
srv_free_paths_and_sizes();
my_free(internal_innobase_data_file_path);
mysql_mutex_destroy(&innobase_share_mutex);
@@ -4053,7 +4040,7 @@ innobase_end(
mysql_mutex_destroy(&pending_checkpoint_mutex);
}
- DBUG_RETURN(err);
+ DBUG_RETURN(0);
}
/****************************************************************//**
diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h
index f1ca1039ccb..f503d52802c 100644
--- a/storage/innobase/include/buf0flu.h
+++ b/storage/innobase/include/buf0flu.h
@@ -35,7 +35,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0types.h"
/** Flag indicating if the page_cleaner is in active state. */
-extern ibool buf_page_cleaner_is_active;
+extern bool buf_page_cleaner_is_active;
/** Event to synchronise with the flushing. */
extern os_event_t buf_flush_event;
diff --git a/storage/innobase/include/dict0stats_bg.h b/storage/innobase/include/dict0stats_bg.h
index d5f0870718d..8f3385eb22b 100644
--- a/storage/innobase/include/dict0stats_bg.h
+++ b/storage/innobase/include/dict0stats_bg.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 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
@@ -144,6 +144,10 @@ DECLARE_THREAD(dict_stats_thread)(
void* arg); /*!< in: a dummy parameter
required by os_thread_create */
+/** Shut down the dict_stats_thread. */
+void
+dict_stats_shutdown();
+
# ifndef UNIV_NONINL
# include "dict0stats_bg.ic"
# endif
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index bb4ab85e836..2998a10ed15 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 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
@@ -76,22 +77,12 @@ are not found and the user wants.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
-innobase_start_or_create_for_mysql(void);
-/*====================================*/
-/****************************************************************//**
-Shuts down the Innobase database.
-@return DB_SUCCESS or error code */
-UNIV_INTERN
-dberr_t
-innobase_shutdown_for_mysql(void);
+innobase_start_or_create_for_mysql();
-/********************************************************************
-Signal all per-table background threads to shutdown, and wait for them to do
-so. */
+/** Shut down InnoDB. */
UNIV_INTERN
void
-srv_shutdown_table_bg_threads(void);
-/*=============================*/
+innodb_shutdown();
/*************************************************************//**
Copy the file path component of the physical file to parameter. It will
@@ -159,6 +150,9 @@ enum srv_shutdown_state {
SRV_SHUTDOWN_EXIT_THREADS/*!< Exit all threads */
};
+/** Whether any undo log records can be generated */
+extern bool srv_undo_sources;
+
/** At a shutdown this value climbs from SRV_SHUTDOWN_NONE to
SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern enum srv_shutdown_state srv_shutdown_state;
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 5d5a879d656..61a435e3c0f 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -2528,31 +2528,29 @@ suspend_thread:
goto loop;
}
-/*********************************************************************//**
-Check if purge should stop.
-@return true if it should shutdown. */
+/** Check if purge should stop.
+@param[in] n_purged pages purged in the last batch
+@return whether purge should exit */
static
bool
-srv_purge_should_exit(
-/*==============*/
- ulint n_purged) /*!< in: pages purged in last batch */
+srv_purge_should_exit(ulint n_purged)
{
- switch (srv_shutdown_state) {
- case SRV_SHUTDOWN_NONE:
- /* Normal operation. */
- break;
+ ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE
+ || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
- case SRV_SHUTDOWN_CLEANUP:
- case SRV_SHUTDOWN_EXIT_THREADS:
- /* Exit unless slow shutdown requested or all done. */
- return(srv_fast_shutdown != 0 || n_purged == 0);
-
- case SRV_SHUTDOWN_LAST_PHASE:
- case SRV_SHUTDOWN_FLUSH_PHASE:
- ut_error;
+ if (srv_undo_sources) {
+ return(false);
}
-
- return(false);
+ if (srv_fast_shutdown) {
+ return(true);
+ }
+ /* Slow shutdown was requested. */
+ if (n_purged) {
+ /* The previous round still did some work. */
+ return(false);
+ }
+ /* Exit if there are no active transactions to roll back. */
+ return(trx_sys_any_active_transactions() == 0);
}
/*********************************************************************//**
@@ -2813,7 +2811,7 @@ srv_purge_coordinator_suspend(
}
rw_lock_x_unlock(&purge_sys->latch);
- } while (stop);
+ } while (stop && srv_undo_sources);
srv_resume_thread(slot, 0, false);
}
@@ -2864,6 +2862,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
purge didn't purge any records then wait for activity. */
if (srv_shutdown_state == SRV_SHUTDOWN_NONE
+ && srv_undo_sources
&& (purge_sys->state == PURGE_STATE_STOP
|| n_total_purged == 0)) {
@@ -2880,36 +2879,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
rseg_history_len = srv_do_purge(
srv_n_purge_threads, &n_total_purged);
-
} while (!srv_purge_should_exit(n_total_purged));
- /* Ensure that we don't jump out of the loop unless the
- exit condition is satisfied. */
-
- ut_a(srv_purge_should_exit(n_total_purged));
-
- ulint n_pages_purged = ULINT_MAX;
-
- /* Ensure that all records are purged if it is not a fast shutdown.
- This covers the case where a record can be added after we exit the
- loop above. */
- while (srv_fast_shutdown == 0 && n_pages_purged > 0) {
- n_pages_purged = trx_purge(1, srv_purge_batch_size, false);
- }
-
- /* This trx_purge is called to remove any undo records (added by
- background threads) after completion of the above loop. When
- srv_fast_shutdown != 0, a large batch size can cause significant
- delay in shutdown ,so reducing the batch size to magic number 20
- (which was default in 5.5), which we hope will be sufficient to
- remove all the undo records */
- const uint temp_batch_size = 20;
-
- n_pages_purged = trx_purge(1, srv_purge_batch_size <= temp_batch_size
- ? srv_purge_batch_size : temp_batch_size,
- true);
- ut_a(n_pages_purged == 0 || srv_fast_shutdown != 0);
-
/* The task queue should always be empty, independent of fast
shutdown state. */
ut_a(srv_get_task_queue_length() == 0);
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index c7026b4f04a..0880f93c7fa 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -129,7 +129,11 @@ UNIV_INTERN ibool srv_is_being_started = FALSE;
/** TRUE if the server was successfully started */
UNIV_INTERN ibool srv_was_started = FALSE;
/** TRUE if innobase_start_or_create_for_mysql() has been called */
-static ibool srv_start_has_been_called = FALSE;
+static ibool srv_start_has_been_called;
+
+/** Whether any undo log records can be generated */
+UNIV_INTERN bool srv_undo_sources;
+
#ifdef UNIV_DEBUG
/** InnoDB system tablespace to set during recovery */
UNIV_INTERN uint srv_sys_space_size_debug;
@@ -1620,8 +1624,7 @@ are not found and the user wants.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
-innobase_start_or_create_for_mysql(void)
-/*====================================*/
+innobase_start_or_create_for_mysql()
{
bool create_new_db;
lsn_t flushed_lsn;
@@ -2776,8 +2779,8 @@ files_checked:
}
}
- srv_startup_is_before_trx_rollback_phase = FALSE;
recv_recovery_rollback_active();
+ srv_startup_is_before_trx_rollback_phase = FALSE;
/* It is possible that file_format tag has never
been set. In this case we initialize it to minimum
@@ -2903,6 +2906,16 @@ files_checked:
srv_master_thread,
NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
thread_started[1 + SRV_MAX_N_IO_THREADS] = true;
+
+ srv_undo_sources = true;
+ /* Create the dict stats gathering thread */
+ srv_dict_stats_thread_active = true;
+ dict_stats_thread_handle = os_thread_create(
+ dict_stats_thread, NULL, NULL);
+ dict_stats_thread_started = true;
+
+ /* Create the thread that will optimize the FTS sub-system. */
+ fts_optimize_init();
}
if (!srv_read_only_mode
@@ -2946,6 +2959,7 @@ files_checked:
(thread_ids + 6 + 32));
}
+ buf_page_cleaner_is_active = true;
buf_flush_page_cleaner_thread_handle = os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
buf_flush_page_cleaner_thread_started = true;
}
@@ -2989,10 +3003,10 @@ files_checked:
if (!wsrep_recovery) {
#endif /* WITH_WSREP */
/* Create the buffer pool dump/load thread */
+ srv_buf_dump_thread_active = true;
buf_dump_thread_handle=
os_thread_create(buf_dump_thread, NULL, NULL);
- srv_buf_dump_thread_active = true;
buf_dump_thread_started = true;
#ifdef WITH_WSREP
} else {
@@ -3002,15 +3016,6 @@ files_checked:
}
#endif /* WITH_WSREP */
- /* Create the dict stats gathering thread */
- dict_stats_thread_handle = os_thread_create(
- dict_stats_thread, NULL, NULL);
- srv_dict_stats_thread_active = true;
- dict_stats_thread_started = true;
-
- /* Create the thread that will optimize the FTS sub-system. */
- fts_optimize_init();
-
/* Create thread(s) that handles key rotation */
fil_system_enter();
fil_crypt_threads_init();
@@ -3060,13 +3065,10 @@ srv_fts_close(void)
}
#endif
-/****************************************************************//**
-Shuts down the InnoDB database.
-@return DB_SUCCESS or error code */
+/** Shut down InnoDB. */
UNIV_INTERN
-dberr_t
-innobase_shutdown_for_mysql(void)
-/*=============================*/
+void
+innodb_shutdown()
{
ulint i;
@@ -3076,15 +3078,20 @@ innobase_shutdown_for_mysql(void)
"Shutting down an improperly started, "
"or created database!");
}
-
- return(DB_SUCCESS);
}
- if (!srv_read_only_mode) {
+ if (srv_undo_sources) {
+ ut_ad(!srv_read_only_mode);
/* Shutdown the FTS optimize sub system. */
fts_optimize_start_shutdown();
fts_optimize_end();
+ dict_stats_shutdown();
+ while (row_get_background_drop_list_len_low()) {
+ srv_wake_master_thread();
+ os_thread_yield();
+ }
+ srv_undo_sources = false;
}
/* 1. Flush the buffer pool to disk, write the current lsn to
@@ -3297,89 +3304,9 @@ innobase_shutdown_for_mysql(void)
srv_was_started = FALSE;
srv_start_has_been_called = FALSE;
-
- return(DB_SUCCESS);
}
#endif /* !UNIV_HOTBACKUP */
-
-/********************************************************************
-Signal all per-table background threads to shutdown, and wait for them to do
-so. */
-UNIV_INTERN
-void
-srv_shutdown_table_bg_threads(void)
-/*===============================*/
-{
- dict_table_t* table;
- dict_table_t* first;
- dict_table_t* last = NULL;
-
- mutex_enter(&dict_sys->mutex);
-
- /* Signal all threads that they should stop. */
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- first = table;
- while (table) {
- dict_table_t* next;
- fts_t* fts = table->fts;
-
- if (fts != NULL) {
- fts_start_shutdown(table, fts);
- }
-
- next = UT_LIST_GET_NEXT(table_LRU, table);
-
- if (!next) {
- last = table;
- }
-
- table = next;
- }
-
- /* We must release dict_sys->mutex here; if we hold on to it in the
- loop below, we will deadlock if any of the background threads try to
- acquire it (for example, the FTS thread by calling que_eval_sql).
-
- Releasing it here and going through dict_sys->table_LRU without
- holding it is safe because:
-
- a) MySQL only starts the shutdown procedure after all client
- threads have been disconnected and no new ones are accepted, so no
- new tables are added or old ones dropped.
-
- b) Despite its name, the list is not LRU, and the order stays
- fixed.
-
- To safeguard against the above assumptions ever changing, we store
- the first and last items in the list above, and then check that
- they've stayed the same below. */
-
- mutex_exit(&dict_sys->mutex);
-
- /* Wait for the threads of each table to stop. This is not inside
- the above loop, because by signaling all the threads first we can
- overlap their shutting down delays. */
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- ut_a(first == table);
- while (table) {
- dict_table_t* next;
- fts_t* fts = table->fts;
-
- if (fts != NULL) {
- fts_shutdown(table, fts);
- }
-
- next = UT_LIST_GET_NEXT(table_LRU, table);
-
- if (table == last) {
- ut_a(!next);
- }
-
- table = next;
- }
-}
-
/*****************************************************************//**
Get the meta-data filename from the table name. */
UNIV_INTERN
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 8d042ae014c..8eff14e0e99 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -243,6 +243,19 @@ trx_purge_add_update_undo_to_history(
hist_size + undo->size, MLOG_4BYTES, mtr);
}
+ /* Before any transaction-generating background threads or the
+ purge have been started, recv_recovery_rollback_active() can
+ start transactions in row_merge_drop_temp_indexes() and
+ fts_drop_orphaned_tables(), and roll back recovered transactions.
+ After the purge thread has been given permission to exit,
+ in fast shutdown, we may roll back transactions (trx->undo_no==0)
+ in THD::cleanup() invoked from unlink_thd(). */
+ ut_ad(srv_undo_sources
+ || ((srv_startup_is_before_trx_rollback_phase
+ || trx_rollback_or_clean_is_active)
+ && purge_sys->state == PURGE_STATE_INIT)
+ || (trx->undo_no == 0 && srv_fast_shutdown));
+
/* Add the log as the first in the history list */
flst_add_first(rseg_header + TRX_RSEG_HISTORY,
undo_header + TRX_UNDO_HISTORY_NODE, mtr);
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 92b783fe81c..7f5d3548acf 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -62,10 +62,10 @@ is set to TRUE by the page_cleaner thread when it is spawned and is set
back to FALSE at shutdown by the page_cleaner as well. Therefore no
need to protect it by a mutex. It is only ever read by the thread
doing the shutdown */
-UNIV_INTERN ibool buf_page_cleaner_is_active = FALSE;
+UNIV_INTERN bool buf_page_cleaner_is_active;
/** Flag indicating if the lru_manager is in active state. */
-UNIV_INTERN bool buf_lru_manager_is_active = false;
+UNIV_INTERN bool buf_lru_manager_is_active;
#ifdef UNIV_PFS_THREAD
UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key;
@@ -2799,8 +2799,6 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
- buf_page_cleaner_is_active = TRUE;
-
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
ulint page_cleaner_sleep_time;
@@ -2909,7 +2907,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/* We have lived our life. Time to die. */
thread_exit:
- buf_page_cleaner_is_active = FALSE;
+ buf_page_cleaner_is_active = false;
my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
@@ -2950,8 +2948,6 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
- buf_lru_manager_is_active = true;
-
/* On server shutdown, the LRU manager thread runs through cleanup
phase to provide free pages for the master and purge threads. */
while (srv_shutdown_state == SRV_SHUTDOWN_NONE
diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc
index ec5efe0dd7c..ba6fd115551 100644
--- a/storage/xtradb/dict/dict0stats_bg.cc
+++ b/storage/xtradb/dict/dict0stats_bg.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 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
@@ -39,12 +39,18 @@ Created Apr 25, 2012 Vasil Dimov
/** Minimum time interval between stats recalc for a given table */
#define MIN_RECALC_INTERVAL 10 /* seconds */
-#define SHUTTING_DOWN() (srv_shutdown_state != SRV_SHUTDOWN_NONE)
-
/** Event to wake up dict_stats_thread on dict_stats_recalc_pool_add()
or shutdown. Not protected by any mutex. */
UNIV_INTERN os_event_t dict_stats_event;
+/** Variable to initiate shutdown the dict stats thread. Note we don't
+use 'srv_shutdown_state' because we want to shutdown dict stats thread
+before purge thread. */
+static bool dict_stats_start_shutdown;
+
+/** Event to wait for shutdown of the dict stats thread */
+static os_event_t dict_stats_shutdown_event;
+
/** This mutex protects the "recalc_pool" variable. */
static ib_mutex_t recalc_pool_mutex;
static ib_mutex_t defrag_pool_mutex;
@@ -341,11 +347,11 @@ Must be called before dict_stats_thread() is started. */
UNIV_INTERN
void
dict_stats_thread_init()
-/*====================*/
{
ut_a(!srv_read_only_mode);
dict_stats_event = os_event_create();
+ dict_stats_shutdown_event = os_event_create();
/* The recalc_pool_mutex is acquired from:
1) the background stats gathering thread before any other latch
@@ -390,6 +396,9 @@ dict_stats_thread_deinit()
os_event_free(dict_stats_event);
dict_stats_event = NULL;
+ os_event_free(dict_stats_shutdown_event);
+ dict_stats_shutdown_event = NULL;
+ dict_stats_start_shutdown = false;
}
/*****************************************************************//**
@@ -533,7 +542,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
my_thread_init();
ut_a(!srv_read_only_mode);
- while (!SHUTTING_DOWN()) {
+ while (!dict_stats_start_shutdown) {
/* Wake up periodically even if not signaled. This is
because we may lose an event - if the below call to
@@ -543,7 +552,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
os_event_wait_time(
dict_stats_event, MIN_RECALC_INTERVAL * 1000000);
- if (SHUTTING_DOWN()) {
+ if (dict_stats_start_shutdown) {
break;
}
@@ -557,6 +566,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
srv_dict_stats_thread_active = false;
+ os_event_set(dict_stats_shutdown_event);
my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */
@@ -564,3 +574,12 @@ DECLARE_THREAD(dict_stats_thread)(void*)
OS_THREAD_DUMMY_RETURN;
}
+
+/** Shut down the dict_stats_thread. */
+void
+dict_stats_shutdown()
+{
+ dict_stats_start_shutdown = true;
+ os_event_set(dict_stats_event);
+ os_event_wait(dict_stats_shutdown_event);
+}
diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc
index 40a9faa6914..df8c6ffe222 100644
--- a/storage/xtradb/fsp/fsp0fsp.cc
+++ b/storage/xtradb/fsp/fsp0fsp.cc
@@ -2740,7 +2740,6 @@ fsp_reserve_free_extents(
ibool success;
ulint n_pages_added;
size_t total_reserved = 0;
- ulint rounds = 0;
ut_ad(mtr);
*n_reserved = n_ext;
@@ -2819,17 +2818,7 @@ try_to_extend:
success = fsp_try_extend_data_file(&n_pages_added, space,
space_header, mtr);
if (success && n_pages_added > 0) {
-
- rounds++;
total_reserved += n_pages_added;
-
- if (rounds > 50) {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Space id %lu trying to reserve %lu extents actually reserved %lu "
- " reserve %lu free %lu size %lu rounds %lu total_reserved %llu",
- space, n_ext, n_pages_added, reserve, n_free, size, rounds, (ullint) total_reserved);
- }
-
goto try_again;
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index dd5d041aed9..ee1e306b441 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1610,14 +1610,11 @@ innobase_drop_database(
the path is used as the database name:
for example, in 'mysql/data/test' the
database name is 'test' */
-/*******************************************************************//**
-Closes an InnoDB database. */
+/** Shut down the InnoDB storage engine.
+@return 0 */
static
int
-innobase_end(
-/*=========*/
- handlerton* hton, /* in: Innodb handlerton */
- ha_panic_function type);
+innobase_end(handlerton*, ha_panic_function);
#if NOT_USED
/*****************************************************************//**
@@ -4493,21 +4490,13 @@ error:
DBUG_RETURN(TRUE);
}
-/*******************************************************************//**
-Closes an InnoDB database.
-@return TRUE if error */
+/** Shut down the InnoDB storage engine.
+@return 0 */
static
int
-innobase_end(
-/*=========*/
- handlerton* hton, /*!< in/out: InnoDB handlerton */
- ha_panic_function type MY_ATTRIBUTE((unused)))
- /*!< in: ha_panic() parameter */
+innobase_end(handlerton*, ha_panic_function)
{
- int err= 0;
-
DBUG_ENTER("innobase_end");
- DBUG_ASSERT(hton == innodb_hton_ptr);
if (innodb_inited) {
@@ -4524,9 +4513,7 @@ innobase_end(
innodb_inited = 0;
hash_table_free(innobase_open_tables);
innobase_open_tables = NULL;
- if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
- err = 1;
- }
+ innodb_shutdown();
srv_free_paths_and_sizes();
my_free(internal_innobase_data_file_path);
mysql_mutex_destroy(&innobase_share_mutex);
@@ -4535,7 +4522,7 @@ innobase_end(
mysql_mutex_destroy(&pending_checkpoint_mutex);
}
- DBUG_RETURN(err);
+ DBUG_RETURN(0);
}
/****************************************************************//**
@@ -18818,6 +18805,10 @@ innodb_sched_priority_cleaner_update(
const void* save) /*!< in: immediate result
from check function */
{
+ if (srv_read_only_mode) {
+ return;
+ }
+
ulint priority = *static_cast<const ulint *>(save);
ulint actual_priority;
ulint nice = 0;
@@ -18844,10 +18835,6 @@ innodb_sched_priority_cleaner_update(
}
/* Set the priority for the page cleaner thread */
- if (srv_read_only_mode) {
-
- return;
- }
ut_ad(buf_page_cleaner_is_active);
nice = os_thread_get_priority(srv_cleaner_tid);
diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h
index af50a5498ef..6089baf81e8 100644
--- a/storage/xtradb/include/buf0flu.h
+++ b/storage/xtradb/include/buf0flu.h
@@ -34,7 +34,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0types.h"
/** Flag indicating if the page_cleaner is in active state. */
-extern ibool buf_page_cleaner_is_active;
+extern bool buf_page_cleaner_is_active;
/** Flag indicating if the lru_manager is in active state. */
extern bool buf_lru_manager_is_active;
diff --git a/storage/xtradb/include/dict0stats_bg.h b/storage/xtradb/include/dict0stats_bg.h
index d5f0870718d..8f3385eb22b 100644
--- a/storage/xtradb/include/dict0stats_bg.h
+++ b/storage/xtradb/include/dict0stats_bg.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 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
@@ -144,6 +144,10 @@ DECLARE_THREAD(dict_stats_thread)(
void* arg); /*!< in: a dummy parameter
required by os_thread_create */
+/** Shut down the dict_stats_thread. */
+void
+dict_stats_shutdown();
+
# ifndef UNIV_NONINL
# include "dict0stats_bg.ic"
# endif
diff --git a/storage/xtradb/include/srv0start.h b/storage/xtradb/include/srv0start.h
index a60776a4665..b055a9d834f 100644
--- a/storage/xtradb/include/srv0start.h
+++ b/storage/xtradb/include/srv0start.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 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
@@ -75,22 +76,12 @@ are not found and the user wants.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
-innobase_start_or_create_for_mysql(void);
-/*====================================*/
-/****************************************************************//**
-Shuts down the Innobase database.
-@return DB_SUCCESS or error code */
-UNIV_INTERN
-dberr_t
-innobase_shutdown_for_mysql(void);
+innobase_start_or_create_for_mysql();
-/********************************************************************
-Signal all per-table background threads to shutdown, and wait for them to do
-so. */
+/** Shut down InnoDB. */
UNIV_INTERN
void
-srv_shutdown_table_bg_threads(void);
-/*=============================*/
+innodb_shutdown();
/*************************************************************//**
Copy the file path component of the physical file to parameter. It will
@@ -158,6 +149,9 @@ enum srv_shutdown_state {
SRV_SHUTDOWN_EXIT_THREADS/*!< Exit all threads */
};
+/** Whether any undo log records can be generated */
+extern bool srv_undo_sources;
+
/** At a shutdown this value climbs from SRV_SHUTDOWN_NONE to
SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern enum srv_shutdown_state srv_shutdown_state;
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index 82e2ab15a0b..0942dcc41d0 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -3214,31 +3214,29 @@ suspend_thread:
goto loop;
}
-/*********************************************************************//**
-Check if purge should stop.
-@return true if it should shutdown. */
+/** Check if purge should stop.
+@param[in] n_purged pages purged in the last batch
+@return whether purge should exit */
static
bool
-srv_purge_should_exit(
-/*==============*/
- ulint n_purged) /*!< in: pages purged in last batch */
+srv_purge_should_exit(ulint n_purged)
{
- switch (srv_shutdown_state) {
- case SRV_SHUTDOWN_NONE:
- /* Normal operation. */
- break;
+ ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE
+ || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
- case SRV_SHUTDOWN_CLEANUP:
- case SRV_SHUTDOWN_EXIT_THREADS:
- /* Exit unless slow shutdown requested or all done. */
- return(srv_fast_shutdown != 0 || n_purged == 0);
-
- case SRV_SHUTDOWN_LAST_PHASE:
- case SRV_SHUTDOWN_FLUSH_PHASE:
- ut_error;
+ if (srv_undo_sources) {
+ return(false);
}
-
- return(false);
+ if (srv_fast_shutdown) {
+ return(true);
+ }
+ /* Slow shutdown was requested. */
+ if (n_purged) {
+ /* The previous round still did some work. */
+ return(false);
+ }
+ /* Exit if there are no active transactions to roll back. */
+ return(trx_sys_any_active_transactions() == 0);
}
/*********************************************************************//**
@@ -3513,7 +3511,7 @@ srv_purge_coordinator_suspend(
}
rw_lock_x_unlock(&purge_sys->latch);
- } while (stop);
+ } while (stop && srv_undo_sources);
srv_resume_thread(slot, 0, false);
}
@@ -3567,6 +3565,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
purge didn't purge any records then wait for activity. */
if (srv_shutdown_state == SRV_SHUTDOWN_NONE
+ && srv_undo_sources
&& (purge_sys->state == PURGE_STATE_STOP
|| n_total_purged == 0)) {
@@ -3587,36 +3586,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_n_purge_threads, &n_total_purged);
srv_inc_activity_count();
-
} while (!srv_purge_should_exit(n_total_purged));
- /* Ensure that we don't jump out of the loop unless the
- exit condition is satisfied. */
-
- ut_a(srv_purge_should_exit(n_total_purged));
-
- ulint n_pages_purged = ULINT_MAX;
-
- /* Ensure that all records are purged if it is not a fast shutdown.
- This covers the case where a record can be added after we exit the
- loop above. */
- while (srv_fast_shutdown == 0 && n_pages_purged > 0) {
- n_pages_purged = trx_purge(1, srv_purge_batch_size, false);
- }
-
- /* This trx_purge is called to remove any undo records (added by
- background threads) after completion of the above loop. When
- srv_fast_shutdown != 0, a large batch size can cause significant
- delay in shutdown ,so reducing the batch size to magic number 20
- (which was default in 5.5), which we hope will be sufficient to
- remove all the undo records */
- const uint temp_batch_size = 20;
-
- n_pages_purged = trx_purge(1, srv_purge_batch_size <= temp_batch_size
- ? srv_purge_batch_size : temp_batch_size,
- true);
- ut_a(n_pages_purged == 0 || srv_fast_shutdown != 0);
-
/* The task queue should always be empty, independent of fast
shutdown state. */
ut_a(srv_get_task_queue_length() == 0);
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 6fd8e8944f5..fdb136ef67e 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -132,7 +132,11 @@ UNIV_INTERN ibool srv_is_being_started = FALSE;
/** TRUE if the server was successfully started */
UNIV_INTERN ibool srv_was_started = FALSE;
/** TRUE if innobase_start_or_create_for_mysql() has been called */
-static ibool srv_start_has_been_called = FALSE;
+static ibool srv_start_has_been_called;
+
+/** Whether any undo log records can be generated */
+UNIV_INTERN bool srv_undo_sources;
+
#ifdef UNIV_DEBUG
/** InnoDB system tablespace to set during recovery */
UNIV_INTERN uint srv_sys_space_size_debug;
@@ -1684,8 +1688,7 @@ are not found and the user wants.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
-innobase_start_or_create_for_mysql(void)
-/*====================================*/
+innobase_start_or_create_for_mysql()
{
bool create_new_db;
lsn_t flushed_lsn;
@@ -2862,8 +2865,8 @@ files_checked:
}
}
- srv_startup_is_before_trx_rollback_phase = FALSE;
recv_recovery_rollback_active();
+ srv_startup_is_before_trx_rollback_phase = FALSE;
/* It is possible that file_format tag has never
been set. In this case we initialize it to minimum
@@ -2995,6 +2998,16 @@ files_checked:
srv_master_thread,
NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
thread_started[1 + SRV_MAX_N_IO_THREADS] = true;
+
+ srv_undo_sources = true;
+ /* Create the dict stats gathering thread */
+ srv_dict_stats_thread_active = true;
+ dict_stats_thread_handle = os_thread_create(
+ dict_stats_thread, NULL, NULL);
+ dict_stats_thread_started = true;
+
+ /* Create the thread that will optimize the FTS sub-system. */
+ fts_optimize_init();
}
if (!srv_read_only_mode
@@ -3039,12 +3052,16 @@ files_checked:
}
- buf_flush_page_cleaner_thread_handle = os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
+ buf_page_cleaner_is_active = true;
+ buf_flush_page_cleaner_thread_handle = os_thread_create(
+ buf_flush_page_cleaner_thread, NULL, NULL);
buf_flush_page_cleaner_thread_started = true;
- }
- buf_flush_lru_manager_thread_handle = os_thread_create(buf_flush_lru_manager_thread, NULL, NULL);
- buf_flush_lru_manager_thread_started = true;
+ buf_lru_manager_is_active = true;
+ buf_flush_lru_manager_thread_handle = os_thread_create(
+ buf_flush_lru_manager_thread, NULL, NULL);
+ buf_flush_lru_manager_thread_started = true;
+ }
if (!srv_file_per_table && srv_pass_corrupt_table) {
fprintf(stderr, "InnoDB: Warning:"
@@ -3092,10 +3109,10 @@ files_checked:
if (!wsrep_recovery) {
#endif /* WITH_WSREP */
/* Create the buffer pool dump/load thread */
+ srv_buf_dump_thread_active = true;
buf_dump_thread_handle=
os_thread_create(buf_dump_thread, NULL, NULL);
- srv_buf_dump_thread_active = true;
buf_dump_thread_started = true;
#ifdef WITH_WSREP
} else {
@@ -3105,15 +3122,6 @@ files_checked:
}
#endif /* WITH_WSREP */
- /* Create the dict stats gathering thread */
- dict_stats_thread_handle = os_thread_create(
- dict_stats_thread, NULL, NULL);
- srv_dict_stats_thread_active = true;
- dict_stats_thread_started = true;
-
- /* Create the thread that will optimize the FTS sub-system. */
- fts_optimize_init();
-
/* Create thread(s) that handles key rotation */
fil_system_enter();
fil_crypt_threads_init();
@@ -3163,13 +3171,10 @@ srv_fts_close(void)
}
#endif
-/****************************************************************//**
-Shuts down the InnoDB database.
-@return DB_SUCCESS or error code */
+/** Shut down InnoDB. */
UNIV_INTERN
-dberr_t
-innobase_shutdown_for_mysql(void)
-/*=============================*/
+void
+innodb_shutdown()
{
ulint i;
@@ -3179,15 +3184,20 @@ innobase_shutdown_for_mysql(void)
"Shutting down an improperly started, "
"or created database!");
}
-
- return(DB_SUCCESS);
}
- if (!srv_read_only_mode) {
+ if (srv_undo_sources) {
+ ut_ad(!srv_read_only_mode);
/* Shutdown the FTS optimize sub system. */
fts_optimize_start_shutdown();
fts_optimize_end();
+ dict_stats_shutdown();
+ while (row_get_background_drop_list_len_low()) {
+ srv_wake_master_thread();
+ os_thread_yield();
+ }
+ srv_undo_sources = false;
}
/* 1. Flush the buffer pool to disk, write the current lsn to
@@ -3402,88 +3412,9 @@ innobase_shutdown_for_mysql(void)
srv_start_has_been_called = FALSE;
/* reset io_tid_i, in case current process does second innodb start (xtrabackup might do that).*/
io_tid_i = 0;
- return(DB_SUCCESS);
}
#endif /* !UNIV_HOTBACKUP */
-
-/********************************************************************
-Signal all per-table background threads to shutdown, and wait for them to do
-so. */
-UNIV_INTERN
-void
-srv_shutdown_table_bg_threads(void)
-/*===============================*/
-{
- dict_table_t* table;
- dict_table_t* first;
- dict_table_t* last = NULL;
-
- mutex_enter(&dict_sys->mutex);
-
- /* Signal all threads that they should stop. */
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- first = table;
- while (table) {
- dict_table_t* next;
- fts_t* fts = table->fts;
-
- if (fts != NULL) {
- fts_start_shutdown(table, fts);
- }
-
- next = UT_LIST_GET_NEXT(table_LRU, table);
-
- if (!next) {
- last = table;
- }
-
- table = next;
- }
-
- /* We must release dict_sys->mutex here; if we hold on to it in the
- loop below, we will deadlock if any of the background threads try to
- acquire it (for example, the FTS thread by calling que_eval_sql).
-
- Releasing it here and going through dict_sys->table_LRU without
- holding it is safe because:
-
- a) MySQL only starts the shutdown procedure after all client
- threads have been disconnected and no new ones are accepted, so no
- new tables are added or old ones dropped.
-
- b) Despite its name, the list is not LRU, and the order stays
- fixed.
-
- To safeguard against the above assumptions ever changing, we store
- the first and last items in the list above, and then check that
- they've stayed the same below. */
-
- mutex_exit(&dict_sys->mutex);
-
- /* Wait for the threads of each table to stop. This is not inside
- the above loop, because by signaling all the threads first we can
- overlap their shutting down delays. */
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- ut_a(first == table);
- while (table) {
- dict_table_t* next;
- fts_t* fts = table->fts;
-
- if (fts != NULL) {
- fts_shutdown(table, fts);
- }
-
- next = UT_LIST_GET_NEXT(table_LRU, table);
-
- if (table == last) {
- ut_a(!next);
- }
-
- table = next;
- }
-}
-
/*****************************************************************//**
Get the meta-data filename from the table name. */
UNIV_INTERN
diff --git a/storage/xtradb/trx/trx0purge.cc b/storage/xtradb/trx/trx0purge.cc
index 90f22e7ef82..df4a3217820 100644
--- a/storage/xtradb/trx/trx0purge.cc
+++ b/storage/xtradb/trx/trx0purge.cc
@@ -247,6 +247,19 @@ trx_purge_add_update_undo_to_history(
hist_size + undo->size, MLOG_4BYTES, mtr);
}
+ /* Before any transaction-generating background threads or the
+ purge have been started, recv_recovery_rollback_active() can
+ start transactions in row_merge_drop_temp_indexes() and
+ fts_drop_orphaned_tables(), and roll back recovered transactions.
+ After the purge thread has been given permission to exit,
+ in fast shutdown, we may roll back transactions (trx->undo_no==0)
+ in THD::cleanup() invoked from unlink_thd(). */
+ ut_ad(srv_undo_sources
+ || ((srv_startup_is_before_trx_rollback_phase
+ || trx_rollback_or_clean_is_active)
+ && purge_sys->state == PURGE_STATE_INIT)
+ || (trx->undo_no == 0 && srv_fast_shutdown));
+
/* Add the log as the first in the history list */
flst_add_first(rseg_header + TRX_RSEG_HISTORY,
undo_header + TRX_UNDO_HISTORY_NODE, mtr);