MDEV-32968 InnoDB fails to restore tablespace first page from doublewrite...

MDEV-32968  InnoDB fails to restore tablespace first page from doublewrite buffer when page is empty

- InnoDB fails to find the space id from the page0 of
the tablespace. In that case, InnoDB can use
doublewrite buffer to recover the page0 and write
into the file.

- buf_dblwr_t::init_or_load_pages(): Loads only the pages
which are valid.(page lsn >= checkpoint). To do that,
InnoDB has to open the redo log before system
tablespace, read the latest checkpoint information.

recv_dblwr_t::find_first_page():
1) Iterate the doublewrite buffer pages and find the 0th page
2) Read the tablespace flags, space id from the 0th page.
3) Read the 1st, 2nd and 3rd page from tablespace file and
compare the space id with the space id which is stored
in doublewrite buffer.
4) If it matches then we can write into the file.
5) Return space which matches the pages from the file.

SysTablespace::read_lsn_and_check_flags(): Remove the
retry logic for validating the first page. After
restoring the first page from doublewrite buffer,
assign tablespace flags by reading the first page.

recv_recovery_read_max_checkpoint(): Reads the maximum
checkpoint information from log file

recv_recovery_from_checkpoint_start(): Avoid reading
the checkpoint header information from log file

Datafile::validate_first_page(): Throw error in case
of first page validation fails.
parent ee30491e
#
# 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
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
......
......@@ -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
......@@ -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`;
......
......@@ -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;
......
......@@ -324,11 +324,14 @@ dberr_t buf_dblwr_t::init_or_load_pages(pfs_os_file_t file, const char *path)
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;
}
......
......@@ -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);
......
......@@ -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
......
......@@ -103,7 +103,8 @@ class buf_dblwr_t
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 */
......
......@@ -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<byte*, ut_allocator<byte*> > list;
......
......@@ -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<byte*>(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<const byte>(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;
}
......
......@@ -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;
srv_log_file_size = srv_log_file_size_requested;
log_sys.log.open_file(get_log_file_path());
err = create_log_file(false, flushed_lsn, logfile0);
log_sys.log.create();
if (err == DB_SUCCESS) {
err = create_log_file_rename(flushed_lsn,
logfile0);
if (!log_set_capacity(
srv_log_file_size_requested)) {
return(srv_init_abort(DB_ERROR));
}
/* Enable checkpoints in the page cleaner. */
recv_sys.recovery_on = false;
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));
}
srv_log_file_found = log_file_found;
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);
}
log_sys.log.open_file(get_log_file_path());
srv_log_file_size = srv_log_file_size_requested;
log_sys.log.create();
err = create_log_file(false, flushed_lsn, logfile0);
if (err == DB_SUCCESS) {
err = create_log_file_rename(flushed_lsn, logfile0);
}
if (!log_set_capacity(srv_log_file_size_requested)) {
return(srv_init_abort(DB_ERROR));
if (err != DB_SUCCESS) {
return(srv_init_abort(err));
}
/* Enable checkpoints in the page cleaner. */
recv_sys.recovery_on = false;
/* 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment