时间:2021-07-01 10:21:17 帮助过:11人阅读
*/ err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances); //buf_pool_init 初始化 详见 fprintf(stderr," InnoDB: Completed initialization of buffer pool\n"); if (err != DB_SUCCESS) { fprintf(stderr," InnoDB: Fatal error: cannot allocate memory" " for the buffer pool\n"); return(DB_ERROR); } fsp_init(); log_init(); lock_sys_create(srv_lock_table_size); /* Create i/o-handler threads: */ for (i = 0; i < srv_n_file_io_threads; i++) { n[i] = i; os_thread_create(io_handler_thread, n + i, thread_ids + i); } if (srv_n_log_files * srv_log_file_size >= 262144) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: combined size of log files" " must be < 4 GB\n"); return(DB_ERROR); } sum_of_new_sizes = 0; if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: tablespace size must be" " at least 10 MB\n"); return(DB_ERROR); } err = open_or_create_data_files(&create_new_db, #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) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Could not open or create data files.\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: If you tried to add new data files," " and it failed here,\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: you should now edit innodb_data_file_path" " in my.cnf back\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: to what it was, and remove the" " new ibdata files InnoDB created\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: in this failed attempt. InnoDB only wrote" " those files full of\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: zeros, but did not yet use them in any way." " But be careful: do not\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: remove old data files" " which contain your precious data!\n"); return((int) err); } 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) { return((int) err); } if (log_file_created) { log_created = TRUE; } else { log_opened = TRUE; } if ((log_opened && create_new_db) || (log_opened && log_created)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: all log files must be" " created at the same time.\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: All log files must be" " created also in database creation.\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: If you want bigger or smaller" " log files, shut down the\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: database and make sure there" " were no errors in shutdown.\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Then delete the existing log files." " Edit the .cnf file\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: and start the database again.\n"); return(DB_ERROR); } } /* 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 (max_flushed_lsn != min_flushed_lsn #ifdef UNIV_LOG_ARCHIVE || max_arch_log_no != min_arch_log_no #endif /* UNIV_LOG_ARCHIVE */ ) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Cannot initialize created" " log files because\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: data files were not in sync" " with each other\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: or the data files are corrupt.\n"); return(DB_ERROR); } if (max_flushed_lsn < (ib_uint64_t) 1000) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Cannot initialize created" " log files because\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: data files are corrupt," " or new data files were\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: created when the database" " was started previous\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: time but the database" " was not shut down\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: normally after that.\n"); return(DB_ERROR); } mutex_enter(&(log_sys->mutex)); #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)); } trx_sys_file_format_init(); if (create_new_db) { mtr_start(&mtr); fsp_header_init(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); /* To maintain backward compatibility we create only the first rollback segment before the double write buffer. All the remaining rollback segments will be created later, after the double write buffer has been created. */ trx_sys_create(); dict_create(); srv_startup_is_before_trx_rollback_phase = FALSE; #ifdef UNIV_LOG_ARCHIVE } else if (srv_archive_recovery) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Starting archive" " recovery from a backup...\n"); err = recv_recovery_from_archive_start( min_flushed_lsn, srv_archive_recovery_limit_lsn, min_arch_log_no); if (err != DB_SUCCESS) { 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 system */ fsp_header_get_free_limit(); recv_recovery_from_archive_finish(); #endif /* UNIV_LOG_ARCHIVE */ } else { /* Check if we support the max format that is stamped on the system tablespace. Note: We are NOT allowed to make any modifications to the TRX_SYS_PAGE_NO page before recovery because this page also contains the max_trx_id etc. important system variables that are required for recovery. We need to ensure that we return the system to a state where normal recovery is guaranteed to work. We do this by invalidating the buffer cache, this will force the reread of the page and restoration to its last known consistent state, this is REQUIRED for the recovery process to work. */ err = trx_sys_file_format_max_check( srv_max_file_format_at_startup); if (err != DB_SUCCESS) { return(err); } /* Invalidate the buffer pool to ensure that we reread the page that we read above, during recovery. Note that this is not as heavy weight as it seems. At this point there will be only ONE page in the buf_LRU and there must be no page in the buf_flush list. */ buf_pool_invalidate(); /* We always try to do a recovery, even if the database had been shut down normally: this is the normal startup path */ err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT, IB_ULONGLONG_MAX, min_flushed_lsn, max_flushed_lsn); if (err != DB_SUCCESS) { return(DB_ERROR); } /* 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. */ dict_boot(); trx_sys_init_at_db_start(); /* Initialize the fsp free limit global variable in the log system */ fsp_header_get_free_limit(); /* recv_recovery_from_checkpoint_finish needs trx lists which are initialized in trx_sys_init_at_db_start(). */ recv_recovery_from_checkpoint_finish(); if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { /* The following call is necessary for the insert buffer to work with multiple tablespaces. We must know the mapping between space id‘s and .ibd file names. In a crash recovery, we 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(). In a normal startup, we create the space objects for every table in the InnoDB data dictionary that has an .ibd file. We also determine the maximum tablespace id used. */ dict_check_tablespaces_and_store_max_id( recv_needed_recovery); } srv_startup_is_before_trx_rollback_phase = FALSE; recv_recovery_rollback_active(); /* It is possible that file_format tag has never been set. In this case we initialize it to minimum value. Important to note that we can do it ONLY after we have finished the recovery process so that the image of TRX_SYS_PAGE_NO is not stale. */ 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(); } #ifdef UNIV_LOG_ARCHIVE /* Archiving is always off under MySQL */ if (!srv_log_archive_on) { ut_a(DB_SUCCESS == log_archive_noarchivelog()); } else { mutex_enter(&(log_sys->mutex)); start_archive = FALSE; if (log_sys->archiving_state == LOG_ARCH_OFF) { start_archive = TRUE; } mutex_exit(&(log_sys->mutex)); if (start_archive) { ut_a(DB_SUCCESS == log_archive_archivelog()); } } #endif /* UNIV_LOG_ARCHIVE */ /* fprintf(stderr, "Max allowed record size %lu\n", page_get_free_space_of_empty() / 2); */ if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ trx_sys_create_doublewrite_buf(); } /* Here the double write buffer has already been created and so any new rollback segments will be allocated after the double write buffer. The default segment should already exist. We create the new segments only if it‘s a new database or the database was shutdown cleanly. */ /* Note: When creating the extra rollback segments during an upgrade we violate the latching order, even if the change buffer is empty. We make an exception in sync0sync.c and check srv_is_being_started for that violation. It cannot create a deadlock because we are still running in single threaded mode essentially. Only the IO threads should be running at this stage. */ trx_sys_create_rsegs(TRX_SYS_N_RSEGS - 1); /* Create the thread which watches the timeouts for lock waits */ os_thread_create(&srv_lock_timeout_thread, NULL, 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); /* Create the thread which prints InnoDB monitor info */ os_thread_create(&srv_monitor_thread, NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); srv_is_being_started = FALSE; err = dict_create_or_check_foreign_constraint_tables(); if (err != DB_SUCCESS) { return((int)DB_ERROR); } /* 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)); /* Currently we allow only a single purge thread. */ ut_a(srv_n_purge_threads == 0 || srv_n_purge_threads == 1); /* If the user has requested a separate purge thread then start the purge thread. */ if (srv_n_purge_threads == 1) { os_thread_create(&srv_purge_thread, NULL, NULL); } /* Wait for the purge and master thread to startup. */ while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { if (srv_thread_has_reserved_slot(SRV_MASTER) == ULINT_UNDEFINED || (srv_n_purge_threads == 1 && srv_thread_has_reserved_slot(SRV_WORKER) == ULINT_UNDEFINED)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: " "Waiting for the background threads to " "start\n"); os_thread_sleep(1000000); } else { break; } } #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_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, "