Bug #13116225 LIVE DOWNGRADE CRASHES WITH INNODB_PAGE_SIZE=4K
This bug ensures that a live downgrade from an InnoDB 5.6 with WL5756 and a database created with innodb-page-size=8k or 4k will make a version 5.5 installation politely refuse to start. Instead of crashing or giving some indication about a corrupted database, it will indicate the page size difference. This patch takes only that part of the Wl5756 patch that is needed to protect against opening a tablespace that is stamped with a different page size. It also contains the change in dict_index_find_on_id_low() just in case a database with another page size is created by recompiling a pre-WL5756 InnoDB.
This commit is contained in:
parent
dbe70b9fd6
commit
ab7a8ceb31
@ -911,6 +911,11 @@ dict_index_find_on_id_low(
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
|
||||
/* This can happen if the system tablespace is the wrong page size */
|
||||
if (dict_sys == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
|
||||
|
||||
while (table) {
|
||||
|
@ -1803,36 +1803,44 @@ fil_write_flushed_lsn_to_data_files(
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Reads the flushed lsn and arch no fields from a data file at database
|
||||
startup. */
|
||||
Reads the flushed lsn, arch no, and tablespace flag fields from a data
|
||||
file at database startup. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_read_flushed_lsn_and_arch_log_no(
|
||||
/*=================================*/
|
||||
fil_read_first_page(
|
||||
/*================*/
|
||||
os_file_t data_file, /*!< in: open data file */
|
||||
ibool one_read_already, /*!< in: TRUE if min and max
|
||||
parameters below already
|
||||
contain sensible data */
|
||||
ulint* flags, /*!< out: tablespace flags */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
ulint* min_arch_log_no, /*!< in/out: */
|
||||
ulint* max_arch_log_no, /*!< in/out: */
|
||||
ulint* min_arch_log_no, /*!< out: min of archived
|
||||
log numbers in data files */
|
||||
ulint* max_arch_log_no, /*!< out: max of archived
|
||||
log numbers in data files */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
|
||||
ib_uint64_t* max_flushed_lsn) /*!< in/out: */
|
||||
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
|
||||
lsn values in data files */
|
||||
ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
|
||||
lsn values in data files */
|
||||
{
|
||||
byte* buf;
|
||||
byte* buf2;
|
||||
page_t* page;
|
||||
ib_uint64_t flushed_lsn;
|
||||
|
||||
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
|
||||
buf = ut_malloc(2 * UNIV_PAGE_SIZE);
|
||||
/* Align the memory for a possible read from a raw device */
|
||||
buf = ut_align(buf2, UNIV_PAGE_SIZE);
|
||||
page = ut_align(buf, UNIV_PAGE_SIZE);
|
||||
|
||||
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
|
||||
os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE);
|
||||
|
||||
flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
|
||||
*flags = mach_read_from_4(page +
|
||||
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
|
||||
|
||||
ut_free(buf2);
|
||||
flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
|
||||
|
||||
ut_free(buf);
|
||||
|
||||
if (!one_read_already) {
|
||||
*min_flushed_lsn = flushed_lsn;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri
|
||||
#include "dict0mem.h"
|
||||
|
||||
|
||||
#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
|
||||
within a file page */
|
||||
|
||||
/* The data structures in files are defined just as byte strings in C */
|
||||
typedef byte fsp_header_t;
|
||||
typedef byte xdes_t;
|
||||
|
||||
/* SPACE HEADER
|
||||
============
|
||||
|
||||
File space header data structure: this data structure is contained in the
|
||||
first page of a space. The space for this header is reserved in every extent
|
||||
descriptor page, but used only in the first. */
|
||||
|
||||
/*-------------------------------------*/
|
||||
#define FSP_SPACE_ID 0 /* space id */
|
||||
#define FSP_NOT_USED 4 /* this field contained a value up to
|
||||
which we know that the modifications
|
||||
in the database have been flushed to
|
||||
the file space; not used now */
|
||||
#define FSP_SIZE 8 /* Current size of the space in
|
||||
pages */
|
||||
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
|
||||
free list has not been initialized:
|
||||
the pages >= this limit are, by
|
||||
definition, free; note that in a
|
||||
single-table tablespace where size
|
||||
< 64 pages, this number is 64, i.e.,
|
||||
we have initialized the space
|
||||
about the first extent, but have not
|
||||
physically allocted those pages to the
|
||||
file */
|
||||
#define FSP_SPACE_FLAGS 16 /* table->flags & ~DICT_TF_COMPACT */
|
||||
#define FSP_FRAG_N_USED 20 /* number of used pages in the
|
||||
FSP_FREE_FRAG list */
|
||||
#define FSP_FREE 24 /* list of free extents */
|
||||
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
|
||||
/* list of partially free extents not
|
||||
belonging to any segment */
|
||||
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
|
||||
/* list of full extents not belonging
|
||||
to any segment */
|
||||
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* 8 bytes which give the first unused
|
||||
segment id */
|
||||
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where all the segment inode
|
||||
slots are reserved */
|
||||
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where not all the segment
|
||||
header slots are reserved */
|
||||
/*-------------------------------------*/
|
||||
/* File space header size */
|
||||
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
|
||||
|
||||
#define FSP_FREE_ADD 4 /* this many free extents are added
|
||||
to the free list from above
|
||||
FSP_FREE_LIMIT at a time */
|
||||
|
||||
/* FILE SEGMENT INODE
|
||||
==================
|
||||
|
||||
|
@ -328,18 +328,23 @@ Reads the flushed lsn and arch no fields from a data file at database
|
||||
startup. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_read_flushed_lsn_and_arch_log_no(
|
||||
/*=================================*/
|
||||
fil_read_first_page(
|
||||
/*================*/
|
||||
os_file_t data_file, /*!< in: open data file */
|
||||
ibool one_read_already, /*!< in: TRUE if min and max
|
||||
parameters below already
|
||||
contain sensible data */
|
||||
ulint* flags, /*!< out: tablespace flags */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
ulint* min_arch_log_no, /*!< in/out: */
|
||||
ulint* max_arch_log_no, /*!< in/out: */
|
||||
ulint* min_arch_log_no, /*!< out: min of archived
|
||||
log numbers in data files */
|
||||
ulint* max_arch_log_no, /*!< out: max of archived
|
||||
log numbers in data files */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
|
||||
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
|
||||
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
|
||||
lsn values in data files */
|
||||
ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed
|
||||
lsn values in data files */
|
||||
/*******************************************************************//**
|
||||
Increments the count of pending insert buffer page merges, if space is not
|
||||
being deleted.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri
|
||||
#include "page0types.h"
|
||||
#include "fsp0types.h"
|
||||
|
||||
/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
|
||||
|
||||
/** Number of flag bits used to indicate the tablespace page size */
|
||||
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
|
||||
/** Zero relative shift position of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_POS_PAGE_SSIZE 6
|
||||
/** Bit mask of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_MASK_PAGE_SSIZE \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
|
||||
<< FSP_FLAGS_POS_PAGE_SSIZE)
|
||||
/** Return the value of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
|
||||
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
|
||||
>> FSP_FLAGS_POS_PAGE_SSIZE)
|
||||
|
||||
/* @} */
|
||||
|
||||
/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
|
||||
|
||||
/** Offset of the space header within a file page */
|
||||
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
|
||||
|
||||
/* The data structures in files are defined just as byte strings in C */
|
||||
typedef byte fsp_header_t;
|
||||
typedef byte xdes_t;
|
||||
|
||||
/* SPACE HEADER
|
||||
============
|
||||
|
||||
File space header data structure: this data structure is contained in the
|
||||
first page of a space. The space for this header is reserved in every extent
|
||||
descriptor page, but used only in the first. */
|
||||
|
||||
/*-------------------------------------*/
|
||||
#define FSP_SPACE_ID 0 /* space id */
|
||||
#define FSP_NOT_USED 4 /* this field contained a value up to
|
||||
which we know that the modifications
|
||||
in the database have been flushed to
|
||||
the file space; not used now */
|
||||
#define FSP_SIZE 8 /* Current size of the space in
|
||||
pages */
|
||||
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
|
||||
free list has not been initialized:
|
||||
the pages >= this limit are, by
|
||||
definition, free; note that in a
|
||||
single-table tablespace where size
|
||||
< 64 pages, this number is 64, i.e.,
|
||||
we have initialized the space
|
||||
about the first extent, but have not
|
||||
physically allocted those pages to the
|
||||
file */
|
||||
#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
|
||||
dict_table_t::flags */
|
||||
#define FSP_FRAG_N_USED 20 /* number of used pages in the
|
||||
FSP_FREE_FRAG list */
|
||||
#define FSP_FREE 24 /* list of free extents */
|
||||
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
|
||||
/* list of partially free extents not
|
||||
belonging to any segment */
|
||||
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
|
||||
/* list of full extents not belonging
|
||||
to any segment */
|
||||
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* 8 bytes which give the first unused
|
||||
segment id */
|
||||
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where all the segment inode
|
||||
slots are reserved */
|
||||
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where not all the segment
|
||||
header slots are reserved */
|
||||
/*-------------------------------------*/
|
||||
/* File space header size */
|
||||
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
|
||||
|
||||
#define FSP_FREE_ADD 4 /* this many free extents are added
|
||||
to the free list from above
|
||||
FSP_FREE_LIMIT at a time */
|
||||
/* @} */
|
||||
|
||||
/* @} */
|
||||
|
||||
/**********************************************************************//**
|
||||
Initializes the file space system. */
|
||||
UNIV_INTERN
|
||||
@ -352,6 +436,18 @@ fseg_print(
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#endif /* UNIV_BTR_PRINT */
|
||||
|
||||
/********************************************************************//**
|
||||
Extract the page size from tablespace flags.
|
||||
This feature, storing the page_ssize into the tablespace flags, is added
|
||||
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
|
||||
database is opened with this code branch.
|
||||
@return page size of the tablespace in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_page_size(
|
||||
/*====================*/
|
||||
ulint flags); /*!< in: tablespace flags */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fsp0fsp.ic"
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
@ -43,3 +43,31 @@ fsp_descr_page(
|
||||
|
||||
return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET));
|
||||
}
|
||||
/********************************************************************//**
|
||||
Extract the page size from tablespace flags.
|
||||
This feature, storing the page_ssize into the tablespace flags, is added
|
||||
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
|
||||
database is opened with this code branch.
|
||||
@return page size of the tablespace in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_page_size(
|
||||
/*====================*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
{
|
||||
ulint page_size = 0;
|
||||
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
|
||||
/* Convert from a 'log2 minus 9' to a page size in bytes. */
|
||||
if (UNIV_UNLIKELY(ssize)) {
|
||||
page_size = (512 << ssize);
|
||||
|
||||
ut_ad(page_size <= UNIV_PAGE_SIZE);
|
||||
} else {
|
||||
/* If the page size was not stored, then it is the
|
||||
original 16k. */
|
||||
page_size = UNIV_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return(page_size);
|
||||
}
|
||||
|
@ -733,6 +733,7 @@ open_or_create_data_files(
|
||||
ibool one_created = FALSE;
|
||||
ulint size;
|
||||
ulint size_high;
|
||||
ulint flags;
|
||||
ulint rounded_size_pages;
|
||||
char name[10000];
|
||||
|
||||
@ -914,12 +915,31 @@ open_or_create_data_files(
|
||||
return(DB_ERROR);
|
||||
}
|
||||
skip_size_check:
|
||||
fil_read_flushed_lsn_and_arch_log_no(
|
||||
files[i], one_opened,
|
||||
fil_read_first_page(
|
||||
files[i], one_opened, &flags,
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
min_arch_log_no, max_arch_log_no,
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
min_flushed_lsn, max_flushed_lsn);
|
||||
|
||||
if (UNIV_PAGE_SIZE
|
||||
!= fsp_flags_get_page_size(flags)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: data file %s"
|
||||
" uses page size %lu,\n",
|
||||
name,
|
||||
fsp_flags_get_page_size(flags));
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: but the only supported"
|
||||
" page size in this release is=%lu\n",
|
||||
(ulong) UNIV_PAGE_SIZE);
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
one_opened = TRUE;
|
||||
} else {
|
||||
/* We created the data file and now write it full of
|
||||
|
Loading…
x
Reference in New Issue
Block a user