diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-10-11 22:48:19 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-10-11 23:00:48 +0300 |
commit | 81a5b6ccd531e802bbb0f2034189095d2196de8b (patch) | |
tree | 1a2ea81a0cdeba2db80025231a2e4c5fdf65da90 | |
parent | b8944e897298968a0bc31119bc975ef472bdb820 (diff) | |
download | mariadb-git-81a5b6ccd531e802bbb0f2034189095d2196de8b.tar.gz |
MDEV-17433 Allow InnoDB start up with empty ib_logfile0 from mariabackup --prepare
A prepared backup from Mariabackup does not really need to contain any
redo log file, because all log will have been applied to the data files.
When the user copies a prepared backup to a data directory (overwriting
existing files), it could happen that the data directory already contained
redo log files from the past. mariabackup --copy-back) would delete the
old redo log files, but a user’s own copying script might not do that.
To prevent corruption caused by mixing an old redo log file with data
files from a backup, starting with MDEV-13311, Mariabackup would create
a zero-length ib_logfile0 that would prevent startup.
Actually, there is no need to prevent InnoDB from starting up when a
single zero-length file ib_logfile0 is present. Only if there exist
multiple data files of different lengths, then we should refuse to
start up due to inconsistency. A single zero-length ib_logfile0 should
be treated as if the log files were missing: create new log files
according to the configuration.
open_log_file(): Remove. There is no need to open the log files
at this point, because os_file_get_status() already determined
the size of the file.
innobase_start_or_create_for_mysql(): Move the creation of new
log files a little later, not when finding out that the first log
file does not exist, but after finding out that it does not exist
or it exists as a zero-length file.
-rw-r--r-- | mysql-test/suite/innodb/r/log_file_size.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/log_file_size.test | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 114 |
3 files changed, 45 insertions, 73 deletions
diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result index e049b34ad81..89d5c6ac4d6 100644 --- a/mysql-test/suite/innodb/r/log_file_size.result +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -3,7 +3,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /InnoDB: Log file .*ib_logfile0 size 0 is too small/ in mysqld.1.err +FOUND 1 /InnoDB: Log file .*ib_logfile1 is of different size .* bytes than other log files 0 bytes!/ in mysqld.1.err CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index 44cb155c7d9..1e6c7cd4d00 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -43,7 +43,7 @@ eval $check_no_innodb; --move_file $MYSQLD_DATADIR/ib_logfile.old $MYSQLD_DATADIR/ib_logfile.0 --source include/shutdown_mysqld.inc let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 0 is too small; +let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size .* bytes than other log files 0 bytes!; --source include/search_pattern_in_file.inc --source include/start_mysqld.inc CHECK TABLE t1; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a360a6ea50e..c6551595a08 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -571,34 +571,6 @@ create_log_files_rename( } /*********************************************************************//** -Opens a log file. -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -open_log_file( -/*==========*/ - pfs_os_file_t* file, /*!< out: file handle */ - const char* name, /*!< in: log file name */ - os_offset_t* size) /*!< out: file size */ -{ - bool ret; - - *file = os_file_create(innodb_log_file_key, name, - OS_FILE_OPEN, OS_FILE_AIO, - OS_LOG_FILE, srv_read_only_mode, &ret); - if (!ret) { - ib::error() << "Unable to open '" << name << "'"; - return(DB_ERROR); - } - - *size = os_file_get_size(*file); - - ret = os_file_close(*file); - ut_a(ret); - return(DB_SUCCESS); -} - -/*********************************************************************//** Create undo tablespace. @return DB_SUCCESS or error code */ static @@ -1975,8 +1947,9 @@ innobase_start_or_create_for_mysql() return(srv_init_abort(err)); } } else { + srv_log_file_size = 0; + for (i = 0; i < SRV_N_LOG_FILES_MAX; i++) { - os_offset_t size; os_file_stat_t stat_info; sprintf(logfilename + dirnamelen, @@ -1994,40 +1967,6 @@ innobase_start_or_create_for_mysql() == SRV_OPERATION_RESTORE_EXPORT) { return(DB_SUCCESS); } - if (flushed_lsn - < static_cast<lsn_t>(1000)) { - ib::error() - << "Cannot create" - " log files because" - " data files are" - " corrupt or the" - " database was not" - " shut down cleanly" - " after creating" - " the data files."; - return(srv_init_abort( - DB_ERROR)); - } - - err = create_log_files( - logfilename, dirnamelen, - flushed_lsn, logfile0); - - if (err == DB_SUCCESS) { - err = create_log_files_rename( - logfilename, - dirnamelen, - flushed_lsn, logfile0); - } - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - - /* Suppress the message about - crash recovery. */ - flushed_lsn = log_get_lsn(); - goto files_checked; } /* opened all files */ @@ -2038,12 +1977,7 @@ innobase_start_or_create_for_mysql() return(srv_init_abort(DB_ERROR)); } - err = open_log_file(&files[i], logfilename, &size); - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - + const os_offset_t size = stat_info.size; ut_a(size != (os_offset_t) -1); if (size & (OS_FILE_LOG_BLOCK_SIZE - 1)) { @@ -2068,8 +2002,13 @@ innobase_start_or_create_for_mysql() /* The first log file must consist of at least the following 512-byte pages: header, checkpoint page 1, empty, - checkpoint page 2, redo log page(s) */ - if (size <= OS_FILE_LOG_BLOCK_SIZE * 4) { + checkpoint page 2, redo log page(s). + + Mariabackup --prepare would create an + empty ib_logfile0. Tolerate it if there + are no other ib_logfile* files. */ + if ((size != 0 || i != 0) + && size <= OS_FILE_LOG_BLOCK_SIZE * 4) { ib::error() << "Log file " << logfilename << " size " << size << " is too small"; @@ -2086,6 +2025,39 @@ innobase_start_or_create_for_mysql() } } + if (srv_log_file_size == 0) { + if (flushed_lsn < lsn_t(1000)) { + ib::error() + << "Cannot create log files because" + " data files are corrupt or the" + " database was not shut down cleanly" + " after creating the data files."; + return srv_init_abort(DB_ERROR); + } + + strcpy(logfilename + dirnamelen, "ib_logfile0"); + srv_log_file_size = srv_log_file_size_requested; + + err = create_log_files( + logfilename, dirnamelen, + flushed_lsn, logfile0); + + if (err == DB_SUCCESS) { + err = create_log_files_rename( + logfilename, dirnamelen, + flushed_lsn, logfile0); + } + + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + + /* Suppress the message about + crash recovery. */ + flushed_lsn = log_get_lsn(); + goto files_checked; + } + srv_n_log_files_found = i; /* Create the in-memory file space objects. */ |