summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-10-11 22:48:19 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-10-11 23:00:48 +0300
commit81a5b6ccd531e802bbb0f2034189095d2196de8b (patch)
tree1a2ea81a0cdeba2db80025231a2e4c5fdf65da90
parentb8944e897298968a0bc31119bc975ef472bdb820 (diff)
downloadmariadb-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.result2
-rw-r--r--mysql-test/suite/innodb/t/log_file_size.test2
-rw-r--r--storage/innobase/srv/srv0start.cc114
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. */