diff options
author | heikki@hundin.mysql.fi <> | 2003-10-07 17:28:59 +0300 |
---|---|---|
committer | heikki@hundin.mysql.fi <> | 2003-10-07 17:28:59 +0300 |
commit | 6112853cdab2770e92f9cfefdfef9c0a14b71cb7 (patch) | |
tree | d53a5cc4e9736e149276ba08d53a7dd09a14b4fd /innobase/srv/srv0start.c | |
parent | 862ff0ed1c1dad812af60987d7ec1a2706d3772c (diff) | |
download | mariadb-git-6112853cdab2770e92f9cfefdfef9c0a14b71cb7.tar.gz |
Many files:
Multiple tablespaces for InnoDB
sql_table.cc:
Tell explicitly that InnoDB should retrieve all columns in CHECKSUM TABLE
sql_update.cc, sql_select.cc, my_base.h:
More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS
Diffstat (limited to 'innobase/srv/srv0start.c')
-rw-r--r-- | innobase/srv/srv0start.c | 311 |
1 files changed, 194 insertions, 117 deletions
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index f0ff1167f4d..5de87038bde 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" @@ -56,6 +57,14 @@ 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; + ibool srv_start_has_been_called = FALSE; ulint srv_sizeof_trx_t_in_ha_innodb_cc; @@ -87,13 +96,6 @@ ibool srv_os_test_mutex_is_locked = FALSE; #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 +139,8 @@ srv_parse_data_file_paths_and_sizes( while ((*str != ':' && *str != '\0') || (*str == ':' - && (*(str + 1) == '\\' || *(str + 1) == '/'))) { + && (*(str + 1) == '\\' || *(str + 1) == '/' + || *(str + 1) == ':'))) { str++; } @@ -234,11 +237,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++; } @@ -452,7 +459,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__ ulint i; @@ -510,7 +518,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)); } /************************************************************************* @@ -563,7 +571,7 @@ open_or_create_log_file( 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); @@ -640,7 +648,7 @@ 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); /* If this is the first log group, create the file space object for archived logs */ @@ -648,7 +656,8 @@ open_or_create_log_file( 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((char*) "arch_log_space", arch_space_id, + FIL_LOG); } else { arch_space_id = ULINT_UNDEFINED; } @@ -708,18 +717,32 @@ open_or_create_data_files( 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); @@ -727,19 +750,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, @@ -750,71 +769,80 @@ 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); - 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]); - 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); one_opened = TRUE; } else { + /* We created the data file and now write it full of + zeros */ + one_created = TRUE; if (i > 0) { @@ -862,7 +890,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; @@ -972,9 +1006,11 @@ innobase_start_or_create_for_mysql(void) 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; + srv_file_per_table = FALSE; /* system tables are created in tablespace + 0 */ #ifdef UNIV_DEBUG fprintf(stderr, "InnoDB: !!!!!!!!!!!!!! UNIV_DEBUG switched on !!!!!!!!!!!!!!!\n"); @@ -999,7 +1035,6 @@ innobase_start_or_create_for_mysql(void) 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" @@ -1122,7 +1157,6 @@ innobase_start_or_create_for_mysql(void) 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 @@ -1136,7 +1170,7 @@ innobase_start_or_create_for_mysql(void) 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, @@ -1168,7 +1202,6 @@ innobase_start_or_create_for_mysql(void) for (i = 0; i < srv_n_file_io_threads; i++) { n[i] = i; - os_thread_create(io_handler_thread, n + i, thread_ids + i); } @@ -1181,7 +1214,6 @@ innobase_start_or_create_for_mysql(void) } if (srv_n_log_files * srv_log_file_size >= 262144) { - fprintf(stderr, "InnoDB: Error: combined size of log files must be < 4 GB\n"); @@ -1227,42 +1259,25 @@ innobase_start_or_create_for_mysql(void) 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(); - } - } - srv_normalize_path_for_win(srv_arch_dir); srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir); + + 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(create_new_db, - &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" @@ -1270,14 +1285,16 @@ innobase_start_or_create_for_mysql(void) "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 && !srv_archive_recovery) { if (ut_dulint_cmp(max_flushed_lsn, min_flushed_lsn) != 0 || max_arch_log_no != min_arch_log_no) { fprintf(stderr, @@ -1323,7 +1340,6 @@ innobase_start_or_create_for_mysql(void) } 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, @@ -1332,14 +1348,11 @@ innobase_start_or_create_for_mysql(void) 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 @@ -1349,7 +1362,7 @@ innobase_start_or_create_for_mysql(void) recv_recovery_from_archive_finish(); } 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, @@ -1413,6 +1426,14 @@ innobase_start_or_create_for_mysql(void) } } + 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 + SRV_MAX_N_IO_THREADS); */ @@ -1425,17 +1446,27 @@ innobase_start_or_create_for_mysql(void) 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 creates 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. */ + + os_thread_sleep(2000000); +#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(); } @@ -1445,8 +1476,8 @@ innobase_start_or_create_for_mysql(void) 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); @@ -1478,7 +1509,7 @@ innobase_start_or_create_for_mysql(void) tablespace_size_in_header, 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)) { @@ -1498,7 +1529,10 @@ innobase_start_or_create_for_mysql(void) if (srv_print_verbose_log) { ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Started\n"); + fprintf(stderr, +" InnoDB: Started; log sequence number %lu %lu\n", + ut_dulint_get_high(srv_start_lsn), + ut_dulint_get_low(srv_start_lsn)); } if (srv_force_recovery > 0) { @@ -1509,6 +1543,47 @@ innobase_start_or_create_for_mysql(void) fflush(stderr); + if (trx_doublewrite_must_reset_space_ids) { + fprintf(stderr, +"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(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_upgraded_to_multiple_tablespaces(); + + fprintf(stderr, +"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!\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. */ + + ibuf_update_max_tablespace_id(); + } + + srv_file_per_table = srv_file_per_table_original_value; + + fprintf(stderr, +"TODO: make sure MySQL sets field->query_id right in prepare/execute\n"); + return((int) DB_SUCCESS); } @@ -1526,17 +1601,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(); @@ -1560,16 +1634,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(); @@ -1628,7 +1702,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", + ut_dulint_get_high(srv_shutdown_lsn), + ut_dulint_get_low(srv_shutdown_lsn)); } return((int) DB_SUCCESS); |