Commit d8249775 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-33512 Corrupted table after IMPORT TABLESPACE and restart

In commit d74d9596 (MDEV-18543)
there was an error that would cause the hidden metadata record
to be deleted, and therefore cause the table to appear corrupted
when it is reloaded into the data dictionary cache.

PageConverter::update_records(): Do not delete the metadata record,
but do validate it.

RecIterator::open(): Make the API more similar to 10.6, to simplify
merges.
parent 662bb176
......@@ -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
......
......@@ -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;
......
......@@ -252,13 +252,13 @@ class RecIterator {
}
/** 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<dict_index_t*>(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);
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;
}
m_rec_iter.open(block);
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,
......
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