diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index 7763aa99322..ceb01ac4807 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -1,7 +1,7 @@ # # MDEV-32242 innodb.doublewrite test case always is skipped # -create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb; start transaction; insert into t1 values(1, repeat('#',12)); insert into t1 values(2, repeat('+',12)); @@ -19,6 +19,7 @@ XA PREPARE 'x'; disconnect dml; connection default; flush table t1 for export; +# Kill the server # restart FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err FOUND 1 /InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]/ in mysqld.1.err @@ -33,5 +34,27 @@ f1 f2 3 //////////// 4 ------------ 5 ............ +connect dml,localhost,root,,; +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; +flush table t1 for export; +# Kill the server +# restart +FOUND 2 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err +XA ROLLBACK 'x'; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select f1, f2 from t1; +f1 f2 +1 ############ +2 ++++++++++++ +3 //////////// +4 ------------ +5 ............ drop table t1; # End of 10.5 tests diff --git a/mysql-test/suite/innodb/r/log_file_name.result b/mysql-test/suite/innodb/r/log_file_name.result index 42b988ed3ca..3d48a24d217 100644 --- a/mysql-test/suite/innodb/r/log_file_name.result +++ b/mysql-test/suite/innodb/r/log_file_name.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); SET GLOBAL innodb_file_per_table=ON; FLUSH TABLES; CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; @@ -89,7 +90,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages/ in mysqld.1.err NOT FOUND /\[Note\] InnoDB: Cannot read first page of .*u2.ibd/ in mysqld.1.err # Fault 7: Missing or wrong data file and innodb_force_recovery @@ -98,11 +99,11 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ from '.*u4.ibd' to '.*u6.ibd' because the target file exists/ in mysqld.1.err # restart: --innodb-force-recovery=1 -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[Warning\] InnoDB: Tablespace \d+ was not found at .*u[1-5].ibd, and innodb_force_recovery was set. All redo log for this tablespace will be ignored!/ in mysqld.1.err # restart diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 89e6577b434..541e4d23a19 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -17,6 +17,7 @@ call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions"); +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; @@ -24,7 +25,7 @@ let MYSQLD_DATADIR=`select @@datadir`; let ALGO=`select @@innodb_checksum_algorithm`; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb; start transaction; insert into t1 values(1, repeat('#',12)); @@ -38,7 +39,7 @@ commit work; SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; --source include/restart_mysqld.inc - +--source ../include/no_checkpoint_start.inc connect (dml,localhost,root,,); XA START 'x'; insert into t1 values (6, repeat('%', @@innodb_page_size/2)); @@ -50,8 +51,8 @@ connection default; flush table t1 for export; let $restart_parameters=; -let $shutdown_timeout=0; ---source include/shutdown_mysqld.inc +--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint; +--source ../include/no_checkpoint_end.inc perl; use IO::Handle; @@ -119,6 +120,35 @@ let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page num XA ROLLBACK 'x'; check table t1; select f1, f2 from t1; + +--source ../include/no_checkpoint_start.inc +connect (dml,localhost,root,,); +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; + +flush table t1 for export; + +let $restart_parameters=; +--source ../include/no_checkpoint_end.inc + +# Zero out the first page in file and try to recover from dblwr +perl; +use IO::Handle; +open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/t1.ibd") or die; +syswrite(FILE, chr(0) x $ENV{INNODB_PAGE_SIZE}); +close FILE; +EOF + +--source include/start_mysqld.inc +let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile; +--source include/search_pattern_in_file.inc +XA ROLLBACK 'x'; +check table t1; +select f1, f2 from t1; drop table t1; --echo # End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test index 1bff8b4e07f..3d96a74e698 100644 --- a/mysql-test/suite/innodb/t/doublewrite_debug.test +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -17,6 +17,7 @@ call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registra call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index 11eca0a7a12..494d256cd11 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -7,6 +7,8 @@ # Embedded server does not support crashing --source include/not_embedded.inc +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); + SET GLOBAL innodb_file_per_table=ON; FLUSH TABLES; @@ -172,6 +174,7 @@ call mtr.add_suppression("InnoDB: Table test/u[123] in the InnoDB data dictionar call mtr.add_suppression("InnoDB: Cannot replay rename of tablespace.*"); call mtr.add_suppression("InnoDB: Attempted to open a previously opened tablespace"); call mtr.add_suppression("InnoDB: Recovery cannot access file"); +call mtr.add_suppression("InnoDB: Cannot read first page in datafile:"); FLUSH TABLES; --enable_query_log @@ -215,7 +218,7 @@ EOF --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= \[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages; @@ -240,7 +243,7 @@ let SEARCH_PATTERN= \[Note\] InnoDB: Cannot read first page of .*u2.ibd; --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; @@ -253,7 +256,7 @@ let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ fro --source include/restart_mysqld.inc -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 57ec3553b8d..d5c954dff89 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -324,11 +324,14 @@ func_exit: os_file_flush(file); } else - for (ulint i= 0; i < size * 2; i++, page += srv_page_size) - if (mach_read_from_8(my_assume_aligned<8>(page + FIL_PAGE_LSN))) - /* Each valid page header must contain a nonzero FIL_PAGE_LSN field. */ + { + alignas(8) char checkpoint[8]; + mach_write_to_8(checkpoint, log_sys.next_checkpoint_lsn); + for (auto i= size * 2; i--; page += srv_page_size) + if (memcmp_aligned<8>(page + FIL_PAGE_LSN, checkpoint, 8) >= 0) + /* Valid pages are not older than the log checkpoint. */ recv_sys.dblwr.add(page); - + } err= DB_SUCCESS; goto func_exit; } diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index f0ead3b80a3..653c848953a 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -475,9 +475,16 @@ Datafile::validate_for_recovery() err = find_space_id(); if (err != DB_SUCCESS || m_space_id == 0) { - ib::error() << "Datafile '" << m_filepath << "' is" - " corrupted. Cannot determine the space ID from" - " the first 64 pages."; + + m_space_id = recv_sys.dblwr.find_first_page( + m_filepath, m_handle); + + if (m_space_id) goto free_first_page; + + sql_print_error( + "InnoDB: Datafile '%s' is corrupted." + " Cannot determine the space ID from" + " the first 64 pages.", m_filepath); return(err); } @@ -485,7 +492,7 @@ Datafile::validate_for_recovery() m_space_id, m_filepath, m_handle)) { return(DB_CORRUPTION); } - +free_first_page: /* Free the previously read first page and then re-validate. */ free_first_page(); err = validate_first_page(0); @@ -531,9 +538,9 @@ Datafile::validate_first_page(lsn_t* flush_lsn) if (error_txt != NULL) { err_exit: - ib::info() << error_txt << " in datafile: " << m_filepath - << ", Space ID:" << m_space_id << ", Flags: " - << m_flags; + sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, " + "Flags: %zu", error_txt, m_filepath, + m_space_id, m_flags); m_is_valid = false; free_first_page(); return(DB_CORRUPTION); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index a7bb417c502..eb6e8d1166e 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -574,7 +574,7 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) } err = it->read_first_page( - m_ignore_read_only ? false : srv_read_only_mode); + m_ignore_read_only && srv_read_only_mode); if (err != DB_SUCCESS) { return(err); @@ -588,20 +588,17 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) /* Check the contents of the first page of the first datafile. */ - for (int retry = 0; retry < 2; ++retry) { + err = it->validate_first_page(flushed_lsn); - err = it->validate_first_page(flushed_lsn); - - if (err != DB_SUCCESS - && (retry == 1 - || recv_sys.dblwr.restore_first_page( + if (err != DB_SUCCESS) { + if (recv_sys.dblwr.restore_first_page( it->m_space_id, it->m_filepath, - it->handle()))) { - + it->handle())) { it->close(); - return(err); } + err = it->read_first_page( + m_ignore_read_only && srv_read_only_mode); } /* Make sure the tablespace space ID matches the diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h index f82baeec89a..99a41d069ef 100644 --- a/storage/innobase/include/buf0dblwr.h +++ b/storage/innobase/include/buf0dblwr.h @@ -103,7 +103,8 @@ public: If we are upgrading from a version before MySQL 4.1, then this function performs the necessary update operations to support innodb_file_per_table. If we are in a crash recovery, this function - loads the pages from double write buffer into memory. + loads the pages from double write buffer which are not older than + the checkpoint into memory. @param file File handle @param path Path name of file @return DB_SUCCESS or error code */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 34211392ba3..aca9f994acb 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -49,6 +49,11 @@ recv_find_max_checkpoint(ulint* max_field) ATTRIBUTE_COLD void recv_recover_page(fil_space_t* space, buf_page_t* bpage) MY_ATTRIBUTE((nonnull)); +/** Read the latest checkpoint information from log file +and store it in log_sys.next_checkpoint and recv_sys.mlog_checkpoint_lsn +@return error code or DB_SUCCESS */ +dberr_t recv_recovery_read_max_checkpoint(); + /** Start recovering from a redo log checkpoint. @param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN of first system tablespace page @@ -141,7 +146,18 @@ struct recv_dblwr_t @param file tablespace file handle @return whether the operation failed */ bool restore_first_page( - ulint space_id, const char *name, os_file_t file); + ulint space_id, const char *name, pfs_os_file_t file); + + /** Restore the first page of the given tablespace from + doublewrite buffer. + 1) Find the page which has page_no as 0 + 2) Read first 3 pages from tablespace file + 3) Compare the space_ids from the pages with page0 which + was retrieved from doublewrite buffer + @param name tablespace filepath + @param file tablespace file handle + @return space_id or 0 in case of error */ + uint32_t find_first_page(const char *name, pfs_os_file_t file); typedef std::deque > list; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 05120871b0a..52649419ec7 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3415,6 +3415,46 @@ recv_init_crash_recovery_spaces(bool rescan, bool& missing_tablespace) return DB_SUCCESS; } +dberr_t recv_recovery_read_max_checkpoint() +{ + ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED || + srv_operation == SRV_OPERATION_RESTORE || + srv_operation == SRV_OPERATION_RESTORE_EXPORT); + ut_d(mysql_mutex_lock(&buf_pool.mutex)); + ut_ad(UT_LIST_GET_LEN(buf_pool.LRU) == 0); + ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0); + ut_d(mysql_mutex_unlock(&buf_pool.mutex)); + + if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO) + { + sql_print_information("InnoDB: innodb_force_recovery=6 skips redo log apply"); + return DB_SUCCESS; + } + + mysql_mutex_lock(&log_sys.mutex); + ulint max_cp; + dberr_t err= recv_find_max_checkpoint(&max_cp); + + if (err != DB_SUCCESS) + recv_sys.recovered_lsn= log_sys.get_lsn(); + else + { + byte* buf= log_sys.checkpoint_buf; + err= log_sys.log.read(max_cp, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if (err == DB_SUCCESS) + { + log_sys.next_checkpoint_no= + mach_read_from_8(buf + LOG_CHECKPOINT_NO); + log_sys.next_checkpoint_lsn= + mach_read_from_8(buf + LOG_CHECKPOINT_LSN); + recv_sys.mlog_checkpoint_lsn= + mach_read_from_8(buf + LOG_CHECKPOINT_END_LSN); + } + } + mysql_mutex_unlock(&log_sys.mutex); + return err; +} + /** Start recovering from a redo log checkpoint. @param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN of first system tablespace page @@ -3422,12 +3462,8 @@ of first system tablespace page dberr_t recv_recovery_from_checkpoint_start(lsn_t flush_lsn) { - ulint max_cp_field; - lsn_t checkpoint_lsn; bool rescan = false; - ib_uint64_t checkpoint_no; lsn_t contiguous_lsn; - byte* buf; dberr_t err = DB_SUCCESS; ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED @@ -3445,27 +3481,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) return(DB_SUCCESS); } - recv_sys.recovery_on = true; - mysql_mutex_lock(&log_sys.mutex); - - err = recv_find_max_checkpoint(&max_cp_field); - - if (err != DB_SUCCESS) { - - recv_sys.recovered_lsn = log_sys.get_lsn(); - mysql_mutex_unlock(&log_sys.mutex); - return(err); - } - - buf = log_sys.checkpoint_buf; - if ((err= log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) { - mysql_mutex_unlock(&log_sys.mutex); - return(err); - } - - checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); - checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); + uint64_t checkpoint_no= log_sys.next_checkpoint_no; + lsn_t checkpoint_lsn= log_sys.next_checkpoint_lsn; + const lsn_t end_lsn= recv_sys.mlog_checkpoint_lsn; + recv_sys.recovery_on = true; /* Start reading the log from the checkpoint lsn. The variable contiguous_lsn contains an lsn up to which the log is known to @@ -3474,8 +3494,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size); - const lsn_t end_lsn = mach_read_from_8( - buf + LOG_CHECKPOINT_END_LSN); ut_ad(recv_sys.pages.empty()); contiguous_lsn = checkpoint_lsn; @@ -3845,8 +3863,52 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, return result; } +uint32_t recv_dblwr_t::find_first_page(const char *name, pfs_os_file_t file) +{ + os_offset_t file_size= os_file_get_size(file); + if (file_size != (os_offset_t) -1) + { + for (const page_t *page : pages) + { + uint32_t space_id= page_get_space_id(page); + if (page_get_page_no(page) > 0 || space_id == 0) +next_page: + continue; + uint32_t flags= mach_read_from_4( + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + page_id_t page_id(space_id, 0); + size_t page_size= fil_space_t::physical_size(flags); + if (file_size < 4 * page_size) + goto next_page; + byte *read_page= + static_cast(aligned_malloc(3 * page_size, page_size)); + /* Read 3 pages from the file and match the space id + with the space id which is stored in + doublewrite buffer page. */ + if (os_file_read(IORequestRead, file, read_page, page_size, + 3 * page_size) != DB_SUCCESS) + goto next_page; + for (ulint j= 0; j <= 2; j++) + { + byte *cur_page= read_page + j * page_size; + if (buf_is_zeroes(span(cur_page, page_size))) + return 0; + if (mach_read_from_4(cur_page + FIL_PAGE_OFFSET) != j + 1 || + memcmp(cur_page + FIL_PAGE_SPACE_ID, + page + FIL_PAGE_SPACE_ID, 4) || + buf_page_is_corrupted(false, cur_page, flags)) + goto next_page; + } + if (!restore_first_page(space_id, name, file)) + return space_id; + break; + } + } + return 0; +} + bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name, - os_file_t file) + pfs_os_file_t file) { const page_id_t page_id(space_id, 0); const byte* page= find_page(page_id); @@ -3854,10 +3916,11 @@ bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name, { /* If the first page of the given user tablespace is not there in the doublewrite buffer, then the recovery is going to fail - now. Hence this is treated as error. */ - ib::error() - << "Corrupted page " << page_id << " of datafile '" - << name <<"' could not be found in the doublewrite buffer."; + now. Report error only when doublewrite buffer is not empty */ + if (pages.size()) + ib::error() << "Corrupted page " << page_id << " of datafile '" + << name <<"' could not be found in the " + <<"doublewrite buffer."; return true; } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 56e41616d1d..0760b8ca5fd 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -297,9 +297,6 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn, log_sys.log.create(); log_sys.log.open_file(logfile0); - if (!fil_system.sys_space->open(create_new_db)) { - return DB_ERROR; - } /* Create a log checkpoint. */ mysql_mutex_lock(&log_sys.mutex); @@ -1274,40 +1271,6 @@ dberr_t srv_start(bool create_new_db) /* Check if undo tablespaces and redo log files exist before creating a new system tablespace */ - if (create_new_db) { - err = srv_check_undo_redo_logs_exists(); - if (err != DB_SUCCESS) { - return(srv_init_abort(DB_ERROR)); - } - recv_sys.debug_free(); - } - - /* Open or create the data files. */ - ulint sum_of_new_sizes; - - err = srv_sys_space.open_or_create( - false, create_new_db, &sum_of_new_sizes, &flushed_lsn); - - switch (err) { - case DB_SUCCESS: - break; - case DB_CANNOT_OPEN_FILE: - ib::error() - << "Could not open or create the system tablespace. If" - " you tried to add new data files to the system" - " tablespace, and it failed here, you should now" - " edit innodb_data_file_path in my.cnf back to what" - " it was, and remove the new ibdata files InnoDB" - " created in this failed attempt. InnoDB only wrote" - " those files full of zeros, but did not yet use" - " them in any way. But be careful: do not remove" - " old data files which contain your precious data!"; - /* fall through */ - default: - /* Other errors might come from Datafile::validate_first_page() */ - return(srv_init_abort(err)); - } - srv_log_file_size_requested = srv_log_file_size; if (innodb_encrypt_temporary_tables && !log_crypt_init()) { @@ -1317,18 +1280,17 @@ dberr_t srv_start(bool create_new_db) std::string logfile0; bool create_new_log = create_new_db; if (create_new_db) { + err = srv_check_undo_redo_logs_exists(); + if (err != DB_SUCCESS) { + return(srv_init_abort(DB_ERROR)); + } + recv_sys.debug_free(); flushed_lsn = log_sys.get_lsn(); log_sys.set_flushed_lsn(flushed_lsn); err = create_log_file(true, flushed_lsn, logfile0); if (err != DB_SUCCESS) { - for (Tablespace::const_iterator - i = srv_sys_space.begin(); - i != srv_sys_space.end(); i++) { - os_file_delete(innodb_data_file_key, - i->filepath()); - } return(srv_init_abort(err)); } } else { @@ -1343,51 +1305,84 @@ dberr_t srv_start(bool create_new_db) } create_new_log = srv_log_file_size == 0; - if (create_new_log) { - if (flushed_lsn < lsn_t(1000)) { - ib::error() - << "Cannot create log file because" - " data files are corrupt or the" - " database was not shut down cleanly" - " after creating the data files."; - return srv_init_abort(DB_ERROR); + if (!create_new_log) { + srv_log_file_found = log_file_found; + + log_sys.log.open_file(get_log_file_path()); + + log_sys.log.create(); + + if (!log_set_capacity( + srv_log_file_size_requested)) { + return(srv_init_abort(DB_ERROR)); } - srv_log_file_size = srv_log_file_size_requested; + /* Enable checkpoints in the page cleaner. */ + recv_sys.recovery_on = false; - err = create_log_file(false, flushed_lsn, logfile0); - - if (err == DB_SUCCESS) { - err = create_log_file_rename(flushed_lsn, - logfile0); - } + err= recv_recovery_read_max_checkpoint(); if (err != DB_SUCCESS) { - return(srv_init_abort(err)); + return srv_init_abort(err); } + } + } - /* Suppress the message about - crash recovery. */ - flushed_lsn = log_sys.get_lsn(); - goto file_checked; + /* Open or create the data files. */ + ulint sum_of_new_sizes; + + err = srv_sys_space.open_or_create( + false, create_new_db, &sum_of_new_sizes, &flushed_lsn); + + switch (err) { + case DB_SUCCESS: + break; + case DB_CANNOT_OPEN_FILE: + sql_print_error("InnoDB: Could not open or create the system" + " tablespace. If you tried to add new data files" + " to the system tablespace, and it failed here," + " you should now edit innodb_data_file_path" + " in my.cnf back to what it was, and remove the" + " new ibdata files InnoDB created in this failed" + " attempt. InnoDB only wrote those files full of" + " zeros, but did not yet use them in any way. But" + " be careful: do not remove old data files which" + " contain your precious data!"); + /* fall through */ + default: + /* Other errors might come from Datafile::validate_first_page() */ + return(srv_init_abort(err)); + } + + if (!create_new_db && create_new_log) { + if (flushed_lsn < lsn_t(1000)) { + sql_print_error( + "InnoDB: Cannot create log file because" + " data files are corrupt or the" + " database was not shut down cleanly" + " after creating the data files."); + return srv_init_abort(DB_ERROR); } - srv_log_file_found = log_file_found; + srv_log_file_size = srv_log_file_size_requested; - log_sys.log.open_file(get_log_file_path()); - - log_sys.log.create(); - - if (!log_set_capacity(srv_log_file_size_requested)) { - return(srv_init_abort(DB_ERROR)); + err = create_log_file(false, flushed_lsn, logfile0); + if (err == DB_SUCCESS) { + err = create_log_file_rename(flushed_lsn, logfile0); } - /* Enable checkpoints in the page cleaner. */ - recv_sys.recovery_on = false; + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + + /* Suppress the message about + crash recovery. */ + flushed_lsn = log_sys.get_lsn(); + goto file_checked; } file_checked: - /* Open log file and data files in the systemtablespace: we keep + /* Open data files in the systemtablespace: we keep them open until database shutdown */ ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug);