Commit 7532976d authored by unknown's avatar unknown

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.
parent 8bb893f5
...@@ -911,6 +911,11 @@ dict_index_find_on_id_low( ...@@ -911,6 +911,11 @@ dict_index_find_on_id_low(
dict_table_t* table; dict_table_t* table;
dict_index_t* index; 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); table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) { while (table) {
......
...@@ -1803,36 +1803,44 @@ fil_write_flushed_lsn_to_data_files( ...@@ -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 Reads the flushed lsn, arch no, and tablespace flag fields from a data
startup. */ file at database startup. */
UNIV_INTERN UNIV_INTERN
void void
fil_read_flushed_lsn_and_arch_log_no( fil_read_first_page(
/*=================================*/ /*================*/
os_file_t data_file, /*!< in: open data file */ os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max ibool one_read_already, /*!< in: TRUE if min and max
parameters below already parameters below already
contain sensible data */ contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */ ulint* min_arch_log_no, /*!< out: min of archived
ulint* max_arch_log_no, /*!< in/out: */ log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */ ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
ib_uint64_t* max_flushed_lsn) /*!< in/out: */ lsn values in data files */
ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
lsn values in data files */
{ {
byte* buf; byte* buf;
byte* buf2; page_t* page;
ib_uint64_t flushed_lsn; 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 */ /* 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) { if (!one_read_already) {
*min_flushed_lsn = flushed_lsn; *min_flushed_lsn = flushed_lsn;
......
/***************************************************************************** /*****************************************************************************
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 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 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 ...@@ -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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
...@@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri ...@@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri
#include "dict0mem.h" #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 /* FILE SEGMENT INODE
================== ==================
......
...@@ -328,18 +328,23 @@ Reads the flushed lsn and arch no fields from a data file at database ...@@ -328,18 +328,23 @@ Reads the flushed lsn and arch no fields from a data file at database
startup. */ startup. */
UNIV_INTERN UNIV_INTERN
void void
fil_read_flushed_lsn_and_arch_log_no( fil_read_first_page(
/*=================================*/ /*================*/
os_file_t data_file, /*!< in: open data file */ os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max ibool one_read_already, /*!< in: TRUE if min and max
parameters below already parameters below already
contain sensible data */ contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */ ulint* min_arch_log_no, /*!< out: min of archived
ulint* max_arch_log_no, /*!< in/out: */ log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */ ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
ib_uint64_t* max_flushed_lsn); /*!< in/out: */ 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 Increments the count of pending insert buffer page merges, if space is not
being deleted. being deleted.
......
/***************************************************************************** /*****************************************************************************
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 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 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 ...@@ -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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
...@@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri ...@@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri
#include "page0types.h" #include "page0types.h"
#include "fsp0types.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. */ Initializes the file space system. */
UNIV_INTERN UNIV_INTERN
...@@ -352,6 +436,18 @@ fseg_print( ...@@ -352,6 +436,18 @@ fseg_print(
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
#endif /* UNIV_BTR_PRINT */ #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 #ifndef UNIV_NONINL
#include "fsp0fsp.ic" #include "fsp0fsp.ic"
#endif #endif
......
/***************************************************************************** /*****************************************************************************
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 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 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 ...@@ -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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
...@@ -43,3 +43,31 @@ fsp_descr_page( ...@@ -43,3 +43,31 @@ fsp_descr_page(
return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET)); 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( ...@@ -733,6 +733,7 @@ open_or_create_data_files(
ibool one_created = FALSE; ibool one_created = FALSE;
ulint size; ulint size;
ulint size_high; ulint size_high;
ulint flags;
ulint rounded_size_pages; ulint rounded_size_pages;
char name[10000]; char name[10000];
...@@ -914,12 +915,31 @@ open_or_create_data_files( ...@@ -914,12 +915,31 @@ open_or_create_data_files(
return(DB_ERROR); return(DB_ERROR);
} }
skip_size_check: skip_size_check:
fil_read_flushed_lsn_and_arch_log_no( fil_read_first_page(
files[i], one_opened, files[i], one_opened, &flags,
#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); 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; one_opened = TRUE;
} else { } else {
/* We created the data file and now write it full of /* We created the data file and now write it full of
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment