MDEV-12113: install_db shows corruption for rest encryption with innodb_data_file_path=ibdata1:3M;

Problem was that FIL_PAGE_FLUSH_LSN_OR_KEY_VERSION field that for
encrypted pages even in system datafiles should contain key_version
except very first page (0:0) is after encryption overwritten with
flush lsn.

Ported WL#7990 Repurpose FIL_PAGE_FLUSH_LSN to 10.1
The field FIL_PAGE_FLUSH_LSN_OR_KEY_VERSION is consulted during
InnoDB startup.

At startup, InnoDB reads the FIL_PAGE_FLUSH_LSN_OR_KEY_VERSION
from the first page of each file in the InnoDB system tablespace.
If there are multiple files, the minimum and maximum LSN can differ.
These numbers are passed to InnoDB startup.

Having the number in other files than the first file of the InnoDB
system tablespace is not providing much additional value. It is
conflicting with other use of the field, such as on InnoDB R-tree
index pages and encryption key_version.

This worklog will stop writing FIL_PAGE_FLUSH_LSN_OR_KEY_VERSION to
other files than the first file of the InnoDB system tablespace
(page number 0:0) when system tablespace is encrypted. If tablespace
is not encrypted we continue writing FIL_PAGE_FLUSH_LSN_OR_KEY_VERSION
to all first pages of system tablespace to avoid unnecessary
warnings on downgrade.

open_or_create_data_files(): pass only one flushed_lsn parameter

xb_load_tablespaces(): pass only one flushed_lsn parameter.

buf_page_create(): Improve comment about where
FIL_PAGE_FIL_FLUSH_LSN_OR_KEY_VERSION is set.

fil_write_flushed_lsn(): A new function, merged from
fil_write_lsn_and_arch_no_to_file() and
fil_write_flushed_lsn_to_data_files().
Only write to the first page of the system tablespace (page 0:0)
if tablespace is encrypted, or write all first pages of system
tablespace and invoke fil_flush_file_spaces(FIL_TYPE_TABLESPACE)
afterwards.

fil_read_first_page(): read flush_lsn and crypt_data only from
first datafile.

fil_open_single_table_tablespace(): Remove output of LSN, because it
was only valid for the system tablespace and the undo tablespaces, not
user tablespaces.

fil_validate_single_table_tablespace(): Remove output of LSN.

checkpoint_now_set(): Use fil_write_flushed_lsn and output
a error if operation fails.

Remove lsn variable from fsp_open_info.

recv_recovery_from_checkpoint_start(): Remove unnecessary second
flush_lsn parameter.

log_empty_and_mark_files_at_shutdown(): Use fil_writte_flushed_lsn
and output error if it fails.

open_or_create_data_files(): Pass only one flushed_lsn variable.
This commit is contained in:
Jan Lindström 2017-05-30 11:30:43 +03:00
parent 473f4a65e1
commit 1af8bf39ca
18 changed files with 557 additions and 604 deletions

View file

@ -27,13 +27,12 @@ extern pfs_os_file_t files[1000];
extern const char *innodb_checksum_algorithm_names[]; extern const char *innodb_checksum_algorithm_names[];
extern TYPELIB innodb_checksum_algorithm_typelib; extern TYPELIB innodb_checksum_algorithm_typelib;
extern dberr_t open_or_create_data_files( extern dberr_t open_or_create_data_files(
ibool* create_new_db, bool* create_new_db,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
lsn_t* min_arch_log_no, lsn_t* min_arch_log_no,
lsn_t* max_arch_log_no, lsn_t* max_arch_log_no,
#endif #endif
lsn_t* min_flushed_lsn, lsn_t* flushed_lsn,
lsn_t* max_flushed_lsn,
ulint* sum_of_new_sizes) ulint* sum_of_new_sizes)
; ;
int int

View file

@ -309,8 +309,7 @@ my_bool xtrabackup_rebuild_indexes = FALSE;
my_bool xtrabackup_incremental_force_scan = FALSE; my_bool xtrabackup_incremental_force_scan = FALSE;
/* The flushed lsn which is read from data files */ /* The flushed lsn which is read from data files */
lsn_t min_flushed_lsn= 0; lsn_t flushed_lsn= 0;
lsn_t max_flushed_lsn= 0;
/* The size of archived log file */ /* The size of archived log file */
ib_int64_t xtrabackup_arch_file_size = 0ULL; ib_int64_t xtrabackup_arch_file_size = 0ULL;
@ -3249,7 +3248,7 @@ xb_load_tablespaces(void)
/*=====================*/ /*=====================*/
{ {
ulint i; ulint i;
ibool create_new_db; bool create_new_db;
ulint err; ulint err;
ulint sum_of_new_sizes; ulint sum_of_new_sizes;
lsn_t min_arch_logno, max_arch_logno; lsn_t min_arch_logno, max_arch_logno;
@ -3265,7 +3264,7 @@ xb_load_tablespaces(void)
err = open_or_create_data_files(&create_new_db, err = open_or_create_data_files(&create_new_db,
&min_arch_logno, &max_arch_logno, &min_arch_logno, &max_arch_logno,
&min_flushed_lsn, &max_flushed_lsn, &flushed_lsn,
&sum_of_new_sizes); &sum_of_new_sizes);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
msg("xtrabackup: Could not open or create data files.\n" msg("xtrabackup: Could not open or create data files.\n"
@ -6475,13 +6474,13 @@ skip_check:
metadata_last_lsn); metadata_last_lsn);
xtrabackup_archived_to_lsn = metadata_last_lsn; xtrabackup_archived_to_lsn = metadata_last_lsn;
} }
if (xtrabackup_archived_to_lsn < min_flushed_lsn) { if (xtrabackup_archived_to_lsn < flushed_lsn) {
msg("xtrabackup: error: logs applying " msg("xtrabackup: error: logs applying "
"lsn limit " UINT64PF " is less than " "lsn limit " UINT64PF " is less than "
"min_flushed_lsn " UINT64PF "min_flushed_lsn " UINT64PF
", there is nothing to do\n", ", there is nothing to do\n",
xtrabackup_archived_to_lsn, xtrabackup_archived_to_lsn,
min_flushed_lsn); flushed_lsn);
goto error_cleanup; goto error_cleanup;
} }
} }
@ -6492,7 +6491,7 @@ skip_check:
*/ */
xtrabackup_apply_log_only = srv_apply_log_only = true; xtrabackup_apply_log_only = srv_apply_log_only = true;
if (!xtrabackup_arch_search_files(min_flushed_lsn)) { if (!xtrabackup_arch_search_files(flushed_lsn)) {
goto error_cleanup; goto error_cleanup;
} }

View file

@ -4291,11 +4291,11 @@ buf_page_create(
memset(frame + FIL_PAGE_NEXT, 0xff, 4); memset(frame + FIL_PAGE_NEXT, 0xff, 4);
mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
/* Reset to zero the file flush lsn field in the page; if the first /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the
page of an ibdata file is 'created' in this function into the buffer following pages:
pool then we lose the original contents of the file flush lsn stamp. (1) The first page of the InnoDB system tablespace (page 0:0)
Then InnoDB could in a crash recovery print a big, false, corruption (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages
warning if the stamp contains an lsn bigger than the ib_logfile lsn. */ (3) key_version on encrypted pages (not page 0:0) */
memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8); memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);

View file

@ -2211,99 +2211,70 @@ fil_set_max_space_id_if_bigger(
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
} }
/****************************************************************//** /** Write the flushed LSN to the page header of the first page in the
Writes the flushed lsn and the latest archived log number to the page header system tablespace.
of the first page of a data file of the system tablespace (space 0), @param[in] lsn flushed LSN
which is uncompressed. */ @return DB_SUCCESS or error number */
static MY_ATTRIBUTE((warn_unused_result))
dberr_t dberr_t
fil_write_lsn_and_arch_no_to_file( fil_write_flushed_lsn(
/*==============================*/ lsn_t lsn)
ulint space, /*!< in: space to write to */
ulint sum_of_sizes, /*!< in: combined size of previous files
in space, in database pages */
lsn_t lsn, /*!< in: lsn to write */
ulint arch_log_no MY_ATTRIBUTE((unused)))
/*!< in: archived log number to write */
{ {
byte* buf1; byte* buf1;
byte* buf; byte* buf;
dberr_t err; dberr_t err;
buf1 = static_cast<byte*>(mem_alloc(2 * UNIV_PAGE_SIZE)); buf1 = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE)); buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE));
err = fil_read(TRUE, space, 0, sum_of_sizes, 0, /* Acquire system tablespace */
UNIV_PAGE_SIZE, buf, NULL, 0); fil_space_t* space = fil_space_acquire(0);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
lsn);
err = fil_write(TRUE, space, 0, sum_of_sizes, 0, /* If tablespace is not encrypted, stamp flush_lsn to
UNIV_PAGE_SIZE, buf, NULL, 0); first page of all system tablespace datafiles to avoid
} unnecessary error messages on possible downgrade. */
if (space->crypt_data->min_key_version == 0) {
fil_node_t* node;
ulint sum_of_sizes = 0;
mem_free(buf1); for (node = UT_LIST_GET_FIRST(space->chain);
node != NULL;
node = UT_LIST_GET_NEXT(chain, node)) {
return(err); err = fil_read(TRUE, 0, 0, sum_of_sizes, 0,
} UNIV_PAGE_SIZE, buf, NULL, 0);
/****************************************************************//** if (err == DB_SUCCESS) {
Writes the flushed lsn and the latest archived log number to the page mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
header of the first page of each data file in the system tablespace. lsn);
@return DB_SUCCESS or error number */
UNIV_INTERN
dberr_t
fil_write_flushed_lsn_to_data_files(
/*================================*/
lsn_t lsn, /*!< in: lsn to write */
ulint arch_log_no) /*!< in: latest archived log file number */
{
fil_space_t* space;
fil_node_t* node;
dberr_t err;
mutex_enter(&fil_system->mutex); err = fil_write(TRUE, 0, 0, sum_of_sizes, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
for (space = UT_LIST_GET_FIRST(fil_system->space_list);
space != NULL;
space = UT_LIST_GET_NEXT(space_list, space)) {
/* We only write the lsn to all existing data files which have
been open during the lifetime of the mysqld process; they are
represented by the space objects in the tablespace memory
cache. Note that all data files in the system tablespace 0
and the UNDO log tablespaces (if separate) are always open. */
if (space->purpose == FIL_TABLESPACE
&& !fil_is_user_tablespace_id(space->id)) {
ulint sum_of_sizes = 0;
for (node = UT_LIST_GET_FIRST(space->chain);
node != NULL;
node = UT_LIST_GET_NEXT(chain, node)) {
mutex_exit(&fil_system->mutex);
err = fil_write_lsn_and_arch_no_to_file(
space->id, sum_of_sizes, lsn,
arch_log_no);
if (err != DB_SUCCESS) {
return(err);
}
mutex_enter(&fil_system->mutex);
sum_of_sizes += node->size; sum_of_sizes += node->size;
} }
} }
} else {
/* When system tablespace is encrypted stamp flush_lsn to
only the first page of the first datafile (rest of pages
are encrypted). */
err = fil_read(TRUE, 0, 0, 0, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
lsn);
err = fil_write(TRUE, 0, 0, 0, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
}
} }
mutex_exit(&fil_system->mutex); fil_flush_file_spaces(FIL_TABLESPACE);
fil_space_release(space);
return(DB_SUCCESS); ut_free(buf1);
return(err);
} }
/** Check the consistency of the first data page of a tablespace /** Check the consistency of the first data page of a tablespace
@ -2356,36 +2327,37 @@ fil_check_first_page(const page_t* page, ulint space_id, ulint flags)
return("inconsistent data in space header"); return("inconsistent data in space header");
} }
/*******************************************************************//** /** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
Reads the flushed lsn, arch no, space_id and tablespace flag fields from the first page of a first data file at database startup.
the first page of a data file at database startup. @param[in] data_file open data file
@param[in] one_read_only true if first datafile is already
read
@param[out] flags FSP_SPACE_FLAGS
@param[out] space_id tablepspace ID
@param[out] min_arch_log_no min of archived log numbers in
data files
@param[out] max_arch_log_no max of archived log numbers in
data files
@param[out] flushed_lsn flushed lsn value
@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set @retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */ @return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
const char* const char*
fil_read_first_page( fil_read_first_page(
/*================*/ pfs_os_file_t data_file,
pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already,
ibool one_read_already, /*!< in: TRUE if min and max ulint* flags,
parameters below already ulint* space_id,
contain sensible data */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< out: min of archived ulint* min_arch_log_no,
log numbers in data files */ ulint* max_arch_log_no,
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t* min_flushed_lsn, /*!< out: min of flushed lsn_t* flushed_lsn,
lsn values in data files */ fil_space_crypt_t** crypt_data)
lsn_t* max_flushed_lsn, /*!< out: max of flushed
lsn values in data files */
fil_space_crypt_t** crypt_data) /*< out: crypt data */
{ {
byte* buf; byte* buf;
byte* page; byte* page;
lsn_t flushed_lsn;
const char* check_msg = NULL; const char* check_msg = NULL;
fil_space_crypt_t* cdata; fil_space_crypt_t* cdata;
@ -2407,6 +2379,11 @@ fil_read_first_page(
*space_id = fsp_header_get_space_id(page); *space_id = fsp_header_get_space_id(page);
*flags = fsp_header_get_flags(page); *flags = fsp_header_get_flags(page);
if (flushed_lsn) {
*flushed_lsn = mach_read_from_8(page +
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
}
if (!fsp_flags_is_valid(*flags)) { if (!fsp_flags_is_valid(*flags)) {
ulint cflags = fsp_flags_convert_from_101(*flags); ulint cflags = fsp_flags_convert_from_101(*flags);
if (cflags == ULINT_UNDEFINED) { if (cflags == ULINT_UNDEFINED) {
@ -2420,33 +2397,33 @@ fil_read_first_page(
} }
check_msg = fil_check_first_page(page, *space_id, *flags); check_msg = fil_check_first_page(page, *space_id, *flags);
}
flushed_lsn = mach_read_from_8(page + /* Possible encryption crypt data is also stored only to first page
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); of the first datafile. */
ulint space = fsp_header_get_space_id(page); ulint offset = fsp_header_get_crypt_offset(
ulint offset = fsp_header_get_crypt_offset( fsp_flags_get_zip_size(*flags));
fsp_flags_get_zip_size(*flags));
cdata = fil_space_read_crypt_data(space, page, offset); cdata = fil_space_read_crypt_data(*space_id, page, offset);
if (crypt_data) { if (crypt_data) {
*crypt_data = cdata; *crypt_data = cdata;
} }
/* If file space is encrypted we need to have at least some /* If file space is encrypted we need to have at least some
encryption service available where to get keys */ encryption service available where to get keys */
if (cdata && cdata->should_encrypt()) { if (cdata && cdata->should_encrypt()) {
if (!encryption_key_id_exists(cdata->key_id)) { if (!encryption_key_id_exists(cdata->key_id)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Tablespace id %ld is encrypted but encryption service" "Tablespace id " ULINTPF
" or used key_id %u is not available. Can't continue opening tablespace.", " is encrypted but encryption service"
space, cdata->key_id); " or used key_id %u is not available. "
"Can't continue opening tablespace.",
return ("table encrypted but encryption service not available."); *space_id, cdata->key_id);
return ("table encrypted but encryption service not available.");
}
} }
} }
@ -2457,8 +2434,6 @@ fil_read_first_page(
} }
if (!one_read_already) { if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
*max_flushed_lsn = flushed_lsn;
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
*min_arch_log_no = arch_log_no; *min_arch_log_no = arch_log_no;
*max_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no;
@ -2466,16 +2441,11 @@ fil_read_first_page(
return(NULL); return(NULL);
} }
if (*min_flushed_lsn > flushed_lsn) {
*min_flushed_lsn = flushed_lsn;
}
if (*max_flushed_lsn < flushed_lsn) {
*max_flushed_lsn = flushed_lsn;
}
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
if (*min_arch_log_no > arch_log_no) { if (*min_arch_log_no > arch_log_no) {
*min_arch_log_no = arch_log_no; *min_arch_log_no = arch_log_no;
} }
if (*max_arch_log_no < arch_log_no) { if (*max_arch_log_no < arch_log_no) {
*max_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no;
} }
@ -4173,6 +4143,7 @@ fil_open_single_table_tablespace(
def.file = os_file_create_simple_no_error_handling( def.file = os_file_create_simple_no_error_handling(
innodb_file_data_key, def.filepath, OS_FILE_OPEN, innodb_file_data_key, def.filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &def.success, atomic_writes); OS_FILE_READ_ONLY, &def.success, atomic_writes);
if (def.success) { if (def.success) {
tablespaces_found++; tablespaces_found++;
} }
@ -4187,11 +4158,11 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */ /* Read the first page of the datadir tablespace, if found. */
if (def.success) { if (def.success) {
def.check_msg = fil_read_first_page( def.check_msg = fil_read_first_page(
def.file, FALSE, &def.flags, &def.id, def.file, false, &def.flags, &def.id,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&space_arch_log_no, &space_arch_log_no, &space_arch_log_no, &space_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&def.lsn, &def.lsn, &def.crypt_data); NULL, &def.crypt_data);
if (table) { if (table) {
table->crypt_data = def.crypt_data; table->crypt_data = def.crypt_data;
@ -4200,6 +4171,7 @@ fil_open_single_table_tablespace(
def.valid = !def.check_msg && def.id == id def.valid = !def.check_msg && def.id == id
&& fsp_flags_match(flags, def.flags); && fsp_flags_match(flags, def.flags);
if (def.valid) { if (def.valid) {
valid_tablespaces_found++; valid_tablespaces_found++;
} else { } else {
@ -4213,11 +4185,11 @@ fil_open_single_table_tablespace(
/* Read the first page of the remote tablespace */ /* Read the first page of the remote tablespace */
if (remote.success) { if (remote.success) {
remote.check_msg = fil_read_first_page( remote.check_msg = fil_read_first_page(
remote.file, FALSE, &remote.flags, &remote.id, remote.file, false, &remote.flags, &remote.id,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&remote.arch_log_no, &remote.arch_log_no, &remote.arch_log_no, &remote.arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&remote.lsn, &remote.lsn, &remote.crypt_data); NULL, &remote.crypt_data);
if (table) { if (table) {
table->crypt_data = remote.crypt_data; table->crypt_data = remote.crypt_data;
@ -4227,6 +4199,7 @@ fil_open_single_table_tablespace(
/* Validate this single-table-tablespace with SYS_TABLES. */ /* Validate this single-table-tablespace with SYS_TABLES. */
remote.valid = !remote.check_msg && remote.id == id remote.valid = !remote.check_msg && remote.id == id
&& fsp_flags_match(flags, remote.flags); && fsp_flags_match(flags, remote.flags);
if (remote.valid) { if (remote.valid) {
valid_tablespaces_found++; valid_tablespaces_found++;
} else { } else {
@ -4241,11 +4214,11 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */ /* Read the first page of the datadir tablespace, if found. */
if (dict.success) { if (dict.success) {
dict.check_msg = fil_read_first_page( dict.check_msg = fil_read_first_page(
dict.file, FALSE, &dict.flags, &dict.id, dict.file, false, &dict.flags, &dict.id,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&dict.arch_log_no, &dict.arch_log_no, &dict.arch_log_no, &dict.arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&dict.lsn, &dict.lsn, &dict.crypt_data); NULL, &dict.crypt_data);
if (table) { if (table) {
table->crypt_data = dict.crypt_data; table->crypt_data = dict.crypt_data;
@ -4289,26 +4262,32 @@ fil_open_single_table_tablespace(
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"A tablespace for %s has been found in " "A tablespace for %s has been found in "
"multiple places;", tablename); "multiple places;", tablename);
if (def.success) { if (def.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Default location; %s, LSN=" LSN_PF "Default location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
def.filepath, def.lsn, def.filepath,
(ulong) def.id, (ulong) def.flags); def.id,
def.flags);
} }
if (remote.success) { if (remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Remote location; %s, LSN=" LSN_PF "Remote location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
remote.filepath, remote.lsn, remote.filepath,
(ulong) remote.id, (ulong) remote.flags); remote.id,
remote.flags);
} }
if (dict.success) { if (dict.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Dictionary location; %s, LSN=" LSN_PF "Dictionary location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
dict.filepath, dict.lsn, dict.filepath,
(ulong) dict.id, (ulong) dict.flags); dict.id,
dict.flags);
} }
/* Force-recovery will allow some tablespaces to be /* Force-recovery will allow some tablespaces to be
@ -4341,6 +4320,7 @@ fil_open_single_table_tablespace(
os_file_close(def.file); os_file_close(def.file);
tablespaces_found--; tablespaces_found--;
} }
if (dict.success && !dict.valid) { if (dict.success && !dict.valid) {
dict.success = false; dict.success = false;
os_file_close(dict.file); os_file_close(dict.file);
@ -4348,6 +4328,7 @@ fil_open_single_table_tablespace(
can be corrected below. */ can be corrected below. */
tablespaces_found--; tablespaces_found--;
} }
if (remote.success && !remote.valid) { if (remote.success && !remote.valid) {
remote.success = false; remote.success = false;
os_file_close(remote.file); os_file_close(remote.file);
@ -4698,7 +4679,7 @@ check_first_page:
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&fsp->arch_log_no, &fsp->arch_log_no, &fsp->arch_log_no, &fsp->arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&fsp->lsn, &fsp->lsn, &fsp->crypt_data)) { NULL, &fsp->crypt_data)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"%s in tablespace %s (table %s)", "%s in tablespace %s (table %s)",
check_msg, fsp->filepath, tablename); check_msg, fsp->filepath, tablename);
@ -4928,11 +4909,11 @@ will_not_choose:
if (def.success && remote.success) { if (def.success && remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Tablespaces for %s have been found in two places;\n" "Tablespaces for %s have been found in two places;\n"
"Location 1: SpaceID: %lu LSN: %lu File: %s\n" "Location 1: SpaceID: " ULINTPF " File: %s\n"
"Location 2: SpaceID: %lu LSN: %lu File: %s\n" "Location 2: SpaceID: " ULINTPF " File: %s\n"
"You must delete one of them.", "You must delete one of them.",
tablename, (ulong) def.id, (ulong) def.lsn, tablename, def.id,
def.filepath, (ulong) remote.id, (ulong) remote.lsn, def.filepath, remote.id,
remote.filepath); remote.filepath);
def.success = FALSE; def.success = FALSE;

View file

@ -18221,8 +18221,15 @@ checkpoint_now_set(
log_make_checkpoint_at(LSN_MAX, TRUE); log_make_checkpoint_at(LSN_MAX, TRUE);
fil_flush_file_spaces(FIL_LOG); fil_flush_file_spaces(FIL_LOG);
} }
fil_write_flushed_lsn_to_data_files(log_sys->lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE); dberr_t err = fil_write_flushed_lsn(log_sys->lsn);
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Failed to write flush lsn to the "
"system tablespace at checkpoint err=%s",
ut_strerr(err));
}
} }
} }

View file

@ -215,7 +215,6 @@ struct fsp_open_info {
ibool valid; /*!< Is the tablespace valid? */ ibool valid; /*!< Is the tablespace valid? */
pfs_os_file_t file; /*!< File handle */ pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */ char* filepath; /*!< File path to open */
lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */ ulint id; /*!< Space ID */
ulint flags; /*!< Tablespace flags */ ulint flags; /*!< Tablespace flags */
ulint encryption_error; /*!< if an encryption error occurs */ ulint encryption_error; /*!< if an encryption error occurs */
@ -637,17 +636,17 @@ void
fil_set_max_space_id_if_bigger( fil_set_max_space_id_if_bigger(
/*===========================*/ /*===========================*/
ulint max_id);/*!< in: maximum known id */ ulint max_id);/*!< in: maximum known id */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/****************************************************************//**
Writes the flushed lsn and the latest archived log number to the page /** Write the flushed LSN to the page header of the first page in the
header of the first page of each data file in the system tablespace. system tablespace.
@return DB_SUCCESS or error number */ @param[in] lsn flushed LSN
UNIV_INTERN @return DB_SUCCESS or error number */
dberr_t dberr_t
fil_write_flushed_lsn_to_data_files( fil_write_flushed_lsn(
/*================================*/ lsn_t lsn)
lsn_t lsn, /*!< in: lsn to write */ MY_ATTRIBUTE((warn_unused_result));
ulint arch_log_no); /*!< in: latest archived log file number */
/** Acquire a tablespace when it could be dropped concurrently. /** Acquire a tablespace when it could be dropped concurrently.
Used by background threads that do not necessarily hold proper locks Used by background threads that do not necessarily hold proper locks
@ -793,35 +792,37 @@ private:
fil_space_t* m_space; fil_space_t* m_space;
}; };
/*******************************************************************//** /** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
Reads the flushed lsn, arch no, and tablespace flag fields from a data the first page of a first data file at database startup.
file at database startup. @param[in] data_file open data file
@param[in] one_read_only true if first datafile is already
read
@param[out] flags FSP_SPACE_FLAGS
@param[out] space_id tablepspace ID
@param[out] min_arch_log_no min of archived log numbers in
data files
@param[out] max_arch_log_no max of archived log numbers in
data files
@param[out] flushed_lsn flushed lsn value
@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set @retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */ @return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
const char* const char*
fil_read_first_page( fil_read_first_page(
/*================*/ pfs_os_file_t data_file,
pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already,
ibool one_read_already, /*!< in: TRUE if min and max ulint* flags,
parameters below already ulint* space_id,
contain sensible data */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< out: min of archived ulint* min_arch_log_no,
log numbers in data files */ ulint* max_arch_log_no,
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t* min_flushed_lsn, /*!< out: min of flushed lsn_t* flushed_lsn,
lsn values in data files */ fil_space_crypt_t** crypt_data)
lsn_t* max_flushed_lsn, /*!< out: max of flushed MY_ATTRIBUTE((warn_unused_result));
lsn values in data files */
fil_space_crypt_t** crypt_data) /*!< out: crypt data */
__attribute__((warn_unused_result));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/*******************************************************************//** /*******************************************************************//**
Parses the body of a log record written about an .ibd file operation. That is, Parses the body of a log record written about an .ibd file operation. That is,
the log record part after the standard (type, space id, page no) header of the the log record part after the standard (type, space id, page no) header of the

View file

@ -123,26 +123,25 @@ a freshly read page)
*/ */
# define recv_recover_page(jri, block) recv_recover_page_func(block) # define recv_recover_page(jri, block) recv_recover_page_func(block)
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/********************************************************//**
Recovers from a checkpoint. When this function returns, the database is able /** Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
@param[in] limit_lsn recover up to this lsn if possible
@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
UNIV_INTERN UNIV_INTERN
dberr_t dberr_t
recv_recovery_from_checkpoint_start_func( recv_recovery_from_checkpoint_start_func(
/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint type, /*!< in: LOG_CHECKPOINT or ulint type,
LOG_ARCHIVE */ lsn_t limit_lsn,
lsn_t limit_lsn, /*!< in: recover up to this lsn
if possible */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t min_flushed_lsn,/*!< in: min flushed lsn from lsn_t flushed_lsn)
data files */ MY_ATTRIBUTE((warn_unused_result));
lsn_t max_flushed_lsn);/*!< in: max flushed lsn from
data files */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
/** Wrapper for recv_recovery_from_checkpoint_start_func(). /** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able Recovers from a checkpoint. When this function returns, the database is able
@ -151,11 +150,10 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param type in: LOG_CHECKPOINT or LOG_ARCHIVE @param type in: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim in: recover up to this log sequence number if possible @param lim in: recover up to this log sequence number if possible
@param min in: minimum flushed log sequence number from data files @param lsn in: flushed log sequence number from first data file
@param max in: maximum flushed log sequence number from data files
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \ # define recv_recovery_from_checkpoint_start(type,lim,lsn) \
recv_recovery_from_checkpoint_start_func(type,lim,min,max) recv_recovery_from_checkpoint_start_func(type,lim,lsn)
#else /* UNIV_LOG_ARCHIVE */ #else /* UNIV_LOG_ARCHIVE */
/** Wrapper for recv_recovery_from_checkpoint_start_func(). /** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able Recovers from a checkpoint. When this function returns, the database is able
@ -164,12 +162,12 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE @param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim ignored: recover up to this log sequence number if possible @param lim ignored: recover up to this log sequence number if possible
@param min in: minimum flushed log sequence number from data files @param lsn in: flushed log sequence number from first data file
@param max in: maximum flushed log sequence number from data files
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \ # define recv_recovery_from_checkpoint_start(type,lim,lsn) \
recv_recovery_from_checkpoint_start_func(min,max) recv_recovery_from_checkpoint_start_func(lsn)
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
/********************************************************//** /********************************************************//**
Completes recovery from a checkpoint. */ Completes recovery from a checkpoint. */
UNIV_INTERN UNIV_INTERN

View file

@ -3246,7 +3246,9 @@ logs_empty_and_mark_files_at_shutdown(void)
/*=======================================*/ /*=======================================*/
{ {
lsn_t lsn; lsn_t lsn;
#ifdef UNIV_LOG_ARCHIVE
ulint arch_log_no; ulint arch_log_no;
#endif
ulint count = 0; ulint count = 0;
ulint pending_io; ulint pending_io;
ibool server_busy; ibool server_busy;
@ -3454,9 +3456,9 @@ wait_suspend_loop:
goto loop; goto loop;
} }
#ifdef UNIV_LOG_ARCHIVE
arch_log_no = 0; arch_log_no = 0;
#ifdef UNIV_LOG_ARCHIVE
UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no; UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
if (!UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) { if (!UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
@ -3511,9 +3513,14 @@ wait_suspend_loop:
srv_shutdown_lsn = lsn; srv_shutdown_lsn = lsn;
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no); dberr_t err = fil_write_flushed_lsn(lsn);
fil_flush_file_spaces(FIL_TABLESPACE); if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Failed to write flush lsn to the "
"system tablespace at shutdown err=%s",
ut_strerr(err));
}
} }
fil_close_all_files(); fil_close_all_files();

View file

@ -2929,22 +2929,22 @@ recv_init_crash_recovery(void)
} }
} }
/********************************************************//** /** Recovers from a checkpoint. When this function returns, the database is able
Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
@param[in] limit_lsn recover up to this lsn if possible
@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
UNIV_INTERN UNIV_INTERN
dberr_t dberr_t
recv_recovery_from_checkpoint_start_func( recv_recovery_from_checkpoint_start_func(
/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint type, /*!< in: LOG_CHECKPOINT or LOG_ARCHIVE */ ulint type,
lsn_t limit_lsn, /*!< in: recover up to this lsn if possible */ lsn_t limit_lsn,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t min_flushed_lsn,/*!< in: min flushed lsn from data files */ lsn_t flushed_lsn)
lsn_t max_flushed_lsn)/*!< in: max flushed lsn from data files */
{ {
log_group_t* group; log_group_t* group;
log_group_t* max_cp_group; log_group_t* max_cp_group;
@ -3165,6 +3165,7 @@ recv_recovery_from_checkpoint_start_func(
group = UT_LIST_GET_NEXT(log_groups, group); group = UT_LIST_GET_NEXT(log_groups, group);
} }
/* Done with startup scan. Clear the flag. */ /* Done with startup scan. Clear the flag. */
recv_log_scan_is_startup_type = FALSE; recv_log_scan_is_startup_type = FALSE;
@ -3177,10 +3178,9 @@ recv_recovery_from_checkpoint_start_func(
there is something wrong we will print a message to the there is something wrong we will print a message to the
user about recovery: */ user about recovery: */
if (checkpoint_lsn != max_flushed_lsn if (checkpoint_lsn != flushed_lsn) {
|| checkpoint_lsn != min_flushed_lsn) {
if (checkpoint_lsn < max_flushed_lsn) { if (checkpoint_lsn < flushed_lsn) {
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"The log sequence number " "The log sequence number "
@ -3191,24 +3191,21 @@ recv_recovery_from_checkpoint_start_func(
"ib_logfiles to start up the database. " "ib_logfiles to start up the database. "
"Log sequence number in the " "Log sequence number in the "
"ib_logfiles is " LSN_PF ", log" "ib_logfiles is " LSN_PF ", log"
"sequence numbers stamped " "sequence number stamped "
"to ibdata file headers are between " "to ibdata file header is " LSN_PF ".",
"" LSN_PF " and " LSN_PF ".",
checkpoint_lsn, checkpoint_lsn,
min_flushed_lsn, flushed_lsn);
max_flushed_lsn);
} }
if (!recv_needed_recovery) { if (!recv_needed_recovery) {
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"The log sequence numbers " "The log sequence number "
LSN_PF " and " LSN_PF LSN_PF
" in ibdata files do not match" " in ibdata file do not match"
" the log sequence number " " the log sequence number "
LSN_PF LSN_PF
" in the ib_logfiles!", " in the ib_logfiles!",
min_flushed_lsn, flushed_lsn,
max_flushed_lsn,
checkpoint_lsn); checkpoint_lsn);
if (!srv_read_only_mode) { if (!srv_read_only_mode) {

View file

@ -786,27 +786,26 @@ open_log_file(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/*********************************************************************//** /** Creates or opens database data files and closes them.
Creates or opens database data files and closes them. @param[out] create_new_db true = create new database
@param[out] min_arch_log_no min of archived log numbers in
data files
@param[out] max_arch_log_no max of archived log numbers in
data files
@param[out] flushed_lsn flushed lsn in fist datafile
@param[out] sum_of_new_sizes sum of sizes of the new files
added
@return DB_SUCCESS or error code */ @return DB_SUCCESS or error code */
static MY_ATTRIBUTE((nonnull, warn_unused_result)) static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dberr_t
open_or_create_data_files( open_or_create_data_files(
/*======================*/ bool* create_new_db,
ibool* create_new_db, /*!< out: TRUE if new database should be
created */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no,/*!< out: min of archived log ulint* min_arch_log_no,
numbers in data files */ ulint* max_arch_log_no,
ulint* max_arch_log_no,/*!< out: max of archived log
numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t* min_flushed_lsn,/*!< out: min of flushed lsn lsn_t* flushed_lsn,
values in data files */ ulint* sum_of_new_sizes)
lsn_t* max_flushed_lsn,/*!< out: max of flushed lsn
values in data files */
ulint* sum_of_new_sizes)/*!< out: sum of sizes of the
new files added */
{ {
ibool ret; ibool ret;
ulint i; ulint i;
@ -830,7 +829,7 @@ open_or_create_data_files(
*sum_of_new_sizes = 0; *sum_of_new_sizes = 0;
*create_new_db = FALSE; *create_new_db = false;
srv_normalize_path_for_win(srv_data_home); srv_normalize_path_for_win(srv_data_home);
@ -918,12 +917,13 @@ open_or_create_data_files(
} }
const char* check_msg; const char* check_msg;
check_msg = fil_read_first_page( check_msg = fil_read_first_page(
files[i], FALSE, &flags, &space, files[i], FALSE, &flags, &space,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no, min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn, NULL); flushed_lsn, NULL);
/* If first page is valid, don't overwrite DB. /* If first page is valid, don't overwrite DB.
It prevents overwriting DB when mysql_install_db It prevents overwriting DB when mysql_install_db
@ -954,6 +954,7 @@ open_or_create_data_files(
name); name);
return(DB_ERROR); return(DB_ERROR);
} }
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
ut_a(!srv_read_only_mode); ut_a(!srv_read_only_mode);
files[i] = os_file_create( files[i] = os_file_create(
@ -973,7 +974,6 @@ open_or_create_data_files(
} }
if (!ret) { if (!ret) {
os_file_get_last_error(true); os_file_get_last_error(true);
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
@ -983,7 +983,6 @@ open_or_create_data_files(
} }
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
goto skip_size_check; goto skip_size_check;
} }
@ -1010,16 +1009,15 @@ size_check:
"auto-extending " "auto-extending "
"data file %s is " "data file %s is "
"of a different size " "of a different size "
"%lu pages (rounded " ULINTPF " pages (rounded "
"down to MB) than specified " "down to MB) than specified "
"in the .cnf file: " "in the .cnf file: "
"initial %lu pages, " "initial " ULINTPF " pages, "
"max %lu (relevant if " "max " ULINTPF " (relevant if "
"non-zero) pages!", "non-zero) pages!",
name, name,
(ulong) rounded_size_pages, rounded_size_pages,
(ulong) srv_data_file_sizes[i], srv_data_file_sizes[i],
(ulong)
srv_last_file_size_max); srv_last_file_size_max);
return(DB_ERROR); return(DB_ERROR);
@ -1032,12 +1030,12 @@ size_check:
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Data file %s is of a different " "Data file %s is of a different "
"size %lu pages (rounded down to MB) " "size " ULINTPF " pages (rounded down to MB) "
"than specified in the .cnf file " "than specified in the .cnf file "
"%lu pages!", ULINTPF " pages!",
name, name,
(ulong) rounded_size_pages, rounded_size_pages,
(ulong) srv_data_file_sizes[i]); srv_data_file_sizes[i]);
return(DB_ERROR); return(DB_ERROR);
} }
@ -1057,7 +1055,7 @@ check_first_page:
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no, min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn, &crypt_data); flushed_lsn, &crypt_data);
if (check_msg) { if (check_msg) {
@ -1094,9 +1092,9 @@ check_first_page:
!= fsp_flags_get_page_size(flags)) { != fsp_flags_get_page_size(flags)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Data file \"%s\" uses page size %lu," "Data file \"%s\" uses page size " ULINTPF " ,"
"but the start-up parameter " "but the start-up parameter "
"is --innodb-page-size=%lu", "is --innodb-page-size=" ULINTPF " .",
name, name,
fsp_flags_get_page_size(flags), fsp_flags_get_page_size(flags),
UNIV_PAGE_SIZE); UNIV_PAGE_SIZE);
@ -1127,9 +1125,9 @@ check_first_page:
} }
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"Setting file %s size to %lu MB", "Setting file %s size to " ULINTPF " MB",
name, name,
(ulong) (srv_data_file_sizes[i] (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT))); >> (20 - UNIV_PAGE_SIZE_SHIFT)));
ret = os_file_set_size( ret = os_file_set_size(
@ -1592,9 +1590,8 @@ dberr_t
innobase_start_or_create_for_mysql(void) innobase_start_or_create_for_mysql(void)
/*====================================*/ /*====================================*/
{ {
ibool create_new_db; bool create_new_db;
lsn_t min_flushed_lsn; lsn_t flushed_lsn;
lsn_t max_flushed_lsn;
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint min_arch_log_no; ulint min_arch_log_no;
ulint max_arch_log_no; ulint max_arch_log_no;
@ -2152,7 +2149,7 @@ innobase_start_or_create_for_mysql(void)
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&min_arch_log_no, &max_arch_log_no, &min_arch_log_no, &max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&min_flushed_lsn, &max_flushed_lsn, &flushed_lsn,
&sum_of_new_sizes); &sum_of_new_sizes);
if (err == DB_FAIL) { if (err == DB_FAIL) {
@ -2197,12 +2194,12 @@ innobase_start_or_create_for_mysql(void)
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success); ut_a(success);
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
err = create_log_files(create_new_db, logfilename, dirnamelen, err = create_log_files(create_new_db, logfilename, dirnamelen,
max_flushed_lsn, logfile0); flushed_lsn, logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@ -2222,19 +2219,8 @@ innobase_start_or_create_for_mysql(void)
if (err == DB_NOT_FOUND) { if (err == DB_NOT_FOUND) {
if (i == 0) { if (i == 0) {
if (max_flushed_lsn
!= min_flushed_lsn) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot create"
" log files because"
" data files are"
" corrupt or"
" not in sync"
" with each other");
return(DB_ERROR);
}
if (max_flushed_lsn < (lsn_t) 1000) { if (flushed_lsn < (lsn_t) 1000) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot create" "Cannot create"
" log files because" " log files because"
@ -2249,14 +2235,14 @@ innobase_start_or_create_for_mysql(void)
err = create_log_files( err = create_log_files(
create_new_db, logfilename, create_new_db, logfilename,
dirnamelen, max_flushed_lsn, dirnamelen, flushed_lsn,
logfile0); logfile0);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
err = create_log_files_rename( err = create_log_files_rename(
logfilename, logfilename,
dirnamelen, dirnamelen,
max_flushed_lsn, flushed_lsn,
logfile0); logfile0);
} }
@ -2266,8 +2252,7 @@ innobase_start_or_create_for_mysql(void)
/* Suppress the message about /* Suppress the message about
crash recovery. */ crash recovery. */
max_flushed_lsn = min_flushed_lsn flushed_lsn = log_get_lsn();
= log_get_lsn();
goto files_checked; goto files_checked;
} else if (i < 2) { } else if (i < 2) {
/* must have at least 2 log files */ /* must have at least 2 log files */
@ -2422,17 +2407,19 @@ files_checked:
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success); ut_a(success);
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
/* Stamp the LSN to the data files. */ /* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files(max_flushed_lsn, 0); err = fil_write_flushed_lsn(flushed_lsn);
fil_flush_file_spaces(FIL_TABLESPACE); if (err != DB_SUCCESS) {
return(err);
}
err = create_log_files_rename(logfilename, dirnamelen, err = create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0); flushed_lsn, logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@ -2504,7 +2491,7 @@ files_checked:
err = recv_recovery_from_checkpoint_start( err = recv_recovery_from_checkpoint_start(
LOG_CHECKPOINT, LSN_MAX, LOG_CHECKPOINT, LSN_MAX,
min_flushed_lsn, max_flushed_lsn); flushed_lsn);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
/* Initialize the change buffer. */ /* Initialize the change buffer. */
@ -2672,7 +2659,7 @@ files_checked:
DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_EXECUTE_IF("innodb_log_abort_1",
return(DB_ERROR);); return(DB_ERROR););
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"Resizing redo log from %u*%u to %u*%u pages" "Resizing redo log from %u*%u to %u*%u pages"
@ -2681,7 +2668,7 @@ files_checked:
(unsigned) srv_log_file_size, (unsigned) srv_log_file_size,
(unsigned) srv_n_log_files, (unsigned) srv_n_log_files,
(unsigned) srv_log_file_size_requested, (unsigned) srv_log_file_size_requested,
max_flushed_lsn); flushed_lsn);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
@ -2691,7 +2678,7 @@ files_checked:
we need to explicitly flush the log buffers. */ we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID); fil_flush(SRV_LOG_SPACE_FIRST_ID);
ut_ad(max_flushed_lsn == log_get_lsn()); ut_ad(flushed_lsn == log_get_lsn());
/* Prohibit redo log writes from any other /* Prohibit redo log writes from any other
threads until creating a log checkpoint at the threads until creating a log checkpoint at the
@ -2703,8 +2690,7 @@ files_checked:
return(DB_ERROR);); return(DB_ERROR););
/* Stamp the LSN to the data files. */ /* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files( err = fil_write_flushed_lsn(flushed_lsn);
max_flushed_lsn, 0);
DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
@ -2712,8 +2698,6 @@ files_checked:
return(err); return(err);
} }
fil_flush_file_spaces(FIL_TABLESPACE);
/* Close and free the redo log files, so that /* Close and free the redo log files, so that
we can replace them. */ we can replace them. */
fil_close_log_files(true); fil_close_log_files(true);
@ -2730,13 +2714,23 @@ files_checked:
srv_log_file_size = srv_log_file_size_requested; srv_log_file_size = srv_log_file_size_requested;
err = create_log_files(create_new_db, logfilename, err = create_log_files(create_new_db, logfilename,
dirnamelen, max_flushed_lsn, dirnamelen, flushed_lsn,
logfile0); logfile0);
if (err != DB_SUCCESS) {
return(err);
}
/* create_log_files() can increase system lsn that is
why FIL_PAGE_FILE_FLUSH_LSN have to be updated */
flushed_lsn = log_get_lsn();
err = fil_write_flushed_lsn(flushed_lsn);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
err = create_log_files_rename( err = create_log_files_rename(
logfilename, dirnamelen, logfilename, dirnamelen,
max_flushed_lsn, logfile0); flushed_lsn, logfile0);
} }
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {

View file

@ -4371,11 +4371,11 @@ buf_page_create(
memset(frame + FIL_PAGE_NEXT, 0xff, 4); memset(frame + FIL_PAGE_NEXT, 0xff, 4);
mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
/* Reset to zero the file flush lsn field in the page; if the first /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the
page of an ibdata file is 'created' in this function into the buffer following pages:
pool then we lose the original contents of the file flush lsn stamp. (1) The first page of the InnoDB system tablespace (page 0:0)
Then InnoDB could in a crash recovery print a big, false, corruption (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages
warning if the stamp contains an lsn bigger than the ib_logfile lsn. */ (3) key_version on encrypted pages (not page 0:0) */
memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8); memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);

View file

@ -2265,99 +2265,70 @@ fil_set_max_space_id_if_bigger(
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
} }
/****************************************************************//** /** Write the flushed LSN to the page header of the first page in the
Writes the flushed lsn and the latest archived log number to the page header system tablespace.
of the first page of a data file of the system tablespace (space 0), @param[in] lsn flushed LSN
which is uncompressed. */ @return DB_SUCCESS or error number */
static MY_ATTRIBUTE((warn_unused_result))
dberr_t dberr_t
fil_write_lsn_and_arch_no_to_file( fil_write_flushed_lsn(
/*==============================*/ lsn_t lsn)
ulint space, /*!< in: space to write to */
ulint sum_of_sizes, /*!< in: combined size of previous files
in space, in database pages */
lsn_t lsn, /*!< in: lsn to write */
ulint arch_log_no MY_ATTRIBUTE((unused)))
/*!< in: archived log number to write */
{ {
byte* buf1; byte* buf1;
byte* buf; byte* buf;
dberr_t err; dberr_t err;
buf1 = static_cast<byte*>(mem_alloc(2 * UNIV_PAGE_SIZE)); buf1 = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE)); buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE));
err = fil_read(TRUE, space, 0, sum_of_sizes, 0, /* Acquire system tablespace */
UNIV_PAGE_SIZE, buf, NULL, 0); fil_space_t* space = fil_space_acquire(0);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
lsn);
err = fil_write(TRUE, space, 0, sum_of_sizes, 0, /* If tablespace is not encrypted, stamp flush_lsn to
UNIV_PAGE_SIZE, buf, NULL, 0); first page of all system tablespace datafiles to avoid
} unnecessary error messages on possible downgrade. */
if (space->crypt_data->min_key_version == 0) {
fil_node_t* node;
ulint sum_of_sizes = 0;
mem_free(buf1); for (node = UT_LIST_GET_FIRST(space->chain);
node != NULL;
node = UT_LIST_GET_NEXT(chain, node)) {
return(err); err = fil_read(TRUE, 0, 0, sum_of_sizes, 0,
} UNIV_PAGE_SIZE, buf, NULL, 0);
/****************************************************************//** if (err == DB_SUCCESS) {
Writes the flushed lsn and the latest archived log number to the page mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
header of the first page of each data file in the system tablespace. lsn);
@return DB_SUCCESS or error number */
UNIV_INTERN
dberr_t
fil_write_flushed_lsn_to_data_files(
/*================================*/
lsn_t lsn, /*!< in: lsn to write */
ulint arch_log_no) /*!< in: latest archived log file number */
{
fil_space_t* space;
fil_node_t* node;
dberr_t err;
mutex_enter(&fil_system->mutex); err = fil_write(TRUE, 0, 0, sum_of_sizes, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
for (space = UT_LIST_GET_FIRST(fil_system->space_list);
space != NULL;
space = UT_LIST_GET_NEXT(space_list, space)) {
/* We only write the lsn to all existing data files which have
been open during the lifetime of the mysqld process; they are
represented by the space objects in the tablespace memory
cache. Note that all data files in the system tablespace 0
and the UNDO log tablespaces (if separate) are always open. */
if (space->purpose == FIL_TABLESPACE
&& !fil_is_user_tablespace_id(space->id)) {
ulint sum_of_sizes = 0;
for (node = UT_LIST_GET_FIRST(space->chain);
node != NULL;
node = UT_LIST_GET_NEXT(chain, node)) {
mutex_exit(&fil_system->mutex);
err = fil_write_lsn_and_arch_no_to_file(
space->id, sum_of_sizes, lsn,
arch_log_no);
if (err != DB_SUCCESS) {
return(err);
}
mutex_enter(&fil_system->mutex);
sum_of_sizes += node->size; sum_of_sizes += node->size;
} }
} }
} else {
/* When system tablespace is encrypted stamp flush_lsn to
only the first page of the first datafile (rest of pages
are encrypted). */
err = fil_read(TRUE, 0, 0, 0, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
lsn);
err = fil_write(TRUE, 0, 0, 0, 0,
UNIV_PAGE_SIZE, buf, NULL, 0);
}
} }
mutex_exit(&fil_system->mutex); fil_flush_file_spaces(FIL_TABLESPACE);
fil_space_release(space);
return(DB_SUCCESS); ut_free(buf1);
return(err);
} }
/** Check the consistency of the first data page of a tablespace /** Check the consistency of the first data page of a tablespace
@ -2410,30 +2381,29 @@ fil_check_first_page(const page_t* page, ulint space_id, ulint flags)
return("inconsistent data in space header"); return("inconsistent data in space header");
} }
/*******************************************************************//** /** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
Reads the flushed lsn, arch no, space_id and tablespace flag fields from the first page of a first data file at database startup.
the first page of a data file at database startup. @param[in] data_file open data file
@param[in] one_read_only true if first datafile is already
read
@param[out] flags FSP_SPACE_FLAGS
@param[out] space_id tablepspace ID
@param[out] flushed_lsn flushed lsn value
@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set @retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */ @return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
const char* const char*
fil_read_first_page( fil_read_first_page(
/*================*/ pfs_os_file_t data_file,
pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already,
ibool one_read_already, /*!< in: TRUE if min and max ulint* flags,
parameters below already ulint* space_id,
contain sensible data */ lsn_t* flushed_lsn,
ulint* flags, /*!< out: FSP_SPACE_FLAGS */ fil_space_crypt_t** crypt_data)
ulint* space_id, /*!< out: tablespace ID */
lsn_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
lsn_t* max_flushed_lsn, /*!< out: max of flushed
lsn values in data files */
fil_space_crypt_t** crypt_data) /*< out: crypt data */
{ {
byte* buf; byte* buf;
byte* page; byte* page;
lsn_t flushed_lsn;
const char* check_msg = NULL; const char* check_msg = NULL;
fil_space_crypt_t* cdata; fil_space_crypt_t* cdata;
@ -2450,6 +2420,7 @@ fil_read_first_page(
return "File size is less than minimum"; return "File size is less than minimum";
} }
} }
buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE)); buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
/* Align the memory for a possible read from a raw device */ /* Align the memory for a possible read from a raw device */
@ -2468,6 +2439,11 @@ fil_read_first_page(
*space_id = fsp_header_get_space_id(page); *space_id = fsp_header_get_space_id(page);
*flags = fsp_header_get_flags(page); *flags = fsp_header_get_flags(page);
if (flushed_lsn) {
*flushed_lsn = mach_read_from_8(page +
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
}
if (!fsp_flags_is_valid(*flags)) { if (!fsp_flags_is_valid(*flags)) {
ulint cflags = fsp_flags_convert_from_101(*flags); ulint cflags = fsp_flags_convert_from_101(*flags);
if (cflags == ULINT_UNDEFINED) { if (cflags == ULINT_UNDEFINED) {
@ -2480,37 +2456,36 @@ fil_read_first_page(
} }
} }
if (!(IS_XTRABACKUP() && srv_backup_mode)) { if (!(IS_XTRABACKUP() && srv_backup_mode)) {
check_msg = fil_check_first_page(page, *space_id, *flags); check_msg = fil_check_first_page(page, *space_id, *flags);
} }
}
flushed_lsn = mach_read_from_8(page + /* Possible encryption crypt data is also stored only to first page
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); of the first datafile. */
ulint offset = fsp_header_get_crypt_offset(
fsp_flags_get_zip_size(*flags));
ulint space = fsp_header_get_space_id(page); cdata = fil_space_read_crypt_data(*space_id, page, offset);
ulint offset = fsp_header_get_crypt_offset(
fsp_flags_get_zip_size(*flags));
cdata = fil_space_read_crypt_data(space, page, offset); if (crypt_data) {
*crypt_data = cdata;
}
if (crypt_data) { /* If file space is encrypted we need to have at least some
*crypt_data = cdata; encryption service available where to get keys */
} if (cdata && cdata->should_encrypt()) {
/* If file space is encrypted we need to have at least some if (!encryption_key_id_exists(cdata->key_id)) {
encryption service available where to get keys */ ib_logf(IB_LOG_LEVEL_ERROR,
if (cdata && cdata->should_encrypt()) { "Tablespace id " ULINTPF
" is encrypted but encryption service"
if (!encryption_key_id_exists(cdata->key_id)) { " or used key_id %u is not available. "
ib_logf(IB_LOG_LEVEL_ERROR, "Can't continue opening tablespace.",
"Tablespace id %ld is encrypted but encryption service" *space_id, cdata->key_id);
" or used key_id %u is not available. Can't continue opening tablespace.",
space, cdata->key_id);
return ("table encrypted but encryption service not available.");
return ("table encrypted but encryption service not available.");
}
} }
} }
@ -2520,20 +2495,6 @@ fil_read_first_page(
return(check_msg); return(check_msg);
} }
if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
*max_flushed_lsn = flushed_lsn;
return(NULL);
}
if (*min_flushed_lsn > flushed_lsn) {
*min_flushed_lsn = flushed_lsn;
}
if (*max_flushed_lsn < flushed_lsn) {
*max_flushed_lsn = flushed_lsn;
}
return(NULL); return(NULL);
} }
@ -4377,6 +4338,7 @@ fil_open_single_table_tablespace(
def.file = os_file_create_simple_no_error_handling( def.file = os_file_create_simple_no_error_handling(
innodb_file_data_key, def.filepath, OS_FILE_OPEN, innodb_file_data_key, def.filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &def.success, atomic_writes); OS_FILE_READ_ONLY, &def.success, atomic_writes);
if (def.success) { if (def.success) {
tablespaces_found++; tablespaces_found++;
} }
@ -4391,8 +4353,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */ /* Read the first page of the datadir tablespace, if found. */
if (def.success) { if (def.success) {
def.check_msg = fil_read_first_page( def.check_msg = fil_read_first_page(
def.file, FALSE, &def.flags, &def.id, def.file, false, &def.flags, &def.id,
&def.lsn, &def.lsn, &def.crypt_data); NULL, &def.crypt_data);
if (table) { if (table) {
table->crypt_data = def.crypt_data; table->crypt_data = def.crypt_data;
@ -4401,6 +4363,7 @@ fil_open_single_table_tablespace(
def.valid = !def.check_msg && def.id == id def.valid = !def.check_msg && def.id == id
&& fsp_flags_match(flags, def.flags); && fsp_flags_match(flags, def.flags);
if (def.valid) { if (def.valid) {
valid_tablespaces_found++; valid_tablespaces_found++;
} else { } else {
@ -4414,8 +4377,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the remote tablespace */ /* Read the first page of the remote tablespace */
if (remote.success) { if (remote.success) {
remote.check_msg = fil_read_first_page( remote.check_msg = fil_read_first_page(
remote.file, FALSE, &remote.flags, &remote.id, remote.file, false, &remote.flags, &remote.id,
&remote.lsn, &remote.lsn, &remote.crypt_data); NULL, &remote.crypt_data);
if (table) { if (table) {
table->crypt_data = remote.crypt_data; table->crypt_data = remote.crypt_data;
@ -4425,6 +4388,7 @@ fil_open_single_table_tablespace(
/* Validate this single-table-tablespace with SYS_TABLES. */ /* Validate this single-table-tablespace with SYS_TABLES. */
remote.valid = !remote.check_msg && remote.id == id remote.valid = !remote.check_msg && remote.id == id
&& fsp_flags_match(flags, remote.flags); && fsp_flags_match(flags, remote.flags);
if (remote.valid) { if (remote.valid) {
valid_tablespaces_found++; valid_tablespaces_found++;
} else { } else {
@ -4439,8 +4403,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */ /* Read the first page of the datadir tablespace, if found. */
if (dict.success) { if (dict.success) {
dict.check_msg = fil_read_first_page( dict.check_msg = fil_read_first_page(
dict.file, FALSE, &dict.flags, &dict.id, dict.file, false, &dict.flags, &dict.id,
&dict.lsn, &dict.lsn, &dict.crypt_data); NULL, &dict.crypt_data);
if (table) { if (table) {
table->crypt_data = dict.crypt_data; table->crypt_data = dict.crypt_data;
@ -4472,14 +4436,16 @@ fil_open_single_table_tablespace(
"See " REFMAN "innodb-troubleshooting-datadict.html " "See " REFMAN "innodb-troubleshooting-datadict.html "
"for how to resolve the issue.", "for how to resolve the issue.",
tablename); tablename);
if (IS_XTRABACKUP() && fix_dict) { if (IS_XTRABACKUP() && fix_dict) {
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"It will be removed from the data dictionary."); "It will be removed from the data dictionary.");
if (purge_sys) { if (purge_sys) {
fil_remove_invalid_table_from_data_dict(tablename); fil_remove_invalid_table_from_data_dict(tablename);
} }
} }
err = DB_CORRUPTION; err = DB_CORRUPTION;
goto cleanup_and_exit; goto cleanup_and_exit;
@ -4491,26 +4457,32 @@ fil_open_single_table_tablespace(
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"A tablespace for %s has been found in " "A tablespace for %s has been found in "
"multiple places;", tablename); "multiple places;", tablename);
if (def.success) { if (def.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Default location; %s, LSN=" LSN_PF "Default location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
def.filepath, def.lsn, def.filepath,
(ulong) def.id, (ulong) def.flags); def.id,
def.flags);
} }
if (remote.success) { if (remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Remote location; %s, LSN=" LSN_PF "Remote location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
remote.filepath, remote.lsn, remote.filepath,
(ulong) remote.id, (ulong) remote.flags); remote.id,
remote.flags);
} }
if (dict.success) { if (dict.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Dictionary location; %s, LSN=" LSN_PF "Dictionary location; %s"
", Space ID=%lu, Flags=%lu", ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
dict.filepath, dict.lsn, dict.filepath,
(ulong) dict.id, (ulong) dict.flags); dict.id,
dict.flags);
} }
/* Force-recovery will allow some tablespaces to be /* Force-recovery will allow some tablespaces to be
@ -4543,6 +4515,7 @@ fil_open_single_table_tablespace(
os_file_close(def.file); os_file_close(def.file);
tablespaces_found--; tablespaces_found--;
} }
if (dict.success && !dict.valid) { if (dict.success && !dict.valid) {
dict.success = false; dict.success = false;
os_file_close(dict.file); os_file_close(dict.file);
@ -4895,8 +4868,8 @@ fil_validate_single_table_tablespace(
check_first_page: check_first_page:
fsp->success = TRUE; fsp->success = TRUE;
if (const char* check_msg = fil_read_first_page( if (const char* check_msg = fil_read_first_page(
fsp->file, FALSE, &fsp->flags, &fsp->id, fsp->file, false, &fsp->flags, &fsp->id,
&fsp->lsn, &fsp->lsn, &fsp->crypt_data)) { NULL, &fsp->crypt_data)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"%s in tablespace %s (table %s)", "%s in tablespace %s (table %s)",
check_msg, fsp->filepath, tablename); check_msg, fsp->filepath, tablename);
@ -4909,6 +4882,7 @@ check_first_page:
in Xtrabackup, this does not work.*/ in Xtrabackup, this does not work.*/
return; return;
} }
if (!restore_attempted) { if (!restore_attempted) {
if (!fil_user_tablespace_find_space_id(fsp)) { if (!fil_user_tablespace_find_space_id(fsp)) {
return; return;
@ -5152,11 +5126,11 @@ will_not_choose:
if (def.success && remote.success) { if (def.success && remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Tablespaces for %s have been found in two places;\n" "Tablespaces for %s have been found in two places;\n"
"Location 1: SpaceID: %lu LSN: %lu File: %s\n" "Location 1: SpaceID: " ULINTPF " File: %s\n"
"Location 2: SpaceID: %lu LSN: %lu File: %s\n" "Location 2: SpaceID: " ULINTPF " File: %s\n"
"You must delete one of them.", "You must delete one of them.",
tablename, (ulong) def.id, (ulong) def.lsn, tablename, def.id,
def.filepath, (ulong) remote.id, (ulong) remote.lsn, def.filepath, remote.id,
remote.filepath); remote.filepath);
def.success = FALSE; def.success = FALSE;

View file

@ -19238,8 +19238,15 @@ checkpoint_now_set(
log_make_checkpoint_at(LSN_MAX, TRUE); log_make_checkpoint_at(LSN_MAX, TRUE);
fil_flush_file_spaces(FIL_LOG); fil_flush_file_spaces(FIL_LOG);
} }
fil_write_flushed_lsn_to_data_files(log_sys->lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE); dberr_t err = fil_write_flushed_lsn(log_sys->lsn);
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Failed to write flush lsn to the "
"system tablespace at checkpoint err=%s",
ut_strerr(err));
}
} }
} }

View file

@ -212,7 +212,6 @@ struct fsp_open_info {
ibool valid; /*!< Is the tablespace valid? */ ibool valid; /*!< Is the tablespace valid? */
pfs_os_file_t file; /*!< File handle */ pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */ char* filepath; /*!< File path to open */
lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */ ulint id; /*!< Space ID */
ulint flags; /*!< Tablespace flags */ ulint flags; /*!< Tablespace flags */
ulint encryption_error; /*!< if an encryption error occurs */ ulint encryption_error; /*!< if an encryption error occurs */
@ -643,17 +642,17 @@ void
fil_set_max_space_id_if_bigger( fil_set_max_space_id_if_bigger(
/*===========================*/ /*===========================*/
ulint max_id);/*!< in: maximum known id */ ulint max_id);/*!< in: maximum known id */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/****************************************************************//**
Writes the flushed lsn and the latest archived log number to the page /** Write the flushed LSN to the page header of the first page in the
header of the first page of each data file in the system tablespace. system tablespace.
@return DB_SUCCESS or error number */ @param[in] lsn flushed LSN
UNIV_INTERN @return DB_SUCCESS or error number */
dberr_t dberr_t
fil_write_flushed_lsn_to_data_files( fil_write_flushed_lsn(
/*================================*/ lsn_t lsn)
lsn_t lsn, /*!< in: lsn to write */ MY_ATTRIBUTE((warn_unused_result));
ulint arch_log_no); /*!< in: latest archived log file number */
/** Acquire a tablespace when it could be dropped concurrently. /** Acquire a tablespace when it could be dropped concurrently.
Used by background threads that do not necessarily hold proper locks Used by background threads that do not necessarily hold proper locks
@ -799,28 +798,28 @@ private:
fil_space_t* m_space; fil_space_t* m_space;
}; };
/*******************************************************************//** /** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
Reads the flushed lsn, arch no, and tablespace flag fields from a data the first page of a first data file at database startup.
file at database startup. @param[in] data_file open data file
@param[in] one_read_only true if first datafile is already
read
@param[out] flags FSP_SPACE_FLAGS
@param[out] space_id tablepspace ID
@param[out] flushed_lsn flushed lsn value
@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set @retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */ @return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
const char* const char*
fil_read_first_page( fil_read_first_page(
/*================*/ pfs_os_file_t data_file,
pfs_os_file_t data_file, /*!< in: open data file */ ibool one_read_already,
ibool one_read_already, /*!< in: TRUE if min and max ulint* flags,
parameters below already ulint* space_id,
contain sensible data */ lsn_t* flushed_lsn,
ulint* flags, /*!< out: FSP_SPACE_FLAGS */ fil_space_crypt_t** crypt_data)
ulint* space_id, /*!< out: tablespace ID */ MY_ATTRIBUTE((warn_unused_result));
lsn_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
lsn_t* max_flushed_lsn, /*!< out: max of flushed
lsn values in data files */
fil_space_crypt_t** crypt_data) /*!< out: crypt data */
__attribute__((warn_unused_result));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/*******************************************************************//** /*******************************************************************//**
Parses the body of a log record written about an .ibd file operation. That is, Parses the body of a log record written about an .ibd file operation. That is,

View file

@ -137,26 +137,25 @@ a freshly read page)
*/ */
# define recv_recover_page(jri, block) recv_recover_page_func(block) # define recv_recover_page(jri, block) recv_recover_page_func(block)
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/********************************************************//**
Recovers from a checkpoint. When this function returns, the database is able /** Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
@param[in] limit_lsn recover up to this lsn if possible
@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
UNIV_INTERN UNIV_INTERN
dberr_t dberr_t
recv_recovery_from_checkpoint_start_func( recv_recovery_from_checkpoint_start_func(
/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint type, /*!< in: LOG_CHECKPOINT or ulint type,
LOG_ARCHIVE */ lsn_t limit_lsn,
lsn_t limit_lsn, /*!< in: recover up to this lsn
if possible */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t min_flushed_lsn,/*!< in: min flushed lsn from lsn_t flushed_lsn)
data files */ MY_ATTRIBUTE((warn_unused_result));
lsn_t max_flushed_lsn);/*!< in: max flushed lsn from
data files */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
/** Wrapper for recv_recovery_from_checkpoint_start_func(). /** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able Recovers from a checkpoint. When this function returns, the database is able
@ -165,11 +164,10 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param type in: LOG_CHECKPOINT or LOG_ARCHIVE @param type in: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim in: recover up to this log sequence number if possible @param lim in: recover up to this log sequence number if possible
@param min in: minimum flushed log sequence number from data files @param lsn in: flushed log sequence number from first data file
@param max in: maximum flushed log sequence number from data files
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \ # define recv_recovery_from_checkpoint_start(type,lim,lsn) \
recv_recovery_from_checkpoint_start_func(type,lim,min,max) recv_recovery_from_checkpoint_start_func(type,lim,lsn)
#else /* UNIV_LOG_ARCHIVE */ #else /* UNIV_LOG_ARCHIVE */
/** Wrapper for recv_recovery_from_checkpoint_start_func(). /** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able Recovers from a checkpoint. When this function returns, the database is able
@ -178,12 +176,12 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE @param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim ignored: recover up to this log sequence number if possible @param lim ignored: recover up to this log sequence number if possible
@param min in: minimum flushed log sequence number from data files @param lsn in: flushed log sequence number from first data file
@param max in: maximum flushed log sequence number from data files
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \ # define recv_recovery_from_checkpoint_start(type,lim,lsn) \
recv_recovery_from_checkpoint_start_func(min,max) recv_recovery_from_checkpoint_start_func(lsn)
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
/********************************************************//** /********************************************************//**
Completes recovery from a checkpoint. */ Completes recovery from a checkpoint. */
UNIV_INTERN UNIV_INTERN

View file

@ -3836,9 +3836,14 @@ wait_suspend_loop:
srv_shutdown_lsn = lsn; srv_shutdown_lsn = lsn;
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
fil_write_flushed_lsn_to_data_files(lsn, 0); dberr_t err = fil_write_flushed_lsn(lsn);
fil_flush_file_spaces(FIL_TABLESPACE); if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Failed to write flush lsn to the "
"system tablespace at shutdown err=%s",
ut_strerr(err));
}
} }
fil_close_all_files(); fil_close_all_files();

View file

@ -3019,22 +3019,22 @@ recv_init_crash_recovery(void)
} }
} }
/********************************************************//** /** Recovers from a checkpoint. When this function returns, the database is able
Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it. the recovery and free the resources used in it.
@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
@param[in] limit_lsn recover up to this lsn if possible
@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
UNIV_INTERN UNIV_INTERN
dberr_t dberr_t
recv_recovery_from_checkpoint_start_func( recv_recovery_from_checkpoint_start_func(
/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint type, /*!< in: LOG_CHECKPOINT or LOG_ARCHIVE */ ulint type,
lsn_t limit_lsn, /*!< in: recover up to this lsn if possible */ lsn_t limit_lsn,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t min_flushed_lsn,/*!< in: min flushed lsn from data files */ lsn_t flushed_lsn)
lsn_t max_flushed_lsn)/*!< in: max flushed lsn from data files */
{ {
log_group_t* group; log_group_t* group;
log_group_t* max_cp_group; log_group_t* max_cp_group;
@ -3262,6 +3262,7 @@ recv_recovery_from_checkpoint_start_func(
group = UT_LIST_GET_NEXT(log_groups, group); group = UT_LIST_GET_NEXT(log_groups, group);
} }
/* Done with startup scan. Clear the flag. */ /* Done with startup scan. Clear the flag. */
recv_log_scan_is_startup_type = FALSE; recv_log_scan_is_startup_type = FALSE;
@ -3274,10 +3275,9 @@ recv_recovery_from_checkpoint_start_func(
there is something wrong we will print a message to the there is something wrong we will print a message to the
user about recovery: */ user about recovery: */
if (checkpoint_lsn != max_flushed_lsn if (checkpoint_lsn != flushed_lsn) {
|| checkpoint_lsn != min_flushed_lsn) {
if (checkpoint_lsn < max_flushed_lsn) { if (checkpoint_lsn <flushed_lsn) {
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"The log sequence number " "The log sequence number "
@ -3288,24 +3288,21 @@ recv_recovery_from_checkpoint_start_func(
"ib_logfiles to start up the database. " "ib_logfiles to start up the database. "
"Log sequence number in the " "Log sequence number in the "
"ib_logfiles is " LSN_PF ", log" "ib_logfiles is " LSN_PF ", log"
"sequence numbers stamped " "sequence number stamped "
"to ibdata file headers are between " "to ibdata file header is " LSN_PF ".",
"" LSN_PF " and " LSN_PF ".",
checkpoint_lsn, checkpoint_lsn,
min_flushed_lsn, flushed_lsn);
max_flushed_lsn);
} }
if (!recv_needed_recovery) { if (!recv_needed_recovery) {
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"The log sequence numbers " "The log sequence number "
LSN_PF " and " LSN_PF LSN_PF
" in ibdata files do not match" " in ibdata file do not match"
" the log sequence number " " the log sequence number "
LSN_PF LSN_PF
" in the ib_logfiles!", " in the ib_logfiles!",
min_flushed_lsn, flushed_lsn,
max_flushed_lsn,
checkpoint_lsn); checkpoint_lsn);
if (!srv_read_only_mode) { if (!srv_read_only_mode) {

View file

@ -826,32 +826,32 @@ open_log_file(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/*********************************************************************//**
Creates or opens database data files and closes them. /** Creates or opens database data files and closes them.
@param[out] create_new_db true = create new database
@param[out] min_arch_log_no min of archived log numbers in
data files
@param[out] max_arch_log_no max of archived log numbers in
data files
@param[out] flushed_lsn flushed lsn in fist datafile
@param[out] sum_of_new_sizes sum of sizes of the new files
added
@return DB_SUCCESS or error code */ @return DB_SUCCESS or error code */
MY_ATTRIBUTE((nonnull, warn_unused_result)) MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dberr_t
open_or_create_data_files( open_or_create_data_files(
/*======================*/ bool* create_new_db,
ibool* create_new_db, /*!< out: TRUE if new database should be
created */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
lsn_t* min_arch_log_no,/*!< out: min of archived log lsn_t* min_arch_log_no,
numbers in data files */ lsn_t* max_arch_log_no,
lsn_t* max_arch_log_no,/*!< out: max of archived log
numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
lsn_t* min_flushed_lsn,/*!< out: min of flushed lsn lsn_t* flushed_lsn,
values in data files */ ulint* sum_of_new_sizes)
lsn_t* max_flushed_lsn,/*!< out: max of flushed lsn
values in data files */
ulint* sum_of_new_sizes)/*!< out: sum of sizes of the
new files added */
{ {
ibool ret; ibool ret;
ulint i; ulint i;
ibool one_opened = FALSE; bool one_opened = false;
ibool one_created = FALSE; bool one_created = false;
os_offset_t size; os_offset_t size;
ulint flags; ulint flags;
ulint space; ulint space;
@ -870,7 +870,7 @@ open_or_create_data_files(
*sum_of_new_sizes = 0; *sum_of_new_sizes = 0;
*create_new_db = FALSE; *create_new_db = false;
srv_normalize_path_for_win(srv_data_home); srv_normalize_path_for_win(srv_data_home);
@ -958,9 +958,10 @@ open_or_create_data_files(
} }
const char* check_msg; const char* check_msg;
check_msg = fil_read_first_page( check_msg = fil_read_first_page(
files[i], FALSE, &flags, &space, files[i], FALSE, &flags, &space,
min_flushed_lsn, max_flushed_lsn, NULL); flushed_lsn, NULL);
/* If first page is valid, don't overwrite DB. /* If first page is valid, don't overwrite DB.
It prevents overwriting DB when mysql_install_db It prevents overwriting DB when mysql_install_db
@ -991,6 +992,7 @@ open_or_create_data_files(
name); name);
return(DB_ERROR); return(DB_ERROR);
} }
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
ut_a(!srv_read_only_mode); ut_a(!srv_read_only_mode);
files[i] = os_file_create( files[i] = os_file_create(
@ -1010,7 +1012,6 @@ open_or_create_data_files(
} }
if (!ret) { if (!ret) {
os_file_get_last_error(true); os_file_get_last_error(true);
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
@ -1020,7 +1021,6 @@ open_or_create_data_files(
} }
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
goto skip_size_check; goto skip_size_check;
} }
@ -1047,16 +1047,15 @@ size_check:
"auto-extending " "auto-extending "
"data file %s is " "data file %s is "
"of a different size " "of a different size "
"%lu pages (rounded " ULINTPF " pages (rounded "
"down to MB) than specified " "down to MB) than specified "
"in the .cnf file: " "in the .cnf file: "
"initial %lu pages, " "initial " ULINTPF " pages, "
"max %lu (relevant if " "max " ULINTPF " (relevant if "
"non-zero) pages!", "non-zero) pages!",
name, name,
(ulong) rounded_size_pages, rounded_size_pages,
(ulong) srv_data_file_sizes[i], srv_data_file_sizes[i],
(ulong)
srv_last_file_size_max); srv_last_file_size_max);
return(DB_ERROR); return(DB_ERROR);
@ -1069,12 +1068,12 @@ size_check:
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Data file %s is of a different " "Data file %s is of a different "
"size %lu pages (rounded down to MB) " "size " ULINTPF " pages (rounded down to MB) "
"than specified in the .cnf file " "than specified in the .cnf file "
"%lu pages!", ULINTPF " pages!",
name, name,
(ulong) rounded_size_pages, rounded_size_pages,
(ulong) srv_data_file_sizes[i]); srv_data_file_sizes[i]);
return(DB_ERROR); return(DB_ERROR);
} }
@ -1093,7 +1092,7 @@ skip_size_check:
check_first_page: check_first_page:
check_msg = fil_read_first_page( check_msg = fil_read_first_page(
files[i], one_opened, &flags, &space, files[i], one_opened, &flags, &space,
min_flushed_lsn, max_flushed_lsn, &crypt_data); flushed_lsn, &crypt_data);
if (check_msg) { if (check_msg) {
@ -1130,9 +1129,9 @@ check_first_page:
!= fsp_flags_get_page_size(flags)) { != fsp_flags_get_page_size(flags)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Data file \"%s\" uses page size %lu," "Data file \"%s\" uses page size " ULINTPF " ,"
"but the start-up parameter " "but the start-up parameter "
"is --innodb-page-size=%lu", "is --innodb-page-size=" ULINTPF " .",
name, name,
fsp_flags_get_page_size(flags), fsp_flags_get_page_size(flags),
UNIV_PAGE_SIZE); UNIV_PAGE_SIZE);
@ -1163,9 +1162,9 @@ check_first_page:
} }
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"Setting file %s size to %lu MB", "Setting file %s size to " ULINTPF " MB",
name, name,
(ulong) (srv_data_file_sizes[i] (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT))); >> (20 - UNIV_PAGE_SIZE_SHIFT)));
ret = os_file_set_size( ret = os_file_set_size(
@ -1655,9 +1654,8 @@ dberr_t
innobase_start_or_create_for_mysql(void) innobase_start_or_create_for_mysql(void)
/*====================================*/ /*====================================*/
{ {
ibool create_new_db; bool create_new_db;
lsn_t min_flushed_lsn; lsn_t flushed_lsn;
lsn_t max_flushed_lsn;
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
lsn_t min_arch_log_no = LSN_MAX; lsn_t min_arch_log_no = LSN_MAX;
lsn_t max_arch_log_no = LSN_MAX; lsn_t max_arch_log_no = LSN_MAX;
@ -2237,7 +2235,7 @@ innobase_start_or_create_for_mysql(void)
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
&min_arch_log_no, &max_arch_log_no, &min_arch_log_no, &max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
&min_flushed_lsn, &max_flushed_lsn, &flushed_lsn,
&sum_of_new_sizes); &sum_of_new_sizes);
if (err == DB_FAIL) { if (err == DB_FAIL) {
@ -2281,12 +2279,12 @@ innobase_start_or_create_for_mysql(void)
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success); ut_a(success);
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
err = create_log_files(create_new_db, logfilename, dirnamelen, err = create_log_files(create_new_db, logfilename, dirnamelen,
max_flushed_lsn, logfile0); flushed_lsn, logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@ -2306,19 +2304,8 @@ innobase_start_or_create_for_mysql(void)
if (err == DB_NOT_FOUND) { if (err == DB_NOT_FOUND) {
if (i == 0) { if (i == 0) {
if (max_flushed_lsn
!= min_flushed_lsn) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot create"
" log files because"
" data files are"
" corrupt or"
" not in sync"
" with each other");
return(DB_ERROR);
}
if (max_flushed_lsn < (lsn_t) 1000) { if (flushed_lsn < (lsn_t) 1000) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot create" "Cannot create"
" log files because" " log files because"
@ -2333,14 +2320,14 @@ innobase_start_or_create_for_mysql(void)
err = create_log_files( err = create_log_files(
create_new_db, logfilename, create_new_db, logfilename,
dirnamelen, max_flushed_lsn, dirnamelen, flushed_lsn,
logfile0); logfile0);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
err = create_log_files_rename( err = create_log_files_rename(
logfilename, logfilename,
dirnamelen, dirnamelen,
max_flushed_lsn, flushed_lsn,
logfile0); logfile0);
} }
@ -2350,8 +2337,7 @@ innobase_start_or_create_for_mysql(void)
/* Suppress the message about /* Suppress the message about
crash recovery. */ crash recovery. */
max_flushed_lsn = min_flushed_lsn flushed_lsn = log_get_lsn();
= log_get_lsn();
goto files_checked; goto files_checked;
} else if (i < 2 && !IS_XTRABACKUP()) { } else if (i < 2 && !IS_XTRABACKUP()) {
/* must have at least 2 log files */ /* must have at least 2 log files */
@ -2509,17 +2495,19 @@ files_checked:
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success); ut_a(success);
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
/* Stamp the LSN to the data files. */ /* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files(max_flushed_lsn, 0); err = fil_write_flushed_lsn(flushed_lsn);
fil_flush_file_spaces(FIL_TABLESPACE); if (err != DB_SUCCESS) {
return(err);
}
err = create_log_files_rename(logfilename, dirnamelen, err = create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0); flushed_lsn, logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@ -2574,7 +2562,7 @@ files_checked:
err = recv_recovery_from_checkpoint_start( err = recv_recovery_from_checkpoint_start(
LOG_CHECKPOINT, LSN_MAX, LOG_CHECKPOINT, LSN_MAX,
min_flushed_lsn, max_flushed_lsn); flushed_lsn);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@ -2757,7 +2745,7 @@ files_checked:
DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_EXECUTE_IF("innodb_log_abort_1",
return(DB_ERROR);); return(DB_ERROR););
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"Resizing redo log from %u*%u to %u*%u pages" "Resizing redo log from %u*%u to %u*%u pages"
@ -2766,7 +2754,7 @@ files_checked:
(unsigned) srv_log_file_size, (unsigned) srv_log_file_size,
(unsigned) srv_n_log_files, (unsigned) srv_n_log_files,
(unsigned) srv_log_file_size_requested, (unsigned) srv_log_file_size_requested,
max_flushed_lsn); flushed_lsn);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
@ -2776,7 +2764,7 @@ files_checked:
we need to explicitly flush the log buffers. */ we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID); fil_flush(SRV_LOG_SPACE_FIRST_ID);
ut_ad(max_flushed_lsn == log_get_lsn()); ut_ad(flushed_lsn == log_get_lsn());
/* Prohibit redo log writes from any other /* Prohibit redo log writes from any other
threads until creating a log checkpoint at the threads until creating a log checkpoint at the
@ -2788,8 +2776,7 @@ files_checked:
return(DB_ERROR);); return(DB_ERROR););
/* Stamp the LSN to the data files. */ /* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files( err = fil_write_flushed_lsn(flushed_lsn);
max_flushed_lsn, 0);
DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
@ -2797,8 +2784,6 @@ files_checked:
return(err); return(err);
} }
fil_flush_file_spaces(FIL_TABLESPACE);
/* Close and free the redo log files, so that /* Close and free the redo log files, so that
we can replace them. */ we can replace them. */
fil_close_log_files(true); fil_close_log_files(true);
@ -2815,7 +2800,7 @@ files_checked:
srv_log_file_size = srv_log_file_size_requested; srv_log_file_size = srv_log_file_size_requested;
err = create_log_files(create_new_db, logfilename, err = create_log_files(create_new_db, logfilename,
dirnamelen, max_flushed_lsn, dirnamelen, flushed_lsn,
logfile0); logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
@ -2824,12 +2809,17 @@ files_checked:
/* create_log_files() can increase system lsn that is /* create_log_files() can increase system lsn that is
why FIL_PAGE_FILE_FLUSH_LSN have to be updated */ why FIL_PAGE_FILE_FLUSH_LSN have to be updated */
min_flushed_lsn = max_flushed_lsn = log_get_lsn(); flushed_lsn = log_get_lsn();
fil_write_flushed_lsn_to_data_files(min_flushed_lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE); err = fil_write_flushed_lsn(flushed_lsn);
if (err != DB_SUCCESS) {
return(err);
}
err = create_log_files_rename(logfilename, dirnamelen, err = create_log_files_rename(logfilename, dirnamelen,
log_get_lsn(), logfile0); log_get_lsn(), logfile0);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
} }