diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result index 27909b57df8..4d748d6ebed 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result @@ -796,7 +796,7 @@ t1 CREATE TABLE `t1` ( DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 (c1 INT, c2 VARCHAR(1024), c3 BLOB) ENGINE = Innodb; INSERT IGNORE INTO test_wl5522.t1 VALUES -(100, REPEAT('Karanbir', 899), REPEAT('Ajeeth', 1200)); +(100, REPEAT('Karanbir', 899), REPEAT('Ajeeth', 2731)); Warnings: Warning 1265 Data truncated for column 'c2' at row 1 INSERT INTO test_wl5522.t1 SELECT * FROM test_wl5522.t1; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index 68c5d3000cb..6b6506e8481 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -1164,7 +1164,7 @@ DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 (c1 INT, c2 VARCHAR(1024), c3 BLOB) ENGINE = Innodb; INSERT IGNORE INTO test_wl5522.t1 VALUES - (100, REPEAT('Karanbir', 899), REPEAT('Ajeeth', 1200)); + (100, REPEAT('Karanbir', 899), REPEAT('Ajeeth', 2731)); INSERT INTO test_wl5522.t1 SELECT * FROM test_wl5522.t1; INSERT INTO test_wl5522.t1 SELECT * FROM test_wl5522.t1; diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index badd29273ff..f75d6d529a7 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1602,7 +1602,8 @@ btr_page_reorganize_low( /* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */ memcpy(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), temp_page + (PAGE_HEADER + PAGE_MAX_TRX_ID), 8); - /* PAGE_MAX_TRX_ID is unused in clustered index pages, + /* PAGE_MAX_TRX_ID is unused in clustered index pages + (other than the root where it is repurposed as PAGE_ROOT_AUTO_INC), non-leaf pages, and in temporary tables. It was always zero-initialized in page_create() in all InnoDB versions. PAGE_MAX_TRX_ID must be nonzero on dict_index_is_sec_or_ibuf() @@ -1983,6 +1984,36 @@ btr_root_raise_and_insert( index); } + if (dict_index_is_sec_or_ibuf(index)) { + /* In secondary indexes and the change buffer, + PAGE_MAX_TRX_ID can be reset on the root page, because + the field only matters on leaf pages, and the root no + longer is a leaf page. (Older versions of InnoDB did + set PAGE_MAX_TRX_ID on all secondary index pages.) */ + if (root_page_zip) { + page_zip_write_header( + root_page_zip, + PAGE_HEADER + PAGE_MAX_TRX_ID + + root, 0, mtr); + } else { + mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID + + root, 0, mtr); + } + } else { + /* PAGE_ROOT_AUTO_INC is only present in the clustered index + root page; on other clustered index pages, we want to reserve + the field PAGE_MAX_TRX_ID for future use. */ + if (new_page_zip) { + page_zip_write_header( + new_page_zip, + PAGE_HEADER + PAGE_MAX_TRX_ID + + new_page, 0, mtr); + } else { + mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID + + new_page, 0, mtr); + } + } + /* If this is a pessimistic insert which is actually done to perform a pessimistic update then we have stored the lock information of the record to be inserted on the infimum of the diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index b70a1952f97..6a44aa4b8d7 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -468,16 +468,6 @@ protected: return(DB_SUCCESS); } - /** - @return true if it is a root page */ - bool is_root_page(const page_t* page) const UNIV_NOTHROW - { - ut_ad(fil_page_index_page_check(page)); - - return(mach_read_from_4(page + FIL_PAGE_NEXT) == FIL_NULL - && mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL); - } - /** Check if the page is marked as free in the extent descriptor. @param page_no page number to check in the extent descriptor. @return true if the page is marked as free */ @@ -669,7 +659,7 @@ FetchIndexRootPages::operator() ( err = set_current_xdes(block->page.id.page_no(), page); } else if (fil_page_index_page_check(page) && !is_free(block->page.id.page_no()) - && is_root_page(page)) { + && page_is_root(page)) { index_id_t id = btr_page_get_index_id(page); @@ -1831,12 +1821,28 @@ PageConverter::update_index_page( btr_page_set_index_id( page, m_page_zip_ptr, m_index->m_srv_index->id, 0); - page_set_max_trx_id(block, m_page_zip_ptr, m_trx->id, 0); + if (dict_index_is_clust(m_index->m_srv_index)) { + if (page_is_root(page)) { + /* Preserve the PAGE_ROOT_AUTO_INC. */ + } else { + /* Clear PAGE_MAX_TRX_ID so that it can be + used for other purposes in the future. IMPORT + in MySQL 5.6, 5.7 and MariaDB 10.0 and 10.1 + would set the field to the transaction ID even + on clustered index pages. */ + page_set_max_trx_id(block, m_page_zip_ptr, 0, NULL); + } + } else { + /* Set PAGE_MAX_TRX_ID on secondary index leaf pages, + and clear it on non-leaf pages. */ + page_set_max_trx_id(block, m_page_zip_ptr, + page_is_leaf(page) ? m_trx->id : 0, NULL); + } - if (page_is_empty(block->frame)) { + if (page_is_empty(page)) { /* Only a root page can be empty. */ - if (!is_root_page(block->frame)) { + if (!page_is_root(page)) { // TODO: We should relax this and skip secondary // indexes. Mark them as corrupt because they can // always be rebuilt.