diff options
Diffstat (limited to 'innobase/srv/srv0start.c')
-rw-r--r-- | innobase/srv/srv0start.c | 519 |
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); |