-
Marko Mäkelä authored
This is a regression from Bug#17345513 CHECKING FIL_PAGE_TYPE BREAKS COMPATIBILITY WITH OLD INNODB DATA FILES This affected a production environment where the data files were originally created with MySQL 5.0 or earlier. Originally, InnoDB only initialized FIL_PAGE_TYPE on two types of pages: #define FIL_PAGE_INDEX 17855 /*!< B-tree node */ #define FIL_PAGE_UNDO_LOG 2 /*!< Undo log page */ When files were allocated in the file system, the field was initialized to 0. When a page was initialized in the buffer pool, the field would be left uninitialized, reusing whatever value happened to be at that address (typically one of the 3 values). In the originally reported incident, page 32768 in the system tablespace is an allocation bitmap page, but the uninitialized FIL_PAGE_TYPE field on it happened to be FIL_PAGE_INDEX, which caused the flush-time check to fail. Our fix comprises the following parts: 1. Reset wrong page type on allocation bitmap pages and change buffer bitmap pages based on the page number, without checking the page contents and without writing redo log. #define FIL_PAGE_IBUF_BITMAP 5 /*!< Insert buffer bitmap */ #define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */ #define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */ 2. On database startup, reset the page types on the following pages in the system tablespace, writing redo log: #define FSP_IBUF_HEADER_PAGE_NO 3 // init to 6=FIL_PAGE_TYPE_SYS #define FSP_TRX_SYS_PAGE_NO 5 // init to 7=FIL_PAGE_TYPE_TRX_SYS #define FSP_FIRST_RSEG_PAGE_NO 6 // init to 6=FIL_PAGE_TYPE_SYS #define FSP_DICT_HDR_PAGE_NO 7 // init to 6=FIL_PAGE_TYPE_SYS 3. Whenever we modify other types of pages, we reset the FIL_PAGE_TYPE within the same mini-transaction, to one of the following values: #define FIL_PAGE_INODE 3 /*!< Index node */ #define FIL_PAGE_TYPE_SYS 6 /*!< System page */ #define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */ #define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */ Note: Some page types are initialized immediately after page allocation, and the pages are not modified further without changing the page type first. Nothing needs to be done for these page types, if the requirement is to have valid page type when we are writing back pages from the buffer pool to files. #define FIL_PAGE_IBUF_FREE_LIST 4 /*!< Insert buffer free list */ #define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ Because MySQL does not officially support upgrade following by a server crash, there should be no legitimate usage scenario where such pages with an incorrect page type would be written out as a result of applying redo log during crash recovery. BLOB pages created before MySQL 5.1 could carry any page type (including FIL_PAGE_INDEX), but this should not be an issue, because existing BLOB pages are never updated in place. The BLOB columns are always updated by copy-on-write, with a valid FIL_PAGE_TYPE. Note: InnoDB never modifies BLOB pages in place. If BLOB data is modified, entirely new pages will be initialized and rewritten. Thus, no logic is implemented to update FIL_PAGE_TYPE on BLOB pages. This means that even after this fix, subsequent versions of MySQL must be prepared to read BLOB pages that contain anything in FIL_PAGE_TYPE. RB: 8314 Reviewed-by:
Kevin Lewis <kevin.lewis@oracle.com> Reviewed-by:
Vasil Dimov <vasil.dimov@oracle.com> Reviewed-by:
Sunny Bains <sunny.bains@oracle.com>
Marko Mäkelä authoredThis is a regression from Bug#17345513 CHECKING FIL_PAGE_TYPE BREAKS COMPATIBILITY WITH OLD INNODB DATA FILES This affected a production environment where the data files were originally created with MySQL 5.0 or earlier. Originally, InnoDB only initialized FIL_PAGE_TYPE on two types of pages: #define FIL_PAGE_INDEX 17855 /*!< B-tree node */ #define FIL_PAGE_UNDO_LOG 2 /*!< Undo log page */ When files were allocated in the file system, the field was initialized to 0. When a page was initialized in the buffer pool, the field would be left uninitialized, reusing whatever value happened to be at that address (typically one of the 3 values). In the originally reported incident, page 32768 in the system tablespace is an allocation bitmap page, but the uninitialized FIL_PAGE_TYPE field on it happened to be FIL_PAGE_INDEX, which caused the flush-time check to fail. Our fix comprises the following parts: 1. Reset wrong page type on allocation bitmap pages and change buffer bitmap pages based on the page number, without checking the page contents and without writing redo log. #define FIL_PAGE_IBUF_BITMAP 5 /*!< Insert buffer bitmap */ #define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */ #define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */ 2. On database startup, reset the page types on the following pages in the system tablespace, writing redo log: #define FSP_IBUF_HEADER_PAGE_NO 3 // init to 6=FIL_PAGE_TYPE_SYS #define FSP_TRX_SYS_PAGE_NO 5 // init to 7=FIL_PAGE_TYPE_TRX_SYS #define FSP_FIRST_RSEG_PAGE_NO 6 // init to 6=FIL_PAGE_TYPE_SYS #define FSP_DICT_HDR_PAGE_NO 7 // init to 6=FIL_PAGE_TYPE_SYS 3. Whenever we modify other types of pages, we reset the FIL_PAGE_TYPE within the same mini-transaction, to one of the following values: #define FIL_PAGE_INODE 3 /*!< Index node */ #define FIL_PAGE_TYPE_SYS 6 /*!< System page */ #define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */ #define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */ Note: Some page types are initialized immediately after page allocation, and the pages are not modified further without changing the page type first. Nothing needs to be done for these page types, if the requirement is to have valid page type when we are writing back pages from the buffer pool to files. #define FIL_PAGE_IBUF_FREE_LIST 4 /*!< Insert buffer free list */ #define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ Because MySQL does not officially support upgrade following by a server crash, there should be no legitimate usage scenario where such pages with an incorrect page type would be written out as a result of applying redo log during crash recovery. BLOB pages created before MySQL 5.1 could carry any page type (including FIL_PAGE_INDEX), but this should not be an issue, because existing BLOB pages are never updated in place. The BLOB columns are always updated by copy-on-write, with a valid FIL_PAGE_TYPE. Note: InnoDB never modifies BLOB pages in place. If BLOB data is modified, entirely new pages will be initialized and rewritten. Thus, no logic is implemented to update FIL_PAGE_TYPE on BLOB pages. This means that even after this fix, subsequent versions of MySQL must be prepared to read BLOB pages that contain anything in FIL_PAGE_TYPE. RB: 8314 Reviewed-by:
Kevin Lewis <kevin.lewis@oracle.com> Reviewed-by:
Vasil Dimov <vasil.dimov@oracle.com> Reviewed-by:
Sunny Bains <sunny.bains@oracle.com>
Loading