summaryrefslogtreecommitdiff
path: root/innobase/srv/srv0start.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/srv/srv0start.c')
-rw-r--r--innobase/srv/srv0start.c519
1 files changed, 341 insertions, 178 deletions
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 3223854652f..74dd23e4252 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -30,6 +30,7 @@ Created 2/16/1996 Heikki Tuuri
#include "page0cur.h"
#include "trx0trx.h"
#include "dict0boot.h"
+#include "dict0load.h"
#include "trx0sys.h"
#include "dict0crea.h"
#include "btr0btr.h"
@@ -55,6 +56,13 @@ Created 2/16/1996 Heikki Tuuri
#include "srv0start.h"
#include "que0que.h"
+/* Log sequence number immediately after startup */
+dulint srv_start_lsn;
+/* Log sequence number at shutdown */
+dulint srv_shutdown_lsn;
+
+ibool srv_start_raw_disk_in_use = FALSE;
+
static ibool srv_start_has_been_called = FALSE;
ulint srv_sizeof_trx_t_in_ha_innodb_cc;
@@ -87,13 +95,6 @@ static char* srv_monitor_file_name;
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
#define SRV_MAX_N_PENDING_SYNC_IOS 100
-/* The following limit may be too big in some old operating systems:
-we may get an assertion failure in os0file.c */
-
-#define SRV_MAX_N_OPEN_FILES 500
-
-#define SRV_LOG_SPACE_FIRST_ID 1000000000
-
/*************************************************************************
Reads the data files and their sizes from a character string given in
the .cnf file. */
@@ -137,7 +138,8 @@ srv_parse_data_file_paths_and_sizes(
while ((*str != ':' && *str != '\0')
|| (*str == ':'
- && (*(str + 1) == '\\' || *(str + 1) == '/'))) {
+ && (*(str + 1) == '\\' || *(str + 1) == '/'
+ || *(str + 1) == ':'))) {
str++;
}
@@ -227,11 +229,15 @@ srv_parse_data_file_paths_and_sizes(
while (*str != '\0') {
path = str;
- /* Note that we must ignore the ':' in a Windows path */
+ /* Note that we must step over the ':' in a Windows path;
+ a Windows path normally looks like C:\ibdata\ibdata1:1G, but
+ a Windows raw partition may have a specification like
+ \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */
while ((*str != ':' && *str != '\0')
|| (*str == ':'
- && (*(str + 1) == '\\' || *(str + 1) == '/'))) {
+ && (*(str + 1) == '\\' || *(str + 1) == '/'
+ || *(str + 1) == ':'))) {
str++;
}
@@ -420,7 +426,7 @@ io_handler_thread(
os_thread_exit(NULL);
#ifndef __WIN__
- return(NULL);
+ return(NULL); /* Not reached */
#else
return(0);
#endif
@@ -438,7 +444,8 @@ Normalizes a directory path for Windows: converts slashes to backslashes. */
void
srv_normalize_path_for_win(
/*=======================*/
- char* str __attribute__((unused))) /* in/out: null-terminated character string */
+ char* str __attribute__((unused))) /* in/out: null-terminated
+ character string */
{
#ifdef __WIN__
for (; *str; str++) {
@@ -489,7 +496,7 @@ srv_calc_low32(
expressed in bytes */
ulint file_size) /* in: file size in database pages */
{
- return(0xFFFFFFFF & (file_size << UNIV_PAGE_SIZE_SHIFT));
+ return(0xFFFFFFFFUL & (file_size << UNIV_PAGE_SIZE_SHIFT));
}
/*************************************************************************
@@ -513,6 +520,8 @@ ulint
open_or_create_log_file(
/*====================*/
/* out: DB_SUCCESS or error code */
+ ibool create_new_db, /* in: TRUE if we should create a
+ new database */
ibool* log_file_created, /* out: TRUE if new log file
created */
ibool log_file_has_been_opened,/* in: TRUE if a log file has been
@@ -522,11 +531,12 @@ open_or_create_log_file(
ulint i) /* in: log file number in group */
{
ibool ret;
- ulint arch_space_id;
ulint size;
ulint size_high;
char name[10000];
+ UT_NOT_USED(create_new_db);
+
*log_file_created = FALSE;
srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
@@ -535,12 +545,12 @@ open_or_create_log_file(
ut_a(strlen(srv_log_group_home_dirs[k]) <
(sizeof name) - 10 - sizeof "ib_logfile");
- sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], "ib_logfile", i);
+ sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], "ib_logfile", (ulong) i);
files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL,
OS_LOG_FILE, &ret);
if (ret == FALSE) {
- if (os_file_get_last_error() != OS_FILE_ALREADY_EXISTS) {
+ if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS) {
fprintf(stderr,
"InnoDB: Error in creating or opening %s\n", name);
@@ -565,9 +575,9 @@ open_or_create_log_file(
fprintf(stderr,
"InnoDB: Error: log file %s is of different size %lu %lu bytes\n"
"InnoDB: than specified in the .cnf file %lu %lu bytes!\n",
- name, size_high, size,
- srv_calc_high32(srv_log_file_size),
- srv_calc_low32(srv_log_file_size));
+ name, (ulong) size_high, (ulong) size,
+ (ulong) srv_calc_high32(srv_log_file_size),
+ (ulong) srv_calc_low32(srv_log_file_size));
return(DB_ERROR);
}
@@ -585,7 +595,7 @@ open_or_create_log_file(
}
fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n",
- name, srv_log_file_size
+ name, (ulong) srv_log_file_size
>> (20 - UNIV_PAGE_SIZE_SHIFT));
fprintf(stderr,
@@ -617,24 +627,26 @@ open_or_create_log_file(
ut_a(fil_validate());
fil_node_create(name, srv_log_file_size,
- 2 * k + SRV_LOG_SPACE_FIRST_ID);
-
+ 2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
+#ifdef UNIV_LOG_ARCHIVE
/* If this is the first log group, create the file space object
- for archived logs */
+ for archived logs.
+ Under MySQL, no archiving ever done. */
if (k == 0 && i == 0) {
arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
- fil_space_create((char*) "arch_log_space", arch_space_id, FIL_LOG);
+ fil_space_create("arch_log_space", arch_space_id, FIL_LOG);
} else {
arch_space_id = ULINT_UNDEFINED;
}
-
+#endif /* UNIV_LOG_ARCHIVE */
if (i == 0) {
log_group_init(k, srv_n_log_files,
srv_log_file_size * UNIV_PAGE_SIZE,
2 * k + SRV_LOG_SPACE_FIRST_ID,
- arch_space_id);
+ SRV_LOG_SPACE_FIRST_ID + 1); /* dummy arch
+ space id */
}
return(DB_SUCCESS);
@@ -649,12 +661,14 @@ open_or_create_data_files(
/* out: DB_SUCCESS or error code */
ibool* create_new_db, /* out: TRUE if new database should be
created */
- dulint* min_flushed_lsn,/* out: min of flushed lsn values in data
- files */
+#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no,/* out: min of archived log numbers in data
files */
- dulint* max_flushed_lsn,/* out: */
ulint* max_arch_log_no,/* out: */
+#endif /* UNIV_LOG_ARCHIVE */
+ dulint* min_flushed_lsn,/* out: min of flushed lsn values in data
+ files */
+ dulint* max_flushed_lsn,/* out: */
ulint* sum_of_new_sizes)/* out: sum of sizes of the new files added */
{
ibool ret;
@@ -669,7 +683,7 @@ open_or_create_data_files(
if (srv_n_data_files >= 1000) {
fprintf(stderr, "InnoDB: can only have < 1000 data files\n"
"InnoDB: you have defined %lu\n",
- srv_n_data_files);
+ (ulong) srv_n_data_files);
return(DB_ERROR);
}
@@ -687,18 +701,32 @@ open_or_create_data_files(
< (sizeof name) - 1);
sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]);
- files[i] = os_file_create(name, OS_FILE_CREATE,
+ if (srv_data_file_is_raw_partition[i] == 0) {
+
+ /* First we try to create the file: if it already
+ exists, ret will get value FALSE */
+
+ files[i] = os_file_create(name, OS_FILE_CREATE,
OS_FILE_NORMAL, OS_DATA_FILE, &ret);
- if (srv_data_file_is_raw_partition[i] == SRV_NEW_RAW) {
+ if (ret == FALSE && os_file_get_last_error(FALSE) !=
+ OS_FILE_ALREADY_EXISTS) {
+ fprintf(stderr,
+ "InnoDB: Error in creating or opening %s\n",
+ name);
+
+ return(DB_ERROR);
+ }
+ } else if (srv_data_file_is_raw_partition[i] == SRV_NEW_RAW) {
/* The partition is opened, not created; then it is
written over */
+ srv_start_raw_disk_in_use = TRUE;
srv_created_new_raw = TRUE;
files[i] = os_file_create(
- name, OS_FILE_OPEN, OS_FILE_NORMAL,
- OS_DATA_FILE, &ret);
+ name, OS_FILE_OPEN_RAW, OS_FILE_NORMAL,
+ OS_DATA_FILE, &ret);
if (!ret) {
fprintf(stderr,
"InnoDB: Error in opening %s\n", name);
@@ -706,19 +734,15 @@ open_or_create_data_files(
return(DB_ERROR);
}
} else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
+ srv_start_raw_disk_in_use = TRUE;
+
ret = FALSE;
+ } else {
+ ut_a(0);
}
if (ret == FALSE) {
- if (srv_data_file_is_raw_partition[i] != SRV_OLD_RAW
- && os_file_get_last_error() !=
- OS_FILE_ALREADY_EXISTS) {
- fprintf(stderr,
- "InnoDB: Error in creating or opening %s\n",
- name);
-
- return(DB_ERROR);
- }
+ /* We open the data file */
if (one_created) {
fprintf(stderr,
@@ -729,71 +753,83 @@ open_or_create_data_files(
return(DB_ERROR);
}
- files[i] = os_file_create(
- name, OS_FILE_OPEN, OS_FILE_NORMAL,
- OS_DATA_FILE, &ret);
+ if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
+ files[i] = os_file_create(
+ name, OS_FILE_OPEN_RAW, OS_FILE_NORMAL,
+ OS_DATA_FILE, &ret);
+ } else {
+ files[i] = os_file_create(
+ name, OS_FILE_OPEN, OS_FILE_NORMAL,
+ OS_DATA_FILE, &ret);
+ }
+
if (!ret) {
fprintf(stderr,
"InnoDB: Error in opening %s\n", name);
- os_file_get_last_error();
+ os_file_get_last_error(TRUE);
return(DB_ERROR);
}
- if (srv_data_file_is_raw_partition[i] != SRV_OLD_RAW) {
-
- ret = os_file_get_size(files[i], &size,
- &size_high);
- ut_a(ret);
- /* Round size downward to megabytes */
+ if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
+
+ goto skip_size_check;
+ }
+
+ ret = os_file_get_size(files[i], &size, &size_high);
+ ut_a(ret);
+ /* Round size downward to megabytes */
- rounded_size_pages = (size / (1024 * 1024)
+ rounded_size_pages = (size / (1024 * 1024)
+ 4096 * size_high)
<< (20 - UNIV_PAGE_SIZE_SHIFT);
- if (i == srv_n_data_files - 1
+ if (i == srv_n_data_files - 1
&& srv_auto_extend_last_data_file) {
- if (srv_data_file_sizes[i] >
+ if (srv_data_file_sizes[i] >
rounded_size_pages
|| (srv_last_file_size_max > 0
&& srv_last_file_size_max <
rounded_size_pages)) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: auto-extending data file %s is of a different size\n"
"InnoDB: %lu pages (rounded down to MB) than specified in the .cnf file:\n"
"InnoDB: initial %lu pages, max %lu (relevant if non-zero) pages!\n",
- name, rounded_size_pages,
- srv_data_file_sizes[i], srv_last_file_size_max);
+ name, (ulong) rounded_size_pages,
+ (ulong) srv_data_file_sizes[i],
+ (ulong) srv_last_file_size_max);
- return(DB_ERROR);
- }
-
- srv_data_file_sizes[i] =
- rounded_size_pages;
+ return(DB_ERROR);
}
+
+ srv_data_file_sizes[i] = rounded_size_pages;
+ }
- if (rounded_size_pages
- != srv_data_file_sizes[i]) {
+ if (rounded_size_pages != srv_data_file_sizes[i]) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: data file %s is of a different size\n"
"InnoDB: %lu pages (rounded down to MB)\n"
"InnoDB: than specified in the .cnf file %lu pages!\n", name,
- rounded_size_pages,
- srv_data_file_sizes[i]);
+ (ulong) rounded_size_pages,
+ (ulong) srv_data_file_sizes[i]);
- return(DB_ERROR);
- }
+ return(DB_ERROR);
}
-
+skip_size_check:
fil_read_flushed_lsn_and_arch_log_no(files[i],
one_opened,
- min_flushed_lsn, min_arch_log_no,
- max_flushed_lsn, max_arch_log_no);
+#ifdef UNIV_LOG_ARCHIVE
+ min_arch_log_no, max_arch_log_no,
+#endif /* UNIV_LOG_ARCHIVE */
+ min_flushed_lsn, max_flushed_lsn);
one_opened = TRUE;
} else {
+ /* We created the data file and now write it full of
+ zeros */
+
one_created = TRUE;
if (i > 0) {
@@ -811,7 +847,7 @@ open_or_create_data_files(
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Setting file %s size to %lu MB\n",
- name, (srv_data_file_sizes[i]
+ name, (ulong) (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
fprintf(stderr,
@@ -841,7 +877,13 @@ open_or_create_data_files(
ut_a(fil_validate());
- fil_node_create(name, srv_data_file_sizes[i], 0);
+ if (srv_data_file_is_raw_partition[i]) {
+
+ fil_node_create(name, srv_data_file_sizes[i], 0, TRUE);
+ } else {
+ fil_node_create(name, srv_data_file_sizes[i], 0,
+ FALSE);
+ }
}
ios = 0;
@@ -862,23 +904,35 @@ innobase_start_or_create_for_mysql(void)
/*====================================*/
/* out: DB_SUCCESS or error code */
{
+ buf_pool_t* ret;
ibool create_new_db;
ibool log_file_created;
ibool log_created = FALSE;
ibool log_opened = FALSE;
dulint min_flushed_lsn;
dulint max_flushed_lsn;
+#ifdef UNIV_LOG_ARCHIVE
ulint min_arch_log_no;
ulint max_arch_log_no;
- ibool start_archive;
+#endif /* UNIV_LOG_ARCHIVE */
ulint sum_of_new_sizes;
ulint sum_of_data_file_sizes;
ulint tablespace_size_in_header;
ulint err;
ulint i;
- ulint k;
+ ibool srv_file_per_table_original_value = srv_file_per_table;
mtr_t mtr;
+ if (sizeof(ulint) != sizeof(void*)) {
+ fprintf(stderr,
+"InnoDB: Error: size of InnoDB's ulint is %lu, but size of void* is %lu.\n"
+"InnoDB: The sizes should be the same so that on a 64-bit platform you can\n"
+"InnoDB: allocate more than 4 GB of memory.",
+ (ulong)sizeof(ulint), (ulong)sizeof(void*));
+ }
+
+ srv_file_per_table = FALSE; /* system tables are created in tablespace
+ 0 */
#ifdef UNIV_DEBUG
fprintf(stderr,
"InnoDB: !!!!!!!!!!!!!! UNIV_DEBUG switched on !!!!!!!!!!!!!!!\n");
@@ -899,12 +953,17 @@ innobase_start_or_create_for_mysql(void)
"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n");
#endif
+#ifdef UNIV_SIMULATE_AWE
+ fprintf(stderr,
+"InnoDB: !!!!!!!!!!!!!! UNIV_SIMULATE_AWE switched on !!!!!!!!!!!!!!!!!\n");
+#endif
if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) {
fprintf(stderr,
"InnoDB: Error: trx_t size is %lu in ha_innodb.cc but %lu in srv0start.c\n"
"InnoDB: Check that pthread_mutex_t is defined in the same way in these\n"
"InnoDB: compilation modules. Cannot continue.\n",
- srv_sizeof_trx_t_in_ha_innodb_cc, (ulint)sizeof(trx_t));
+ (ulong) srv_sizeof_trx_t_in_ha_innodb_cc,
+ (ulong) sizeof(trx_t));
return(DB_ERROR);
}
@@ -929,6 +988,17 @@ innobase_start_or_create_for_mysql(void)
srv_startup_is_before_trx_rollback_phase = TRUE;
os_aio_use_native_aio = FALSE;
+#if !defined(__WIN2000__) && !defined(UNIV_SIMULATE_AWE)
+ if (srv_use_awe) {
+
+ fprintf(stderr,
+"InnoDB: Error: You have specified innodb_buffer_pool_awe_mem_mb\n"
+"InnoDB: in my.cnf, but AWE can only be used in Windows 2000 and later.\n");
+
+ return(DB_ERROR);
+ }
+#endif
+
#ifdef __WIN__
if (os_get_os_version() == OS_WIN95
|| os_get_os_version() == OS_WIN31
@@ -952,28 +1022,22 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"fdatasync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"O_DSYNC")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"O_DIRECT")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"littlesync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"nosync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
#else
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"normal")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
os_aio_use_native_aio = FALSE;
@@ -991,6 +1055,31 @@ innobase_start_or_create_for_mysql(void)
srv_file_flush_method_str);
return(DB_ERROR);
}
+
+ /* Set the maximum number of threads which can wait for a semaphore
+ inside InnoDB */
+#if defined(__WIN__) || defined(__NETWARE__)
+
+/* Create less event semaphores because Win 98/ME had difficulty creating
+40000 event semaphores.
+Comment from Novell, Inc.: also, these just take a lot of memory on
+NetWare. */
+ srv_max_n_threads = 1000;
+#else
+ if (srv_pool_size >= 8 * 1024) {
+ /* Here we still have srv_pool_size counted
+ in kilobytes, srv_boot converts the value to
+ pages; if buffer pool is less than 8 MB,
+ assume fewer threads. */
+ srv_max_n_threads = 10000;
+ } else {
+ srv_max_n_threads = 1000; /* saves several MB of memory,
+ especially in 64-bit
+ computers */
+ }
+#endif
+ /* Note that the call srv_boot() also changes the values of
+ srv_pool_size etc. to the units used by InnoDB internally */
/* Set the maximum number of threads which can wait for a semaphore
inside InnoDB */
@@ -1043,7 +1132,6 @@ NetWare. */
if (!os_aio_use_native_aio) {
/* In simulated aio we currently have use only for 4 threads */
-
srv_n_file_io_threads = 4;
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
@@ -1057,9 +1145,28 @@ NetWare. */
SRV_MAX_N_PENDING_SYNC_IOS);
}
- fil_init(SRV_MAX_N_OPEN_FILES);
+ fil_init(srv_max_n_open_files);
+
+ if (srv_use_awe) {
+ fprintf(stderr,
+"InnoDB: Using AWE: Memory window is %lu MB and AWE memory is %lu MB\n",
+ (ulong) (srv_awe_window_size / ((1024 * 1024) / UNIV_PAGE_SIZE)),
+ (ulong) (srv_pool_size / ((1024 * 1024) / UNIV_PAGE_SIZE)));
+
+ /* We must disable adaptive hash indexes because they do not
+ tolerate remapping of pages in AWE */
+
+ srv_use_adaptive_hash_indexes = FALSE;
+ ret = buf_pool_init(srv_pool_size, srv_pool_size,
+ srv_awe_window_size);
+ } else {
+ ret = buf_pool_init(srv_pool_size, srv_pool_size,
+ srv_pool_size);
+ }
- buf_pool_init(srv_pool_size, srv_pool_size);
+ if (ret == NULL) {
+ return(DB_ERROR);
+ }
fsp_init();
log_init();
@@ -1070,10 +1177,10 @@ NetWare. */
for (i = 0; i < srv_n_file_io_threads; i++) {
n[i] = i;
-
os_thread_create(io_handler_thread, n + i, thread_ids + i);
}
+#ifdef UNIV_LOG_ARCHIVE
if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
fprintf(stderr,
"InnoDB: Error: you must set the log group home dir in my.cnf the\n"
@@ -1081,9 +1188,9 @@ NetWare. */
return(DB_ERROR);
}
+#endif /* UNIV_LOG_ARCHIVE */
if (srv_n_log_files * srv_log_file_size >= 262144) {
-
fprintf(stderr,
"InnoDB: Error: combined size of log files must be < 4 GB\n");
@@ -1113,8 +1220,10 @@ NetWare. */
}
err = open_or_create_data_files(&create_new_db,
- &min_flushed_lsn, &min_arch_log_no,
- &max_flushed_lsn, &max_arch_log_no,
+#ifdef UNIV_LOG_ARCHIVE
+ &min_arch_log_no, &max_arch_log_no,
+#endif /* UNIV_LOG_ARCHIVE */
+ &min_flushed_lsn, &max_flushed_lsn,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
fprintf(stderr,
@@ -1129,41 +1238,27 @@ NetWare. */
return((int) err);
}
- if (!create_new_db) {
- /* If we are using the doublewrite method, we will
- check if there are half-written pages in data files,
- and restore them from the doublewrite buffer if
- possible */
-
- if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
-
- trx_sys_doublewrite_restore_corrupt_pages();
- }
- }
-
+#ifdef UNIV_LOG_ARCHIVE
srv_normalize_path_for_win(srv_arch_dir);
srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
+#endif /* UNIV_LOG_ARCHIVE */
+
+ for (i = 0; i < srv_n_log_files; i++) {
+ err = open_or_create_log_file(create_new_db, &log_file_created,
+ log_opened, 0, i);
+ if (err != DB_SUCCESS) {
- for (k = 0; k < srv_n_log_groups; k++) {
-
- for (i = 0; i < srv_n_log_files; i++) {
-
- err = open_or_create_log_file(&log_file_created,
- log_opened, k, i);
- if (err != DB_SUCCESS) {
-
- return((int) err);
- }
-
- if (log_file_created) {
- log_created = TRUE;
- } else {
- log_opened = TRUE;
- }
+ return((int) err);
+ }
- if ((log_opened && create_new_db)
+ if (log_file_created) {
+ log_created = TRUE;
+ } else {
+ log_opened = TRUE;
+ }
+ if ((log_opened && create_new_db)
|| (log_opened && log_created)) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: all log files must be created at the same time.\n"
"InnoDB: All log files must be created also in database creation.\n"
"InnoDB: If you want bigger or smaller log files, shut down the\n"
@@ -1171,16 +1266,25 @@ NetWare. */
"InnoDB: Then delete the existing log files. Edit the .cnf file\n"
"InnoDB: and start the database again.\n");
- return(DB_ERROR);
- }
-
+ return(DB_ERROR);
}
}
- if (log_created && !create_new_db && !srv_archive_recovery) {
+ /* Open all log files and data files in the system tablespace: we
+ keep them open until database shutdown */
+ fil_open_log_and_system_tablespace_files();
+
+ if (log_created && !create_new_db
+#ifdef UNIV_LOG_ARCHIVE
+ && !srv_archive_recovery
+#endif /* UNIV_LOG_ARCHIVE */
+ ) {
if (ut_dulint_cmp(max_flushed_lsn, min_flushed_lsn) != 0
- || max_arch_log_no != min_arch_log_no) {
+#ifdef UNIV_LOG_ARCHIVE
+ || max_arch_log_no != min_arch_log_no
+#endif /* UNIV_LOG_ARCHIVE */
+ ) {
fprintf(stderr,
"InnoDB: Cannot initialize created log files because\n"
"InnoDB: data files were not in sync with each other\n"
@@ -1203,8 +1307,14 @@ NetWare. */
mutex_enter(&(log_sys->mutex));
- recv_reset_logs(max_flushed_lsn, max_arch_log_no + 1, TRUE);
-
+#ifdef UNIV_LOG_ARCHIVE
+ /* Do not + 1 arch_log_no because we do not use log
+ archiving */
+ recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
+#else
+ recv_reset_logs(max_flushed_lsn, TRUE);
+#endif /* UNIV_LOG_ARCHIVE */
+
mutex_exit(&(log_sys->mutex));
}
@@ -1219,10 +1329,10 @@ NetWare. */
dict_create();
srv_startup_is_before_trx_rollback_phase = FALSE;
+#ifdef UNIV_LOG_ARCHIVE
} else if (srv_archive_recovery) {
fprintf(stderr,
"InnoDB: Starting archive recovery from a backup...\n");
-
err = recv_recovery_from_archive_start(
min_flushed_lsn,
srv_archive_recovery_limit_lsn,
@@ -1231,14 +1341,11 @@ NetWare. */
return(DB_ERROR);
}
-
/* Since ibuf init is in dict_boot, and ibuf is needed
in any disk i/o, first call dict_boot */
dict_boot();
-
trx_sys_init_at_db_start();
-
srv_startup_is_before_trx_rollback_phase = FALSE;
/* Initialize the fsp free limit global variable in the log
@@ -1246,9 +1353,10 @@ NetWare. */
fsp_header_get_free_limit(0);
recv_recovery_from_archive_finish();
+#endif /* UNIV_LOG_ARCHIVE */
} else {
/* We always try to do a recovery, even if the database had
- been shut down normally */
+ been shut down normally: this is the normal startup path */
err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT,
ut_dulint_max,
@@ -1294,6 +1402,8 @@ NetWare. */
log_make_checkpoint_at(ut_dulint_max, TRUE);
+#ifdef UNIV_LOG_ARCHIVE
+ /* Archiving is always off under MySQL */
if (!srv_log_archive_on) {
ut_a(DB_SUCCESS == log_archive_noarchivelog());
} else {
@@ -1311,6 +1421,14 @@ NetWare. */
ut_a(DB_SUCCESS == log_archive_archivelog());
}
}
+#endif /* UNIV_LOG_ARCHIVE */
+ if (!create_new_db && srv_force_recovery == 0) {
+ /* After a crash recovery we only check that the info in data
+ dictionary is consistent with what we already know about space
+ id's from the call of fil_load_single_table_tablespaces(). */
+
+ dict_check_tablespaces_or_store_max_id(recv_needed_recovery);
+ }
if (srv_measure_contention) {
/* os_thread_create(&test_measure_cont, NULL, thread_ids +
@@ -1324,17 +1442,28 @@ NetWare. */
and prints InnoDB monitor info */
os_thread_create(&srv_lock_timeout_and_monitor_thread, NULL,
- thread_ids + 2 + SRV_MAX_N_IO_THREADS);
+ thread_ids + 2 + SRV_MAX_N_IO_THREADS);
/* Create the thread which warns of long semaphore waits */
os_thread_create(&srv_error_monitor_thread, NULL,
- thread_ids + 3 + SRV_MAX_N_IO_THREADS);
+ thread_ids + 3 + SRV_MAX_N_IO_THREADS);
srv_was_started = TRUE;
srv_is_being_started = FALSE;
+#ifdef UNIV_DEBUG
+ /* Wait a while so that the created threads have time to suspend
+ themselves before we switch sync debugging on; otherwise a thread may
+ execute mutex_enter() before the checks are on, and mutex_exit() after
+ the checks are on, which will cause an assertion failure in sync
+ debug. */
+
+ os_thread_sleep(3000000);
+#endif
sync_order_checks_on = TRUE;
- if (srv_use_doublewrite_buf && trx_doublewrite == NULL) {
+ if (srv_use_doublewrite_buf && trx_doublewrite == NULL) {
+ /* Create the doublewrite buffer to a new tablespace */
+
trx_sys_create_doublewrite_buf();
}
@@ -1344,8 +1473,8 @@ NetWare. */
return((int)DB_ERROR);
}
- /* Create the master thread which monitors the database
- server, and does purge and other utility operations */
+ /* Create the master thread which does purge and other utility
+ operations */
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
SRV_MAX_N_IO_THREADS);
@@ -1365,7 +1494,8 @@ NetWare. */
fprintf(stderr,
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
"InnoDB: the sum of data file sizes is %lu pages\n",
- tablespace_size_in_header, sum_of_data_file_sizes);
+ (ulong) tablespace_size_in_header,
+ (ulong) sum_of_data_file_sizes);
}
if (srv_auto_extend_last_data_file
@@ -1374,10 +1504,11 @@ NetWare. */
fprintf(stderr,
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
"InnoDB: the sum of data file sizes is only %lu pages\n",
- tablespace_size_in_header, sum_of_data_file_sizes);
+ (ulong) tablespace_size_in_header,
+ (ulong) sum_of_data_file_sizes);
}
- /* Check that os_fast_mutexes work as exptected */
+ /* Check that os_fast_mutexes work as expected */
os_fast_mutex_init(&srv_os_test_mutex);
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
@@ -1395,43 +1526,73 @@ NetWare. */
os_fast_mutex_free(&srv_os_test_mutex);
- /***********************************************************/
- /* Do NOT merge to the 4.1 code base! */
- if (trx_sys_downgrading_from_4_1_1) {
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Started; log sequence number %lu %lu\n",
+ (ulong) ut_dulint_get_high(srv_start_lsn),
+ (ulong) ut_dulint_get_low(srv_start_lsn));
+ }
+
+ if (srv_force_recovery > 0) {
+ fprintf(stderr,
+ "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
+ (ulong) srv_force_recovery);
+ }
+
+ fflush(stderr);
+
+ if (trx_doublewrite_must_reset_space_ids) {
+ /* Actually, we did not change the undo log format between
+ 4.0 and 4.1.1, and we would not need to run purge to
+ completion. Note also that the purge algorithm in 4.1.1
+ can process the the history list again even after a full
+ purge, because our algorithm does not cut the end of the
+ history list in all cases so that it would become empty
+ after a full purge. That mean that we may purge 4.0 type
+ undo log even after this phase.
+
+ The insert buffer record format changed between 4.0 and
+ 4.1.1. It is essential that the insert buffer is emptied
+ here! */
+
fprintf(stderr,
-"InnoDB: You are downgrading from an InnoDB version which allows multiple\n"
+"InnoDB: You are upgrading to an InnoDB version which allows multiple\n"
"InnoDB: tablespaces. Wait that purge and insert buffer merge run to\n"
"InnoDB: completion...\n");
for (;;) {
- os_thread_sleep(10000000);
+ os_thread_sleep(1000000);
if (0 == strcmp(srv_main_thread_op_info,
"waiting for server activity")) {
+
+ ut_a(ibuf_is_empty());
+
break;
}
}
fprintf(stderr,
"InnoDB: Full purge and insert buffer merge completed.\n");
- trx_sys_mark_downgraded_from_4_1_1();
+ trx_sys_mark_upgraded_to_multiple_tablespaces();
fprintf(stderr,
-"InnoDB: Downgraded from >= 4.1.1 to 4.0\n");
+"InnoDB: You have now successfully upgraded to the multiple tablespaces\n"
+"InnoDB: format. You should NOT DOWNGRADE again to an earlier version of\n"
+"InnoDB: InnoDB! But if you absolutely need to downgrade, see section 4.6 of\n"
+"InnoDB: http://www.innodb.com/ibman.php for instructions.\n");
}
- /***********************************************************/
- if (srv_print_verbose_log) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Started\n");
- }
+ if (srv_force_recovery == 0) {
+ /* In the insert buffer we may have even bigger tablespace
+ id's, because we may have dropped those tablespaces, but
+ insert buffer merge has not had time to clean the records from
+ the ibuf tree. */
- if (srv_force_recovery > 0) {
- fprintf(stderr,
- "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
- srv_force_recovery);
+ ibuf_update_max_tablespace_id();
}
- fflush(stderr);
+ srv_file_per_table = srv_file_per_table_original_value;
return((int) DB_SUCCESS);
}
@@ -1450,17 +1611,16 @@ innobase_shutdown_for_mysql(void)
if (srv_is_being_started) {
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: Warning: shutting down a not properly started\n");
- fprintf(stderr,
- " InnoDB: or created database!\n");
+" InnoDB: Warning: shutting down a not properly started\n"
+" InnoDB: or created database!\n");
}
return(DB_SUCCESS);
}
- /* 1. Flush buffer pool to disk, write the current lsn to
+ /* 1. Flush the buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive.
- The step 1 is the real InnoDB shutdown. The remaining steps
+ The step 1 is the real InnoDB shutdown. The remaining steps 2 - ...
just free data structures after the shutdown. */
logs_empty_and_mark_files_at_shutdown();
@@ -1484,16 +1644,16 @@ innobase_shutdown_for_mysql(void)
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
HERE OR EARLIER */
- /* 1. Let the lock timeout thread exit */
+ /* a. Let the lock timeout thread exit */
os_event_set(srv_lock_timeout_thread_event);
- /* 2. srv error monitor thread exits automatically, no need
+ /* b. srv error monitor thread exits automatically, no need
to do anything here */
- /* 3. We wake the master thread so that it exits */
+ /* c. We wake the master thread so that it exits */
srv_wake_master_thread();
- /* 4. Exit the i/o threads */
+ /* d. Exit the i/o threads */
os_aio_wake_all_threads_at_shutdown();
@@ -1521,7 +1681,7 @@ innobase_shutdown_for_mysql(void)
if (i == 1000) {
fprintf(stderr,
"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n",
- os_thread_count);
+ (ulong) os_thread_count);
}
if (srv_monitor_file) {
@@ -1555,8 +1715,8 @@ innobase_shutdown_for_mysql(void)
fprintf(stderr,
"InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
- os_thread_count, os_event_count, os_mutex_count,
- os_fast_mutex_count);
+ (ulong) os_thread_count, (ulong) os_event_count,
+ (ulong) os_mutex_count, (ulong) os_fast_mutex_count);
}
if (dict_foreign_err_file) {
@@ -1568,7 +1728,10 @@ innobase_shutdown_for_mysql(void)
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Shutdown completed\n");
+ fprintf(stderr,
+" InnoDB: Shutdown completed; log sequence number %lu %lu\n",
+ (ulong) ut_dulint_get_high(srv_shutdown_lsn),
+ (ulong) ut_dulint_get_low(srv_shutdown_lsn));
}
return((int) DB_SUCCESS);