diff --git a/mysql-test/suite/innodb/r/instant_alter_import.result b/mysql-test/suite/innodb/r/instant_alter_import.result index 9a20ed606bd..55a49e81057 100644 --- a/mysql-test/suite/innodb/r/instant_alter_import.result +++ b/mysql-test/suite/innodb/r/instant_alter_import.result @@ -61,6 +61,7 @@ alter table t1 discard tablespace; flush tables t2 for export; unlock tables; alter table t1 import tablespace; +# restart select * from t1; z 42 diff --git a/mysql-test/suite/innodb/t/instant_alter_import.test b/mysql-test/suite/innodb/t/instant_alter_import.test index 7bd5645436c..50eda83f4b0 100644 --- a/mysql-test/suite/innodb/t/instant_alter_import.test +++ b/mysql-test/suite/innodb/t/instant_alter_import.test @@ -79,6 +79,7 @@ flush tables t2 for export; unlock tables; alter table t1 import tablespace; +--source include/restart_mysqld.inc select * from t1; drop table t2; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index a029873da90..b47333113aa 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -252,13 +252,13 @@ public: } /** Position the cursor on the first user record. */ - void open(buf_block_t* block) UNIV_NOTHROW + rec_t* open(buf_block_t* block, const dict_index_t* index) noexcept + MY_ATTRIBUTE((warn_unused_result)) { + m_cur.index = const_cast(index); page_cur_set_before_first(block, &m_cur); - - if (!end()) { - next(); - } + next(); + return page_cur_get_rec(&m_cur); } /** Move to the next record. */ @@ -1848,12 +1848,39 @@ PageConverter::update_records( bool clust_index = m_index->m_srv_index == m_cluster_index; /* This will also position the cursor on the first user record. */ + rec_t* rec = m_rec_iter.open(block, m_index->m_srv_index); - m_rec_iter.open(block); + if (!rec) { + return DB_CORRUPTION; + } + + ulint deleted; + + if (!page_has_prev(block->frame) + && m_index->m_srv_index->is_instant()) { + /* Expect to find the hidden metadata record */ + if (page_rec_is_supremum(rec)) { + return DB_CORRUPTION; + } + + const ulint info_bits = rec_get_info_bits(rec, comp); + + if (!(info_bits & REC_INFO_MIN_REC_FLAG)) { + return DB_CORRUPTION; + } + + if (!(info_bits & REC_INFO_DELETED_FLAG) + != !m_index->m_srv_index->table->instant) { + return DB_CORRUPTION; + } + + deleted = 0; + goto first; + } while (!m_rec_iter.end()) { - rec_t* rec = m_rec_iter.current(); - ibool deleted = rec_get_deleted_flag(rec, comp); + rec = m_rec_iter.current(); + deleted = rec_get_deleted_flag(rec, comp); /* For the clustered index we have to adjust the BLOB reference and the system fields irrespective of the @@ -1861,6 +1888,7 @@ PageConverter::update_records( cluster records is required for purge to work later. */ if (deleted || clust_index) { +first: m_offsets = rec_get_offsets( rec, m_index->m_srv_index, m_offsets, m_index->m_srv_index->n_core_fields, @@ -3158,7 +3186,7 @@ static size_t get_buf_size() ; } -/* find, parse instant metadata, performing variaous checks, +/* find, parse instant metadata, performing various checks, and apply it to dict_table_t @return DB_SUCCESS or some error */ static dberr_t handle_instant_metadata(dict_table_t *table,