diff options
author | Eugene Kosov <eugene.kosov@mariadb.com> | 2020-08-04 10:13:35 +0300 |
---|---|---|
committer | Eugene Kosov <claprix@yandex.ru> | 2020-08-15 23:05:09 +0300 |
commit | 90c8d773ed0ea7de5e735e836e1e33a190711f17 (patch) | |
tree | 597f3e9ea756c85b5371aba24e0226807a2291d8 | |
parent | b811c6ecc74cc1421eedc92573447768d1eb7980 (diff) | |
download | mariadb-git-90c8d773ed0ea7de5e735e836e1e33a190711f17.tar.gz |
MDEV-21251 CHECK TABLE fails to check info_bits of records
btr_validate_index(): do not stop checking after some level failed.
That way it'll become possible to see errors in leaf pages even when
uppers layers are corrupted too.
page_validate(): check info_bits and status_bits more
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 1 | ||||
-rw-r--r-- | storage/innobase/page/page0page.cc | 57 |
2 files changed, 51 insertions, 7 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 786755cb1ab..b29c26b4842 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -5260,7 +5260,6 @@ btr_validate_index( if (!btr_validate_level(index, trx, n - i, lockout)) { err = DB_CORRUPTION; - break; } } diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index aab4fbe5d8b..38796d8cb8d 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2476,6 +2476,7 @@ wrong_page_type: /* Validate the record list in a loop checking also that it is consistent with the directory. */ ulint count = 0, data_size = 0, own_count = 1, slot_no = 0; + ulint info_bits; slot_no = 0; slot = page_dir_get_nth_slot(page, slot_no); @@ -2499,9 +2500,16 @@ wrong_page_type: goto next_rec; } + info_bits = rec_get_info_bits(rec, page_is_comp(page)); + if (info_bits + & ~(REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) { + ib::error() << "info_bits has an incorrect value " + << info_bits; + ret = false; + } + if (rec == first_rec) { - if ((rec_get_info_bits(rec, page_is_comp(page)) - & REC_INFO_MIN_REC_FLAG)) { + if (info_bits & REC_INFO_MIN_REC_FLAG) { if (page_has_prev(page)) { ib::error() << "REC_INFO_MIN_REC_FLAG " "is set on non-left page"; @@ -2512,8 +2520,7 @@ wrong_page_type: ib::error() << "REC_INFO_MIN_REC_FLAG " "is set in a leaf-page record"; ret = false; - } else if (rec_get_deleted_flag( - rec, page_is_comp(page))) { + } else if (info_bits & REC_INFO_DELETED_FLAG) { /* If this were a 10.4 metadata record for index->table->instant we should not get here in 10.3, because @@ -2529,13 +2536,51 @@ wrong_page_type: ib::error() << "Metadata record is missing"; ret = false; } - } else if (rec_get_info_bits(rec, page_is_comp(page)) - & REC_INFO_MIN_REC_FLAG) { + } else if (info_bits & REC_INFO_MIN_REC_FLAG) { ib::error() << "REC_INFO_MIN_REC_FLAG record is not " "first in page"; ret = false; } + if (page_is_comp(page)) { + const rec_comp_status_t status = rec_get_status(rec); + if (status != REC_STATUS_ORDINARY + && status != REC_STATUS_NODE_PTR + && status != REC_STATUS_INFIMUM + && status != REC_STATUS_SUPREMUM + && status != REC_STATUS_COLUMNS_ADDED) { + ib::error() << "impossible record status " + << status; + ret = false; + } else if (page_rec_is_infimum(rec)) { + if (status != REC_STATUS_INFIMUM) { + ib::error() + << "infimum record has status " + << status; + ret = false; + } + } else if (page_rec_is_supremum(rec)) { + if (status != REC_STATUS_SUPREMUM) { + ib::error() << "supremum record has " + "status " + << status; + ret = false; + } + } else if (!page_is_leaf(page)) { + if (status != REC_STATUS_NODE_PTR) { + ib::error() << "node ptr record has " + "status " + << status; + ret = false; + } + } else if (!index->is_instant() + && status == REC_STATUS_COLUMNS_ADDED) { + ib::error() << "instantly added record in a " + "non-instant index"; + ret = false; + } + } + /* Check that the records are in the ascending order */ if (count >= PAGE_HEAP_NO_USER_LOW && !page_rec_is_supremum(rec)) { |