summaryrefslogtreecommitdiff
path: root/storage/xtradb/srv
diff options
context:
space:
mode:
authorSachin Setiya <sachin.setiya@mariadb.com>2017-03-17 02:05:20 +0530
committerSachin Setiya <sachin.setiya@mariadb.com>2017-03-17 02:05:20 +0530
commitf66395f7c06f357e7ace74317e6563a1e5dbc3ae (patch)
treed1669b069aa722c9c73abe52e5924b7bbba41b39 /storage/xtradb/srv
parentc401773c8dd97bd9f6bf6cff9fcafdf24fbd0ee1 (diff)
parentc4f3e64c23fe7f7fd18c0a79f87f9771df15fe9f (diff)
downloadmariadb-git-f66395f7c06f357e7ace74317e6563a1e5dbc3ae.tar.gz
Merge tag 'mariadb-10.0.30' into bb-sachin-10.0-galera-merge
Signed-off-by: Sachin Setiya <sachin.setiya@mariadb.com>
Diffstat (limited to 'storage/xtradb/srv')
-rw-r--r--storage/xtradb/srv/srv0conc.cc9
-rw-r--r--storage/xtradb/srv/srv0srv.cc314
-rw-r--r--storage/xtradb/srv/srv0start.cc383
3 files changed, 321 insertions, 385 deletions
diff --git a/storage/xtradb/srv/srv0conc.cc b/storage/xtradb/srv/srv0conc.cc
index 0580d7d0054..dadb1f19a8a 100644
--- a/storage/xtradb/srv/srv0conc.cc
+++ b/storage/xtradb/srv/srv0conc.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -82,7 +83,9 @@ typedef UT_LIST_NODE_T(struct srv_conc_slot_t) srv_conc_node_t;
/** Slot for a thread waiting in the concurrency control queue. */
struct srv_conc_slot_t{
- os_event_t event; /*!< event to wait */
+ os_event_t event; /*!< event to wait for;
+ os_event_set() and os_event_reset()
+ are protected by srv_conc_mutex */
ibool reserved; /*!< TRUE if slot
reserved */
ibool wait_ended; /*!< TRUE when another thread has
@@ -381,11 +384,11 @@ srv_conc_exit_innodb_without_atomics(
}
}
- os_fast_mutex_unlock(&srv_conc_mutex);
-
if (slot != NULL) {
os_event_set(slot->event);
}
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
}
/*********************************************************************//**
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index c04b446f480..a76c6aaf62b 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -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, 2014, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -74,12 +74,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mysql/plugin.h"
#include "mysql/service_thd_wait.h"
-/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
-ibool innobase_thd_is_idle(const void* thd);
-ib_int64_t innobase_thd_get_start_time(const void* thd);
-void innobase_thd_kill(ulong thd_id);
-ulong innobase_thd_get_thread_id(const void* thd);
-
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
@@ -440,11 +434,6 @@ starting from SRV_FORCE_IGNORE_CORRUPT, so that data can be recovered
by SELECT or mysqldump. When this is nonzero, we do not allow any user
modifications to the data. */
UNIV_INTERN ulong srv_force_recovery;
-#ifndef DBUG_OFF
-/** Inject a crash at different steps of the recovery process.
-This is for testing and debugging only. */
-UNIV_INTERN ulong srv_force_recovery_crash;
-#endif /* !DBUG_OFF */
/** Print all user-level transactions deadlocks to mysqld stderr */
@@ -473,6 +462,7 @@ this many index pages, there are 2 ways to calculate statistics:
table/index are not found in the innodb database */
UNIV_INTERN unsigned long long srv_stats_transient_sample_pages = 8;
UNIV_INTERN my_bool srv_stats_persistent = TRUE;
+UNIV_INTERN my_bool srv_stats_include_delete_marked = FALSE;
UNIV_INTERN unsigned long long srv_stats_persistent_sample_pages = 20;
UNIV_INTERN my_bool srv_stats_auto_recalc = TRUE;
@@ -747,7 +737,11 @@ struct srv_sys_t{
ulint n_sys_threads; /*!< size of the sys_threads
array */
- srv_slot_t* sys_threads; /*!< server thread table */
+ srv_slot_t* sys_threads; /*!< server thread table;
+ os_event_set() and
+ os_event_reset() on
+ sys_threads[]->event are
+ covered by srv_sys_t::mutex */
ulint n_threads_active[SRV_MASTER + 1];
/*!< number of threads active
@@ -769,13 +763,16 @@ UNIV_INTERN ib_mutex_t server_mutex;
static srv_sys_t* srv_sys = NULL;
-/** Event to signal the monitor thread. */
+/** Event to signal srv_monitor_thread. Not protected by a mutex.
+Set after setting srv_print_innodb_monitor. */
UNIV_INTERN os_event_t srv_monitor_event;
-/** Event to signal the error thread */
+/** Event to signal the shutdown of srv_error_monitor_thread.
+Not protected by a mutex. */
UNIV_INTERN os_event_t srv_error_event;
-/** Event to signal the buffer pool dump/load thread */
+/** Event for waking up buf_dump_thread. Not protected by a mutex.
+Set on shutdown or by buf_dump_start() or buf_load_start(). */
UNIV_INTERN os_event_t srv_buf_dump_event;
/** The buffer pool dump/load file name */
@@ -945,7 +942,6 @@ srv_suspend_thread_low(
/*===================*/
srv_slot_t* slot) /*!< in/out: thread slot */
{
-
ut_ad(!srv_read_only_mode);
ut_ad(srv_sys_mutex_own());
@@ -1003,34 +999,71 @@ srv_suspend_thread(
return(sig_count);
}
-/*********************************************************************//**
-Releases threads of the type given from suspension in the thread table.
-NOTE! The server mutex has to be reserved by the caller!
-@return number of threads released: this may be less than n if not
- enough threads were suspended at the moment. */
-UNIV_INTERN
-ulint
-srv_release_threads(
-/*================*/
- srv_thread_type type, /*!< in: thread type */
- ulint n) /*!< in: number of threads to release */
+/** Resume the calling thread.
+@param[in,out] slot thread slot
+@param[in] sig_count signal count (if wait)
+@param[in] wait whether to wait for the event
+@param[in] timeout_usec timeout in microseconds (0=infinite)
+@return whether the wait timed out */
+static
+bool
+srv_resume_thread(srv_slot_t* slot, ib_int64_t sig_count = 0, bool wait = true,
+ ulint timeout_usec = 0)
+{
+ bool timeout;
+
+ ut_ad(!srv_read_only_mode);
+ ut_ad(slot->in_use);
+ ut_ad(slot->suspended);
+
+ if (!wait) {
+ timeout = false;
+ } else if (timeout_usec) {
+ timeout = OS_SYNC_TIME_EXCEEDED == os_event_wait_time_low(
+ slot->event, timeout_usec, sig_count);
+ } else {
+ timeout = false;
+ os_event_wait_low(slot->event, sig_count);
+ }
+
+ srv_sys_mutex_enter();
+ ut_ad(slot->in_use);
+ ut_ad(slot->suspended);
+
+ slot->suspended = FALSE;
+ ++srv_sys->n_threads_active[slot->type];
+ srv_sys_mutex_exit();
+ return(timeout);
+}
+
+/** Ensure that a given number of threads of the type given are running
+(or are already terminated).
+@param[in] type thread type
+@param[in] n number of threads that have to run */
+void
+srv_release_threads(enum srv_thread_type type, ulint n)
{
- ulint i;
- ulint count = 0;
+ ulint running;
ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
- srv_sys_mutex_enter();
+ do {
+ running = 0;
- for (i = 0; i < srv_sys->n_sys_threads; i++) {
- srv_slot_t* slot;
+ srv_sys_mutex_enter();
- slot = &srv_sys->sys_threads[i];
+ for (ulint i = 0; i < srv_sys->n_sys_threads; i++) {
+ srv_slot_t* slot = &srv_sys->sys_threads[i];
- if (slot->in_use
- && srv_slot_get_type(slot) == type
- && slot->suspended) {
+ if (!slot->in_use || srv_slot_get_type(slot) != type) {
+ continue;
+ } else if (!slot->suspended) {
+ if (++running >= n) {
+ break;
+ }
+ continue;
+ }
switch (type) {
case SRV_NONE:
@@ -1060,21 +1093,11 @@ srv_release_threads(
break;
}
- slot->suspended = FALSE;
-
- ++srv_sys->n_threads_active[type];
-
os_event_set(slot->event);
-
- if (++count == n) {
- break;
- }
}
- }
- srv_sys_mutex_exit();
-
- return(count);
+ srv_sys_mutex_exit();
+ } while (running && running < n);
}
/*********************************************************************//**
@@ -1087,11 +1110,8 @@ srv_free_slot(
{
srv_sys_mutex_enter();
- if (!slot->suspended) {
- /* Mark the thread as inactive. */
- srv_suspend_thread_low(slot);
- }
-
+ /* Mark the thread as inactive. */
+ srv_suspend_thread_low(slot);
/* Free the slot for reuse. */
ut_ad(slot->in_use);
slot->in_use = FALSE;
@@ -1402,22 +1422,26 @@ srv_printf_innodb_monitor(
low level 135. Therefore we can reserve the latter mutex here without
a danger of a deadlock of threads. */
- mutex_enter(&dict_foreign_err_mutex);
+ if (!recv_recovery_on) {
- if (!srv_read_only_mode && ftell(dict_foreign_err_file) != 0L) {
- fputs("------------------------\n"
- "LATEST FOREIGN KEY ERROR\n"
- "------------------------\n", file);
- ut_copy_file(file, dict_foreign_err_file);
- }
+ mutex_enter(&dict_foreign_err_mutex);
- mutex_exit(&dict_foreign_err_mutex);
+ if (!srv_read_only_mode
+ && ftell(dict_foreign_err_file) != 0L) {
+ fputs("------------------------\n"
+ "LATEST FOREIGN KEY ERROR\n"
+ "------------------------\n", file);
+ ut_copy_file(file, dict_foreign_err_file);
+ }
+
+ mutex_exit(&dict_foreign_err_mutex);
+ }
/* Only if lock_print_info_summary proceeds correctly,
before we call the lock_print_info_all_transactions
to print all the lock information. IMPORTANT NOTE: This
function acquires the lock mutex on success. */
- ret = lock_print_info_summary(file, nowait);
+ ret = recv_recovery_on ? FALSE : lock_print_info_summary(file, nowait);
if (ret) {
if (trx_start_pos) {
@@ -1450,10 +1474,13 @@ srv_printf_innodb_monitor(
"--------\n", file);
os_aio_print(file);
- fputs("-------------------------------------\n"
- "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
- "-------------------------------------\n", file);
- ibuf_print(file);
+ if (!recv_recovery_on) {
+
+ fputs("-------------------------------------\n"
+ "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
+ "-------------------------------------\n", file);
+ ibuf_print(file);
+ }
fprintf(file,
@@ -1465,10 +1492,13 @@ srv_printf_innodb_monitor(
btr_cur_n_sea_old = btr_cur_n_sea;
btr_cur_n_non_sea_old = btr_cur_n_non_sea;
- fputs("---\n"
- "LOG\n"
- "---\n", file);
- log_print(file);
+ if (!recv_recovery_on) {
+
+ fputs("---\n"
+ "LOG\n"
+ "---\n", file);
+ log_print(file);
+ }
fputs("----------------------\n"
"BUFFER POOL AND MEMORY\n"
@@ -1563,8 +1593,9 @@ srv_printf_innodb_monitor(
? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0),
recv_sys_subtotal);
+
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
- dict_sys->size);
+ dict_sys ? dict_sys->size : 0);
buf_print_io(file);
@@ -1672,6 +1703,10 @@ srv_printf_innodb_monitor(
mutex_exit(&srv_innodb_monitor_mutex);
fflush(file);
+#ifndef DBUG_OFF
+ srv_debug_monitor_printed = true;
+#endif
+
return(ret);
}
@@ -1982,6 +2017,12 @@ srv_export_innodb_status(void)
mutex_exit(&srv_innodb_monitor_mutex);
}
+#ifndef DBUG_OFF
+/** false before InnoDB monitor has been printed at least once, true
+afterwards */
+bool srv_debug_monitor_printed = false;
+#endif
+
/*********************************************************************//**
A thread which prints the info output by various InnoDB monitors.
@return a dummy parameter */
@@ -2266,36 +2307,6 @@ loop:
old_sema = sema;
}
- if (srv_kill_idle_transaction && trx_sys) {
- trx_t* trx;
- time_t now;
-rescan_idle:
- now = time(NULL);
- mutex_enter(&trx_sys->mutex);
- trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
- while (trx) {
- if (trx->state == TRX_STATE_ACTIVE
- && trx->mysql_thd
- && innobase_thd_is_idle(trx->mysql_thd)) {
- ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd);
- ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd);
-
- if (trx->last_stmt_start != start_time) {
- trx->idle_start = now;
- trx->last_stmt_start = start_time;
- } else if (difftime(now, trx->idle_start)
- > srv_kill_idle_transaction) {
- /* kill the session */
- mutex_exit(&trx_sys->mutex);
- innobase_thd_kill(thd_id);
- goto rescan_idle;
- }
- }
- trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
- }
- mutex_exit(&trx_sys->mutex);
- }
-
/* Flush stderr so that a database user gets the output
to possible MySQL error file */
@@ -2451,10 +2462,8 @@ DECLARE_THREAD(srv_redo_log_follow_thread)(
} while (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE);
- srv_track_changed_pages = FALSE;
log_online_read_shutdown();
os_event_set(srv_redo_log_tracked_event);
- srv_redo_log_thread_started = false; /* Defensive, not required */
my_thread_end();
os_thread_exit(NULL);
@@ -2620,15 +2629,7 @@ srv_active_wake_master_thread(void)
if (slot->in_use) {
ut_a(srv_slot_get_type(slot) == SRV_MASTER);
-
- if (slot->suspended) {
-
- slot->suspended = FALSE;
-
- ++srv_sys->n_threads_active[SRV_MASTER];
-
- os_event_set(slot->event);
- }
+ os_event_set(slot->event);
}
srv_sys_mutex_exit();
@@ -3149,7 +3150,7 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
- os_event_wait(slot->event);
+ srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
@@ -3271,8 +3272,7 @@ DECLARE_THREAD(srv_worker_thread)(
do {
srv_suspend_thread(slot);
-
- os_event_wait(slot->event);
+ srv_resume_thread(slot);
srv_current_thread_priority = srv_purge_thread_priority;
@@ -3412,8 +3412,6 @@ srv_purge_coordinator_suspend(
ib_int64_t sig_count = srv_suspend_thread(slot);
do {
- ulint ret;
-
rw_lock_x_lock(&purge_sys->latch);
purge_sys->running = false;
@@ -3422,32 +3420,11 @@ srv_purge_coordinator_suspend(
/* We don't wait right away on the the non-timed wait because
we want to signal the thread that wants to suspend purge. */
-
- if (stop) {
- os_event_wait_low(slot->event, sig_count);
- ret = 0;
- } else if (rseg_history_len <= trx_sys->rseg_history_len) {
- ret = os_event_wait_time_low(
- slot->event, SRV_PURGE_MAX_TIMEOUT, sig_count);
- } else {
- /* We don't want to waste time waiting, if the
- history list increased by the time we got here,
- unless purge has been stopped. */
- ret = 0;
- }
-
- srv_sys_mutex_enter();
-
- /* The thread can be in state !suspended after the timeout
- but before this check if another thread sent a wakeup signal. */
-
- if (slot->suspended) {
- slot->suspended = FALSE;
- ++srv_sys->n_threads_active[slot->type];
- ut_a(srv_sys->n_threads_active[slot->type] == 1);
- }
-
- srv_sys_mutex_exit();
+ const bool wait = stop
+ || rseg_history_len <= trx_sys->rseg_history_len;
+ const bool timeout = srv_resume_thread(
+ slot, sig_count, wait,
+ stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
sig_count = srv_suspend_thread(slot);
@@ -3459,6 +3436,19 @@ srv_purge_coordinator_suspend(
if (!stop) {
ut_a(purge_sys->n_stop == 0);
purge_sys->running = true;
+
+ if (timeout
+ && rseg_history_len == trx_sys->rseg_history_len
+ && trx_sys->rseg_history_len < 5000) {
+ /* No new records were added since the
+ wait started. Simply wait for new
+ records. The magic number 5000 is an
+ approximation for the case where we
+ have cached UNDO log records which
+ prevent truncate of the UNDO
+ segments. */
+ stop = true;
+ }
} else {
ut_a(purge_sys->n_stop > 0);
@@ -3467,33 +3457,9 @@ srv_purge_coordinator_suspend(
}
rw_lock_x_unlock(&purge_sys->latch);
-
- if (ret == OS_SYNC_TIME_EXCEEDED) {
-
- /* No new records added since wait started then simply
- wait for new records. The magic number 5000 is an
- approximation for the case where we have cached UNDO
- log records which prevent truncate of the UNDO
- segments. */
-
- if (rseg_history_len == trx_sys->rseg_history_len
- && trx_sys->rseg_history_len < 5000) {
-
- stop = true;
- }
- }
-
} while (stop);
- srv_sys_mutex_enter();
-
- if (slot->suspended) {
- slot->suspended = FALSE;
- ++srv_sys->n_threads_active[slot->type];
- ut_a(srv_sys->n_threads_active[slot->type] == 1);
- }
-
- srv_sys_mutex_exit();
+ srv_resume_thread(slot, 0, false);
}
/*********************************************************************//**
@@ -3549,8 +3515,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_purge_coordinator_suspend(slot, rseg_history_len);
}
+ ut_ad(!slot->suspended);
+
if (srv_purge_should_exit(n_total_purged)) {
- ut_a(!slot->suspended);
break;
}
@@ -3665,12 +3632,10 @@ srv_get_task_queue_length(void)
return(n_tasks);
}
-/**********************************************************************//**
-Wakeup the purge threads. */
+/** Wake up the purge threads. */
UNIV_INTERN
void
-srv_purge_wakeup(void)
-/*==================*/
+srv_purge_wakeup()
{
ut_ad(!srv_read_only_mode);
@@ -3685,4 +3650,3 @@ srv_purge_wakeup(void)
}
}
}
-
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 270489a1973..35b378ec831 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -613,19 +613,6 @@ create_log_file(
/** Initial number of the first redo log file */
#define INIT_LOG_FILE0 (SRV_N_LOG_FILES_MAX + 1)
-#ifdef DBUG_OFF
-# define RECOVERY_CRASH(x) do {} while(0)
-#else
-# define RECOVERY_CRASH(x) do { \
- if (srv_force_recovery_crash == x) { \
- fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \
- srv_force_recovery_crash); \
- fflush(stderr); \
- exit(3); \
- } \
-} while (0)
-#endif
-
/*********************************************************************//**
Creates all log files.
@return DB_SUCCESS or error code */
@@ -666,13 +653,14 @@ create_log_files(
file should be recoverable. The buffer
pool was clean, and we can simply create
all log files from the scratch. */
- RECOVERY_CRASH(6);
+ DBUG_EXECUTE_IF("innodb_log_abort_6",
+ return(DB_ERROR););
}
}
ut_ad(!buf_pool_check_no_pending_io());
- RECOVERY_CRASH(7);
+ DBUG_EXECUTE_IF("innodb_log_abort_7", return(DB_ERROR););
for (unsigned i = 0; i < srv_n_log_files; i++) {
sprintf(logfilename + dirnamelen,
@@ -685,7 +673,7 @@ create_log_files(
}
}
- RECOVERY_CRASH(8);
+ DBUG_EXECUTE_IF("innodb_log_abort_8", return(DB_ERROR););
/* We did not create the first log file initially as
ib_logfile0, so that crash recovery cannot find it until it
@@ -740,10 +728,16 @@ create_log_files(
return(DB_SUCCESS);
}
-/*********************************************************************//**
-Renames the first log file. */
+/** Rename the first redo log file.
+@param[in,out] logfilename buffer for the log file name
+@param[in] dirnamelen length of the directory path
+@param[in] lsn FIL_PAGE_FILE_FLUSH_LSN value
+@param[in,out] logfile0 name of the first log file
+@return error code
+@retval DB_SUCCESS on successful operation */
+MY_ATTRIBUTE((warn_unused_result, nonnull))
static
-void
+dberr_t
create_log_files_rename(
/*====================*/
char* logfilename, /*!< in/out: buffer for log file name */
@@ -754,6 +748,9 @@ create_log_files_rename(
/* If innodb_flush_method=O_DSYNC,
we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID);
+
+ DBUG_EXECUTE_IF("innodb_log_abort_9", return(DB_ERROR););
+
/* Close the log files, so that we can rename
the first one. */
fil_close_log_files(false);
@@ -762,26 +759,28 @@ create_log_files_rename(
checkpoint has been created. */
sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
- RECOVERY_CRASH(9);
-
ib_logf(IB_LOG_LEVEL_INFO,
"Renaming log file %s to %s", logfile0, logfilename);
mutex_enter(&log_sys->mutex);
ut_ad(strlen(logfile0) == 2 + strlen(logfilename));
- ibool success = os_file_rename(
- innodb_file_log_key, logfile0, logfilename);
- ut_a(success);
-
- RECOVERY_CRASH(10);
+ dberr_t err = os_file_rename(
+ innodb_file_log_key, logfile0, logfilename)
+ ? DB_SUCCESS : DB_ERROR;
/* Replace the first file with ib_logfile0. */
strcpy(logfile0, logfilename);
mutex_exit(&log_sys->mutex);
- fil_open_log_and_system_tablespace_files();
+ DBUG_EXECUTE_IF("innodb_log_abort_10", err = DB_ERROR;);
- ib_logf(IB_LOG_LEVEL_WARN, "New log files created, LSN=" LSN_PF, lsn);
+ if (err == DB_SUCCESS) {
+ fil_open_log_and_system_tablespace_files();
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "New log files created, LSN=" LSN_PF, lsn);
+ }
+
+ return(err);
}
/*********************************************************************//**
@@ -1613,8 +1612,6 @@ innobase_start_or_create_for_mysql(void)
lsn_t max_arch_log_no = LSN_MAX;
#endif /* UNIV_LOG_ARCHIVE */
ulint sum_of_new_sizes;
- ulint sum_of_data_file_sizes;
- ulint tablespace_size_in_header;
dberr_t err;
unsigned i;
ulint srv_n_log_files_found = srv_n_log_files;
@@ -1627,6 +1624,19 @@ innobase_start_or_create_for_mysql(void)
size_t dirnamelen;
bool sys_datafiles_created = false;
+ /* Check that os_fast_mutexes work as expected */
+ os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex);
+
+ ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex));
+
+ os_fast_mutex_unlock(&srv_os_test_mutex);
+
+ os_fast_mutex_lock(&srv_os_test_mutex);
+
+ os_fast_mutex_unlock(&srv_os_test_mutex);
+
+ os_fast_mutex_free(&srv_os_test_mutex);
+
high_level_read_only = srv_read_only_mode
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
@@ -1669,22 +1679,7 @@ innobase_start_or_create_for_mysql(void)
#endif /* PAGE_ATOMIC_REF_COUNT */
);
-
- if (sizeof(ulint) != sizeof(void*)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: size of InnoDB's ulint is %lu, "
- "but size of void*\n", (ulong) sizeof(ulint));
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: is %lu. The sizes should be the same "
- "so that on a 64-bit\n",
- (ulong) sizeof(void*));
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: platforms you can allocate more than 4 GB "
- "of memory.\n");
- }
+ compile_time_assert(sizeof(ulint) == sizeof(void*));
/* If stacktrace is used we set up signal handler for SIGUSR2 signal
here. If signal handler set fails we report that and disable
@@ -2108,6 +2103,7 @@ innobase_start_or_create_for_mysql(void)
fsp_init();
log_init();
+ log_online_init();
lock_sys_create(srv_lock_table_size);
@@ -2282,14 +2278,18 @@ innobase_start_or_create_for_mysql(void)
dirnamelen, max_flushed_lsn,
logfile0);
+ if (err == DB_SUCCESS) {
+ err = create_log_files_rename(
+ logfilename,
+ dirnamelen,
+ max_flushed_lsn,
+ logfile0);
+ }
+
if (err != DB_SUCCESS) {
return(err);
}
- create_log_files_rename(
- logfilename, dirnamelen,
- max_flushed_lsn, logfile0);
-
/* Suppress the message about
crash recovery. */
max_flushed_lsn = min_flushed_lsn
@@ -2414,8 +2414,9 @@ files_checked:
trx_sys_create();
- if (create_new_db) {
+ bool srv_monitor_thread_started = false;
+ if (create_new_db) {
ut_a(!srv_read_only_mode);
init_log_online();
@@ -2459,8 +2460,12 @@ files_checked:
fil_flush_file_spaces(FIL_TABLESPACE);
- create_log_files_rename(logfilename, dirnamelen,
- max_flushed_lsn, logfile0);
+ err = create_log_files_rename(logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
} else {
/* Check if we support the max format that is stamped
@@ -2489,6 +2494,22 @@ files_checked:
and there must be no page in the buf_flush list. */
buf_pool_invalidate();
+ /* Start monitor thread early enough so that e.g. crash
+ recovery failing to find free pages in the buffer pool is
+ diagnosed. */
+ if (!srv_read_only_mode)
+ {
+ /* Create the thread which prints InnoDB monitor
+ info */
+ thread_handles[4 + SRV_MAX_N_IO_THREADS] =
+ os_thread_create(
+ srv_monitor_thread,
+ NULL,
+ thread_ids + 4 + SRV_MAX_N_IO_THREADS);
+
+ thread_started[4 + SRV_MAX_N_IO_THREADS] = true;
+ }
+
/* We always try to do a recovery, even if the database had
been shut down normally: this is the normal startup path */
@@ -2497,25 +2518,92 @@ files_checked:
min_flushed_lsn, max_flushed_lsn);
if (err != DB_SUCCESS) {
-
- return(DB_ERROR);
+ return(err);
}
init_log_online();
- /* Since the insert buffer init is in dict_boot, and the
- insert buffer is needed in any disk i/o, first we call
- dict_boot(). Note that trx_sys_init_at_db_start() only needs
- to access space 0, and the insert buffer at this stage already
- works for space 0. */
-
+ /* Initialize the change buffer. */
err = dict_boot();
if (err != DB_SUCCESS) {
return(err);
}
+ if (!srv_read_only_mode) {
+ if (sum_of_new_sizes > 0) {
+ /* New data file(s) were added */
+ mtr_start(&mtr);
+ fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
+ mtr_commit(&mtr);
+ /* Immediately write the log record about
+ increased tablespace size to disk, so that it
+ is durable even if mysqld would crash
+ quickly */
+ log_buffer_flush_to_disk();
+ }
+ }
+
+ const ulint tablespace_size_in_header
+ = fsp_header_get_tablespace_size();
+
+#ifdef UNIV_DEBUG
+ /* buf_debug_prints = TRUE; */
+#endif /* UNIV_DEBUG */
+ ulint sum_of_data_file_sizes = 0;
+
+ for (ulint d = 0; d < srv_n_data_files; d++) {
+ sum_of_data_file_sizes += srv_data_file_sizes[d];
+ }
+
+ /* Compare the system tablespace file size to what is
+ stored in FSP_SIZE. In open_or_create_data_files()
+ we already checked that the file sizes match the
+ innodb_data_file_path specification. */
+ if (srv_read_only_mode
+ || sum_of_data_file_sizes == tablespace_size_in_header) {
+ /* Do not complain about the size. */
+ } else if (!srv_auto_extend_last_data_file
+ || sum_of_data_file_sizes
+ < tablespace_size_in_header) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tablespace size stored in header is " ULINTPF
+ " pages, but the sum of data file sizes is "
+ ULINTPF " pages",
+ tablespace_size_in_header,
+ sum_of_data_file_sizes);
+
+ if (srv_force_recovery == 0
+ && sum_of_data_file_sizes
+ < tablespace_size_in_header) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Cannot start InnoDB. The tail of"
+ " the system tablespace is"
+ " missing. Have you edited"
+ " innodb_data_file_path in my.cnf"
+ " in an inappropriate way, removing"
+ " data files from there?"
+ " You can set innodb_force_recovery=1"
+ " in my.cnf to force"
+ " a startup if you are trying to"
+ " recover a badly corrupt database.");
+
+ return(DB_ERROR);
+ }
+ }
+
+ /* This must precede recv_apply_hashed_log_recs(TRUE). */
ib_bh = trx_sys_init_at_db_start();
+
+ if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
+ /* Apply the hashed log records to the
+ respective file pages, for the last batch of
+ recv_group_scan_log_recs(). */
+
+ recv_apply_hashed_log_recs(TRUE);
+ DBUG_PRINT("ib_log", ("apply completed"));
+ }
+
n_recovered_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list);
/* The purge system needs to create the purge view and
@@ -2584,7 +2672,8 @@ files_checked:
ULINT_MAX, LSN_MAX, NULL);
ut_a(success);
- RECOVERY_CRASH(1);
+ DBUG_EXECUTE_IF("innodb_log_abort_1",
+ return(DB_ERROR););
min_flushed_lsn = max_flushed_lsn = log_get_lsn();
@@ -2599,8 +2688,6 @@ files_checked:
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
- RECOVERY_CRASH(2);
-
/* Flush the old log files. */
log_buffer_flush_to_disk();
/* If innodb_flush_method=O_DSYNC,
@@ -2615,21 +2702,27 @@ files_checked:
ut_d(recv_no_log_write = TRUE);
ut_ad(!buf_pool_check_no_pending_io());
- RECOVERY_CRASH(3);
+ DBUG_EXECUTE_IF("innodb_log_abort_3",
+ return(DB_ERROR););
/* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files(
max_flushed_lsn, 0);
- fil_flush_file_spaces(FIL_TABLESPACE);
+ DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
- RECOVERY_CRASH(4);
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
+
+ fil_flush_file_spaces(FIL_TABLESPACE);
/* Close and free the redo log files, so that
we can replace them. */
fil_close_log_files(true);
- RECOVERY_CRASH(5);
+ DBUG_EXECUTE_IF("innodb_log_abort_5",
+ return(DB_ERROR););
/* Free the old log file space. */
log_group_close_all();
@@ -2653,8 +2746,11 @@ files_checked:
fil_write_flushed_lsn_to_data_files(min_flushed_lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE);
- create_log_files_rename(logfilename, dirnamelen,
- log_get_lsn(), logfile0);
+ err = create_log_files_rename(logfilename, dirnamelen,
+ log_get_lsn(), logfile0);
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
}
srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -2668,20 +2764,8 @@ files_checked:
trx_sys_file_format_tag_init();
}
- if (!create_new_db && sum_of_new_sizes > 0) {
- /* New data file(s) were added */
- mtr_start(&mtr);
-
- fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
-
- mtr_commit(&mtr);
-
- /* Immediately write the log record about increased tablespace
- size to disk, so that it is durable even if mysqld would crash
- quickly */
-
- log_buffer_flush_to_disk();
- }
+ ut_ad(err == DB_SUCCESS);
+ ut_a(sum_of_new_sizes != ULINT_UNDEFINED);
#ifdef UNIV_LOG_ARCHIVE
if (!srv_read_only_mode) {
@@ -2760,10 +2844,13 @@ files_checked:
thread_started[3 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which prints InnoDB monitor info */
- thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
- srv_monitor_thread,
- NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
- thread_started[4 + SRV_MAX_N_IO_THREADS] = true;
+ if (!thread_started[4 + SRV_MAX_N_IO_THREADS]) {
+ /* srv_monitor_thread not yet started */
+ thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
+ srv_monitor_thread,
+ NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
+ thread_started[4 + SRV_MAX_N_IO_THREADS] = true;
+ }
}
/* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
@@ -2830,125 +2917,6 @@ files_checked:
buf_flush_lru_manager_thread_handle = os_thread_create(buf_flush_lru_manager_thread, NULL, NULL);
buf_flush_lru_manager_thread_started = true;
-#ifdef UNIV_DEBUG
- /* buf_debug_prints = TRUE; */
-#endif /* UNIV_DEBUG */
- sum_of_data_file_sizes = 0;
-
- for (i = 0; i < srv_n_data_files; i++) {
- sum_of_data_file_sizes += srv_data_file_sizes[i];
- }
-
- tablespace_size_in_header = fsp_header_get_tablespace_size();
-
- if (!srv_read_only_mode
- && !srv_auto_extend_last_data_file
- && sum_of_data_file_sizes != tablespace_size_in_header) {
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: tablespace size"
- " stored in header is %lu pages, but\n",
- (ulong) tablespace_size_in_header);
- ut_print_timestamp(stderr);
- fprintf(stderr,
- "InnoDB: the sum of data file sizes is %lu pages\n",
- (ulong) sum_of_data_file_sizes);
-
- if (srv_force_recovery == 0
- && sum_of_data_file_sizes < tablespace_size_in_header) {
- /* This is a fatal error, the tail of a tablespace is
- missing */
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Cannot start InnoDB."
- " The tail of the system tablespace is\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: missing. Have you edited"
- " innodb_data_file_path in my.cnf in an\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: inappropriate way, removing"
- " ibdata files from there?\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: You can set innodb_force_recovery=1"
- " in my.cnf to force\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: a startup if you are trying"
- " to recover a badly corrupt database.\n");
-
- return(DB_ERROR);
- }
- }
-
- if (!srv_read_only_mode
- && srv_auto_extend_last_data_file
- && sum_of_data_file_sizes < tablespace_size_in_header) {
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: tablespace size stored in header"
- " is %lu pages, but\n",
- (ulong) tablespace_size_in_header);
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: the sum of data file sizes"
- " is only %lu pages\n",
- (ulong) sum_of_data_file_sizes);
-
- if (srv_force_recovery == 0) {
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Cannot start InnoDB. The tail of"
- " the system tablespace is\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: missing. Have you edited"
- " innodb_data_file_path in my.cnf in an\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: inappropriate way, removing"
- " ibdata files from there?\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: You can set innodb_force_recovery=1"
- " in my.cnf to force\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: a startup if you are trying to"
- " recover a badly corrupt database.\n");
-
- return(DB_ERROR);
- }
- }
-
- /* Check that os_fast_mutexes work as expected */
- os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex);
-
- if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: pthread_mutex_trylock returns"
- " an unexpected value on\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: success! Cannot continue.\n");
- exit(1);
- }
-
- os_fast_mutex_unlock(&srv_os_test_mutex);
-
- os_fast_mutex_lock(&srv_os_test_mutex);
-
- os_fast_mutex_unlock(&srv_os_test_mutex);
-
- os_fast_mutex_free(&srv_os_test_mutex);
-
if (!srv_file_per_table && srv_pass_corrupt_table) {
fprintf(stderr, "InnoDB: Warning:"
" The option innodb_file_per_table is disabled,"
@@ -3200,6 +3168,7 @@ innobase_shutdown_for_mysql(void)
btr_search_disable();
ibuf_close();
+ log_online_shutdown();
log_shutdown();
trx_sys_file_format_close();
trx_sys_close();